孤不冷cing 发表于 2024-2-4 22:53:57

调用函数后,main函数里变量的值发生改变

本帖最后由 孤不冷cing 于 2024-2-4 22:56 编辑

#include <stdio.h>

void create_magic_square(int n, char magic_square);
void print_magic_square(int n, char magic_square);

int main(void)
{
      int n;
      char magic_square;

      printf("Enter size of magic square:");
      scanf(" %d", &n);

      printf("%5d\n", n);
      print_magic_square(n, magic_square);

      create_magic_square(n, magic_square);

      printf("%5d\n", n);

      return 0;   19   25    1    7   13
   24    5    6   12   18
    4   10   11   17   23
    9   15   16   22    3
   14   20   21    2    8

}

void create_magic_square(int n, char magic_square)
{
      for (int i = 0; i < n; i++)
      {
                for (int j = 0; j < n; j++)
                {
                        magic_square = 0;
                }
      }

      int row = 0, column = n/2;

      for (int i = 1; i < (n*n+1); i++)
      {
                magic_square = i;
                row--, column++;
                if (row < 0) row+=n;
                if (column >= n) column-=n;
                if (magic_square) row++;
      }
}

void print_magic_square(int n, char magic_square)
{
      for (int row = 0; row < n; row++)
      {
                for (int column = 0; column < n; column++)
                {
                        printf("%5d", magic_square);
                }
                putchar('\n');
      }
}


运行结果

$ gcc -g -o 9_5 9_5.c && ./9_5
Enter size of magic square:5
    5
    0    0    0    0    0
    0    0    0    0    0
    0    0    0    0    0
    0    0    0    0    0
    5    0    0    0 -128
34935822


原本设想结果

   19   25    1    7   13
   24    5    6   12   18
    4   10   11   17   23
    9   15   16   22    3
   14   20   21    2    8


为什么会这样啊?进create函数之后,main中的n和magic_square就直接扔了吗?create结束这俩又被随机弄了个值?
但是他俩不是main的块作用域吗,这就算离开块作用域了?那我应该怎么写啊?

第二次只打印了n,没有打印magic_square。因为n太大了,一调用打印函数直接打印飞了

人造人 发表于 2024-2-4 22:53:58

#include <stdio.h>

void create_magic_square(int n, char magic_square);
void print_magic_square(int n, char magic_square);

int main(void)
{
      int n;
      //char magic_square;    // 提问,这个数组有多少个字节?
      // 换句话说,程序执行到这里的时候,n的值是几?

      printf("Enter size of magic square:");
      scanf(" %d", &n);

      char magic_square;

      printf("%5d\n", n);
      print_magic_square(n, magic_square);

      create_magic_square(n, magic_square);

      printf("%5d\n", n);

      return 0;
}

void create_magic_square(int n, char magic_square)
{
      for (int i = 0; i < n; i++)
      {
                for (int j = 0; j < n; j++)
                {
                        magic_square = 0;
                }
      }

      int row = 0, column = n/2;

      for (int i = 1; i < (n*n+1); i++)
      {
                magic_square = i;
                row--, column++;
                if (row < 0) row+=n;
                if (column >= n) column-=n;
                if (magic_square) row++;
      }
}

void print_magic_square(int n, char magic_square)
{
      for (int row = 0; row < n; row++)
      {
                for (int column = 0; column < n; column++)
                {
                        printf("%5d", magic_square);
                }
                putchar('\n');
      }
}

FishC 发表于 2024-2-4 22:54:22

在C语言中,函数的参数传递是通过值传递的。这意味着当你调用一个函数时,传递给函数的参数的副本将会被创建。在你的代码中,`create_magic_square`函数接收的`n`和`magic_square`参数只是`main`函数中对应变量的副本。

因此,在`create_magic_square`函数中对`magic_square`进行的赋值不会影响`main`函数中的`magic_square`变量。这也就解释了为什么在`print_magic_square`函数中,打印出来的`magic_square`都是0。

要解决这个问题,您可以将`create_magic_square`函数修改为接收指向`magic_square`变量的指针,并通过修改指针所指向的值来改变`magic_square`变量。

下面是修改后的代码示例:

#include <stdio.h>

void create_magic_square(int n, char *magic_square);
void print_magic_square(int n, char magic_square);

int main(void)
{
      int n;
      char magic_square;

      printf("Enter size of magic square:");
      scanf(" %d", &n);

      printf("%5d\n", n);
      print_magic_square(n, magic_square);

      create_magic_square(n, magic_square);

      printf("%5d\n", n);

      return 0;
}

