2 xuayin6083105 xuayin6083105 于 2014.12.03 01:09 提问

代码放在主函数没问题,拿出来放到子函数就出错,

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include

int **a = NULL;

int *find_a(int **a)
{
int data;
printf("input find number:\n");
scanf("%d", &data);
int i = 0,j;
for (i = 0; i < 10; i++)
{
for (j = 0; j < 8; j++)
{
if (a[i][j] == data)
{
return &a[i][j];
}
}
}
return NULL;
}

void create_a(int **a)
{

}

void pint_a(int **a)
{
int i, j;

}

int main(void)
{
create_a(a);
a = (int **)calloc(10, sizeof(int*));
int i, j;
for (i = 0; i < 10; i++)
{
a[i] = calloc(8, sizeof(int));
}
srand((unsigned int)time(NULL));
for (i = 0; i < 10; i++)
{
for (j = 0; j < 8; j++)
{
a[i][j] = rand() % 100;
}
}
for (i = 0; i < 10; i++)
{
for (j = 0; j < 8; j++)
{
printf("%d\t", ((a + i) + j));
}
printf("\n");
}
if (find_a(a) == NULL)
printf("not find data \n");
else
printf("find data %d\n", find_a(a));

system("pause");
return 0;

}
这是放在主函数中的,运行正确,

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include

int **a = NULL;

int *find_a(int **a)
{
int data;
printf("input find number:\n");
scanf("%d", &data);
int i = 0,j;
for (i = 0; i < 10; i++)
{
for (j = 0; j < 8; j++)
{
if (a[i][j] == data)
{
return &a[i][j];
}
}
}
return NULL;
}

void create_a(int **a)
{
a = (int **)calloc(10, sizeof(int*));
int i, j;
for (i = 0; i < 10; i++)
{
a[i] = calloc(8, sizeof(int));
}
srand((unsigned int)time(NULL));
for (i = 0; i < 10; i++)
{
for (j = 0; j < 8; j++)
{
a[i][j] = rand() % 100;
}
}
}

void pint_a(int **a)
{
int i, j;
for (i = 0; i < 10; i++)
{
for (j = 0; j < 8; j++)
{
printf("%d\t", ((a + i) + j));
}
printf("\n");
}
}

int main(void)
{
create_a(a);
pint_a(a);
if (find_a(a) == NULL)
printf("not find data \n");
else
printf("find data %d\n", find_a(a));

system("pause");
return 0;

}

这是拿出来后的样子

运行出错,结果提示:0x013D16E4 处有未经处理的异常(在 1201考试题07.exe 中): 0xC0000005: 读取位置 0x00000000 时发生访问冲突。

并指向这句:printf("%d\t", ((a + i) + j));

2个回答

caozhy
caozhy   Ds   Rxr 2014.12.03 02:48
已采纳

无论如何,你这种写法很不好,你有一个全局变量叫a,为什么你函数的形参也叫a呢?
更糟糕的是,C++允许你定义这种重名的变量,可是不幸的是,它在函数内部,将你写的a视作的是参数a,而不是全局变量a

因为C++语言规定,当你这么写的时候,使用的是可见性范围内的,作用域范围最小的变量。

此时你要访问全局变量的a,需要写成 ::a 才行。

当然,非常非常不建议你这么写,事实上,我认为C++允许这种冲突为合法代码完全是一个非常糟糕的事情,可能是历史遗留问题造成的,你实际开发中应该避免这样的冲突。当然你仅仅为了观察这个情况而编写测试的代码除外。

eagleyan
eagleyan 回复xuayin6083105: 顺便说一句,这个问题我曾经面试的时候问倒了十几个人。 :-D
3 年多之前 回复
eagleyan
eagleyan 回复xuayin6083105: 顺便说一句,这个问题我曾经面试的时候问倒了十几个人。 :-D
3 年多之前 回复
eagleyan
eagleyan 回复xuayin6083105: 我个人觉得这是好的经历,让你明白了全局变量和局部变量的差异;另外,这里有一个陷阱就是什么样的值传进去会被修改,指针和引用(c++的类型)的内容会被修改,而指针重新赋值不会改变原来指针的值。(引用的值不能被改变)
3 年多之前 回复
xuayin6083105
xuayin6083105 谢谢,瞬间懂了,一直习惯在子函数中用重名的变量,觉得方便自己阅读,结果出的都是这样的错,被坑了好久
3 年多之前 回复
eagleyan
eagleyan   Rxr 2014.12.03 02:11

这里你没有真正理解参数传递的方式,函数传递参数,实际上是把值直接copy进去,无论是地址,还是变量。那传地址的话,你可以改变里面的值,但是改变该地址是没有用的。你这里把一个为空的指针a传到函数里,你重新给a复制,他并没有改变全局变量a的值。(实际上是改变了局部变量a的值,由于你的参数和全局变量取了一个名字,在函数里操作的是局部变量而不是全局的a)。
你可以很简单的修改一下你的函数,把输入参数改成b(create_a和print_b都改成int **b)这个时候就不会覆盖全局变量a的值,你的程序就会得到一样的结果了。

xuayin6083105
xuayin6083105 嗯,就是局部变量惹的祸,但是主观里当成全局变量了,一直找不到错哪儿,被坑了好多天了
3 年多之前 回复
xuayin6083105
xuayin6083105 嗯,就是局部变量惹的祸,但是主观里当成全局变量了,一直找不到错哪儿,被坑了好多天了
3 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!