多文件C程序中,有使用extern来导入其他文件的符号。在两个文件中extern的符号类型不一,会有什么后果。看以下例子:
文件t1.c:
-
int a[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
-
int *p = a;
-
-
int show()
-
{
-
printf("a = %p p = %p &p = %p \n",a,p,&p);
-
return 0;
-
}
文件t2.c:
-
#include <stdio.h>
-
-
extern int *a;
-
extern int p[];
-
-
int main()
-
{
-
int x = 0;
-
int y = 0;
-
-
show();
-
printf("a = %p p = %p &a = %p &p = %p p[0] = 0x%x\n",a,p,&a,&p,p[0]);
-
x = a[3];
-
y = p[3];
-
-
printf("x = %d y = %d \n",x,y);
-
return 0;
-
}
可以看到t1.c和t2.c中的符号a和p的类型是不一样的。再编译和运行
-
$gcc -g -Wall *.c
-
$./a.out
-
a = 0x8049760 p = 0x8049760 &p = 0x80497a0
-
a = (nil) p = 0x80497a0 &a = 0x8049760 &p = 0x80497a0 p[0] = 0x8049760
-
Segmentation fault (core dumped)
在运行期core dump了。可以看到在t2.c中导入的符号与t1.c中的符号好想不一致哦。
而且看出main.a是NULL,就找到了core dump的原因(t2.c:13)。
经过分析可以看出show.a,show.p,main.&a,main.p[0]是一样的,show.&p,main.&p是一样的。
再进一步分析:
show.a和show.p一致是因为在t1.c中a为数组,也就是所谓的常量指针。然后用a给p赋值,
所以,show.a和show.p一致。
那么为什么show.a和main.&a是一样的呢?
如果&a理解为是t1.c的a的地址,那么就很好理解main中的a为什么是NULL了。show.a的第一个元素
的值为0。那么作为指针的main.a的值为0,所以,就变成0了。
试试这样的代码:
-
int **p = (int *)a;
-
printf("p = %p \n",*p);
其实,show.a就相当于a,main.a就相当于*p。
所以,show.a和main.a的地址是同一个,show.p和main.p的地址也是一样的。所以,在一个文件中导入其他文件的符号,其实符号的地址是一样的。不用管是什么类型。
在t1.c中a为数组,在t2.c中a为指针。那么两个a的地址是一样的。对指针a的值就是数组a的第一个值,而数组a的值为0。所以,在32位系统上指针a的值就变成NULL了。
所以,在t1.c中的p是指针,在t2.c中p是数组。应用上一个结论,指针p的地址与数组p的地址是一个。那么y的值就是p地址后的第四个整数。
最终的结论就是,导入符号的时候,导入的符号与原符号地址相同。
那么,以下代码的结果是什么?
-
a = &a;
-
for(int i = 0; i < 16; i++){
-
printf("0x%x ",a[i]);
-
}
-
printf("\n");
请先不要编译运行,先想想结果是什么,然后在运行去验证。
阅读(2925) | 评论(0) | 转发(1) |