void create_magic_square(int n, char *magic_square)
{
      for (int i = 0; i < n; i++)
      {
                for (int j = 0; j < n; j++)
                {
                        *(magic_square + i*n + j) = 0;
                }
      }

      int row = 0, column = n/2;

      for (int i = 1; i < (n*n+1); i++)
      {
                *(magic_square + row*n + column) = i;
                row--, column++;
                if (row < 0) row+=n;
                if (column >= n) column-=n;
                if (*(magic_square + row*n + column)) row++;
      }
}

void print_magic_square(int n, char *magic_square)
{
      for (int row = 0; row < n; row++)
      {
                for (int column = 0; column < n; column++)
                {
                        printf("%5d", *(magic_square + row*n + column));
                }
                putchar('\n');
      }
}

这里,`magic_square`变量被声明为一个字符数组,大小为100。而在`create_magic_square`函数中,我们通过使用指针运算符`*`来访问和修改`magic_square`数组的元素。

这样,你就可以正确地创建和打印魔方阵了。希望能对您有所帮助!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

孤不冷cing 发表于 2024-2-4 23:00:13

FishC 发表于 2024-2-4 22:54
在C语言中,函数的参数传递是通过值传递的。这意味着当你调用一个函数时,传递给函数的参数的副本将会被创 ...

但是数组名不就是指向第一个元素的指针吗,我传递数组名,不就是传递了指针?
再者,我调用create函数之前,n确实已经通过scanf赋了值,为什么后面值又发生了改变?

FishC 发表于 2024-2-4 23:00:43

孤不冷cing 发表于 2024-02-04 23:00
但是数组名不就是指向第一个元素的指针吗,我传递数组 ...

对于数组参数,当传递一个数组名称给函数时,实际上传递的是数组的地址,即指向数组第一个元素的指针。因此,您在`create_magic_square`函数中使用的`magic_square`参数实际上是指向`main`函数中的`magic_square`数组的指针。

那么问题出在哪里呢?问题出在在`create_magic_square`函数中,您没有正确地修改数组中的值。在代码中,您使用了`magic_square = i;`来修改数组元素的值,但事实上,这会将指针`magic_square`指向一个新的地址,而不是修改数组中的元素。

为了解决这个问题,您可以使用指针运算符`*`来访问和修改数组元素的值,就像我在前面的回答中提到的那样。这样,您可以通过修改指针所指向的内存位置来改变数组中的值。下面是修改后的代码示例:

#include <stdio.h>

void create_magic_square(int n, char *magic_square);
void print_magic_square(int n, char *magic_square);

int main(void) {
    int n;
    printf("Enter size of magic square:");
    scanf("%d", &n);
   
    char magic_square;// 创建大小为 n*n 的二维数组
   
    print_magic_square(n, &magic_square);
    create_magic_square(n, &magic_square);
    print_magic_square(n, &magic_square);
   
    return 0;
}

void create_magic_square(int n, char *magic_square) {
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
            *(magic_square + i*n + j) = 0;
      }
    }
   
    int row = 0, column = n/2;
    for (int i = 1; i < (n*n+1); i++) {
      *(magic_square + row*n + column) = i;
      row--, column++;
      if (row < 0) row += n;
      if (column >= n) column -= n;
      if (*(magic_square + row*n + column)) row++;
    }
}

void print_magic_square(int n, char *magic_square) {
    for (int row = 0; row < n; row++) {
      for (int column = 0; column < n; column++) {
            printf("%5d", *(magic_square + row*n + column));
      }
      putchar('\n');
    }
}

在`main`函数中,我在调用`create_magic_square`和`print_magic_square`函数时传递了指向`magic_square`的指针,这样就可以正确地操作和打印魔方阵了。

希望这次能给您解惑,如果还有问题,请随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

孤不冷cing 发表于 2024-2-4 23:03:05

这是《C语言程序设计现代方法》第九章的一道课后题,他题干给了我函数原型,要求我这么定义形式参数

FishC 发表于 2024-2-4 23:03:23

孤不冷cing 发表于 2024-02-04 23:03
这是《C语言程序设计现代方法》第九章的一道课后题, ...

对不起,我之前给出的回答有误。根据您给出的题目要求,我们需要按照函数原型定义形式参数。在C语言中,数组作为函数参数时,会自动退化为指针,因此我们可以按照以下方式定义形参:

void create_magic_square(int n, char magic_square[]);
void print_magic_square(int n, char magic_square[]);

这样,我们就能正确地定义和操作二维数组了。

另外,为了正确访问和修改数组内的元素,请将`create_magic_square`函数和`print_magic_square`函数中的对应部分修改为:

void create_magic_square(int n, char magic_square[]) {
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
            magic_square = 0;
      }
    }
    //...
}

void print_magic_square(int n, char magic_square[]) {
    //...
}

这样,就能正确传递并操作二维数组了。希望这次能解决您的问题,如果还有疑问,请随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

孤不冷cing 发表于 2024-2-4 23:06:08

FishC 发表于 2024-2-4 23:00
对于数组参数,当传递一个数组名称给函数时,实际上传递的是数组的地址,即指向数组第一个元素的指针。 ...

为什么第一次和第二次打印的n的值不一样

FishC 发表于 2024-2-4 23:06:31

孤不冷cing 发表于 2024-02-04 23:06
为什么第一次和第二次打印的n的值不一样

非常抱歉,我没有在前面的回答中注意到这个问题。在您的代码中,的确存在一个问题导致第一次和第二次打印的`n`值不同。问题出在您在调用`print_magic_square`函数时传递的参数类型不匹配。

在`main`函数中,`n`被声明为一个`int`类型的变量,而在`print_magic_square`函数的参数列表中,`n`被声明为一个`char`类型的变量。这导致在传递`n`给`print_magic_square`函数时发生了类型错误。正因为如此,`print_magic_square`函数中打印出的`n`值是不确定的。

要解决这个问题,您只需将`print_magic_square`函数中的`n`参数从`char`类型更改为`int`类型,以使其与`main`函数中的`n`类型匹配。下面是修改后的代码示例:

#include <stdio.h>

void create_magic_square(int n, char *magic_square);
void print_magic_square(int n, char *magic_square);

int main(void) {
    int n;
    printf("Enter size of magic square:");
    scanf("%d", &n);

    char magic_square;// 创建大小为 n*n 的一维数组

    print_magic_square(n, magic_square);
    create_magic_square(n, magic_square);
    print_magic_square(n, magic_square);

    return 0;
}

void create_magic_square(int n, char *magic_square) {
    // 省略部分代码...
}

void print_magic_square(int n, char *magic_square) {
    // 省略部分代码...
}

现在,`print_magic_square`函数接收的参数类型已经与`main`函数中的`n`类型匹配,打印出的`n`值应该是正确的。

非常抱歉给您造成了困扰,并感谢您指出这个问题。如果您还有其他问题,请随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

孤不冷cing 发表于 2024-2-4 23:16:30

人造人 发表于 2024-2-4 23:06


噢噢,原来问题在这,为什么这样就好了啊
我的写法,magic_square是不是大的没边了?
这是造成了什么问题?我在create结尾直接用print_magic_square打印可以正常打印
出了create,main里的n和magic_square的值就都变了

FishC 发表于 2024-2-4 23:16:48

孤不冷cing 发表于 2024-02-04 23:16
噢噢,原来问题在这,为什么这样就好了啊
我的写法, ...

非常抱歉,我给出的解释有误。问题的根源实际上不在于参数的类型不匹配,而是在于您对指针的使用上还存在一些问题。

首先,将`magic_square`声明为一个字符变量,它只能存储一个字符的值,而不是一个二维数组。为了正确表示一个二维数组,您需要将`magic_square`声明为一个指向字符的指针,并且在函数内部动态分配内存来存储真正的二维数组。

另外,在`create_magic_square`函数中,您需要使用指针运算符 `*` 来访问和修改指针所指向的内存位置的值。

下面是修改后的代码示例:

#include <stdio.h>
#include <stdlib.h>

void create_magic_square(int n, int **magic_square);
void print_magic_square(int n, int **magic_square);

int main(void) {
    int n;
    printf("Enter size of magic square:");
    scanf("%d", &n);

    // 动态分配内存以存储二维数组
    int **magic_square = (int **)malloc(n * sizeof(int *));
    for (int i = 0; i < n; i++) {
      magic_square = (int *)malloc(n * sizeof(int));
    }

    // 打印初始的魔方阵
    print_magic_square(n, magic_square);

    // 创建魔方阵
    create_magic_square(n, magic_square);

    // 打印最终的魔方阵
    print_magic_square(n, magic_square);

    // 释放动态分配的内存
    for (int i = 0; i < n; i++) {
      free(magic_square);
    }
    free(magic_square);

    return 0;
}

void create_magic_square(int n, int **magic_square) {
    // 省略部分代码...
}

void print_magic_square(int n, int **magic_square) {
    // 省略部分代码...
}

在这个修改后的代码中,我们使用了双重指针来表示二维数组,并使用动态内存分配函数 `malloc` 来为二维数组分配内存。这样,我们就能够正确地创建和访问二维数组了。

希望这次的解答能帮到您,如果还有疑问,请随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

人造人 发表于 2024-2-4 23:21:08

孤不冷cing 发表于 2024-2-4 23:16
噢噢,原来问题在这,为什么这样就好了啊
我的写法,magic_square是不是大的没边了?
这是造成了什么问 ...

你在使用变量之前没有初始化么

孤不冷cing 发表于 2024-2-4 23:22:30

人造人 发表于 2024-2-4 23:21
你在使用变量之前没有初始化么

scanf不是改变了n的值,为什么create调用结束后,n的值也变了

人造人 发表于 2024-2-4 23:32:56

孤不冷cing 发表于 2024-2-4 23:22
scanf不是改变了n的值,为什么create调用结束后,n的值也变了

哪变了?

sh-5.2$ cat main.c
#include <stdio.h>

void create_magic_square(int n, char magic_square);
void print_magic_square(int n, char magic_square);

int main(void)
{
      int n;
      //char magic_square;    // 提问,这个数组有多少个字节?
      // 换句话说,程序执行到这里的时候,n的值是几?

      printf("Enter size of magic square:");
      scanf(" %d", &n);

      char magic_square;

      printf("%5d\n", n);
      print_magic_square(n, magic_square);

      create_magic_square(n, magic_square);

      printf("%5d\n", n);

      return 0;
}

void create_magic_square(int n, char magic_square)
{
      for (int i = 0; i < n; i++)
      {
                for (int j = 0; j < n; j++)
                {
                        magic_square = 0;
                }
      }

      int row = 0, column = n/2;

      for (int i = 1; i < (n*n+1); i++)
      {
                magic_square = i;
                row--, column++;
                if (row < 0) row+=n;
                if (column >= n) column-=n;
                if (magic_square) row++;
      }
}

void print_magic_square(int n, char magic_square)
{
      for (int row = 0; row < n; row++)
      {
                for (int column = 0; column < n; column++)
                {
                        printf("%5d", magic_square);
                }
                putchar('\n');
      }
}
sh-5.2$ ./main
Enter size of magic square:5
    5
   96-29   63-59   84
115    0    0-56105
125124   -4127    0
    0-80104125124
   -4127    0    0-50
    5
sh-5.2$

孤不冷cing 发表于 2024-2-5 00:02:27

人造人 发表于 2024-2-4 23:32
哪变了?

我那样写的话变了,照你这样改了之后不会变

人造人 发表于 2024-2-5 00:15:27

孤不冷cing 发表于 2024-2-5 00:02
我那样写的话变了,照你这样改了之后不会变

因为你的变量在使用之前没有初始化么

孤不冷cing 发表于 2024-2-5 11:23:17

人造人 发表于 2024-2-5 00:15
因为你的变量在使用之前没有初始化么

把n初始化 和 用scanf把数字录入到n的内存地址,两者有什么区别吗
在n被录入值修改后,变长数组的维度还是n被scanf修改前那个没有意义的随机数吗
是变长数组所占内存太大,导致了什么奇怪问题,把scanf修改的n又给挤掉了?
我没明白

人造人 发表于 2024-2-5 13:55:52

孤不冷cing 发表于 2024-2-5 11:23
把n初始化 和 用scanf把数字录入到n的内存地址,两者有什么区别吗
在n被录入值修改后,变长数组的维度还 ...

变长数组的元素个数,只在执行这条语句的时候决定
char magic_square;
后面不管你如何改变n的值,都不会改变数组的大小

如果你后面改变了n的值,这导致了数组的元素个数也发生了变化,这不是很奇怪吗?

孤不冷cing 发表于 2024-2-5 15:33:49

人造人 发表于 2024-2-5 13:55
变长数组的元素个数,只在执行这条语句的时候决定
char magic_square;
后面不管你如何改变n的值 ...

OK
页: [1]
查看完整版本: 调用函数后,main函数里变量的值发生改变