我知道这个话题已经解决了几次,但我仍然没有得到它。
参考http://c-faq.com/aryptr/aryptr2.html
char a[] = "hello";
char *p = "world";
创建一个数组" a"。该变量只是第一个内存地址的标签。 p是一个变量(==另一个内存地址的标签),包含第一个字符的地址(w - 可能是内存中的其他位置)。
我不明白的是这个主题的例子(谢谢!): using extern to link array with pointer:
extern1.c
extern int *array;
int test();
int main(int argc, char *argv[])
{
printf ("in main: array address = %x\n", array);
test();
return 0;
}
extern2.c
int array[10] = {1, 2, 3};
int test()
{
printf ("in test: array address = %x\n", array);
return 0;
}
为什么指针变量" extern int * array" extern1中的(==内存地址标签,包含其他地址)已包含数组[0]的内容?
有什么区别
int array[10] = {1, 2, 3};
int *ptrArrWorking = array; // == &array[0];
? 在外部情况下,它将类似于
int array[10] = {1, 2, 3};
int *ptrArrNotWorking = array[0];
编辑:为了更明确,让我们将上面的例子解释为
int array[10] = {1, 2, 3};
int *ptrArrNotWorking = (int *)array[0];
所以这模拟了在extern示例中可以看到的相同行为。
隐藏间接在哪里?
非常感谢你。
答案 0 :(得分:5)
您已在array
中定义了一个名为int array[10] = {1, 2, 3};
的对象:
int
这是一个包含10个printf
s的连续内存段。将它传递给test
中的printf
后,它会衰减成指向其第一个元素的指针 - 这就是数组传递给函数的方式。因此,int
会打印第一个extern1.c
的地址。
然而,在array
中,您再次声明extern int *array;
时撒了谎:
array
这假装array
是一个指针,一个保存其他东西地址的对象。这种不匹配使程序“形成不良,无需诊断”。这是“严重破坏”的标准 - 从那时起,对程序是否编译或在运行时实际执行的操作没有要求。
实际上,破坏声明后面的代码确实会将array
视为指针。所以当你将printf
传递给printf
时,它会从数组的开头切掉一些字节(通常是4或8,具体取决于你的平台),大喊“你去,这里是指针“并将其交给int
。
当然,它实际上并不是一个有效的指针,但是来自array
的前几个NodeParentID
的位被塞在一起,所以你看到的是无意义的。
答案 1 :(得分:0)
仅使用extern
declares a variable, but not defines it。
实际上这意味着array
变量(在 extern1.c 中声明为extern
)只是array的别名> extern2.c
答案 2 :(得分:0)
创建一个数组" a"。该变量只是第一个内存地址的标签。
不,a
是整个数组hello\0
。每当在表达式中使用标识符a
时,数组"衰变"到指向其第一个元素的指针。也就是说,在使用a
的表达式中,您将获得指向char*
字母的临时'h'
。
想象一下:阵列是前往罗马的道路。你问编译器"通往罗马的路在哪里,我需要访问它"然后它会为你提供一个临时的路标。这并不意味着通往罗马的道路成为路标。这也不意味着道路标志本身就是通往罗马的道路。同样地,通往罗马的道路并不仅仅因为你在驾驶它(访问它)而成为路标。
为什么指针变量" extern int * array" extern1中的(==内存地址标签,包含其他地址)已包含数组[0]的内容?
没有。你不能写extern int* array
并期望获得指向其他地方分配的数组int array[10]
中第一项的指针。因为数组不是指针而指针不是数组。
反汇编示例中发生的事情是代码调用未定义的行为(错误),程序员在这里对编译器说,"这里存储的内容实际上是指针,相信我&#34 ;即使那里没有指针,但整数。
因为它发生在该特定系统上,您将指针的地址设置为1
。不是尖锐的数据。这是你无法依靠的;如果指针和整数在给定系统上具有不同的大小或表示,代码也可能崩溃。
要使用关于道路的类比,您的编译器是驱动程序,CPU的程序计数器是汽车。使用extern int *array
,你告诉编译器"那边有一个路标!",指的是实际道路。编辑然后盲目地做你告诉它的事情,并试图从沥青中解释出一些方向,然后让汽车跟随它,然后它跑到旷野,可能会崩溃,而且肯定永远不会到达罗马。
下面:
int array[10] = {1, 2, 3};
int *ptrArrWorking = array; // == &array[0];
将指针设置为指向数组中的第一项。这意味着指针将获取该项存储位置的内存地址。您不会将地址本身设置为1,这在大多数系统上很可能都是无意义的。
在外部情况下,它会像
int array[10] = {1, 2, 3};
int *ptrArrNotWorking = array[0];
确切地说,这是没有任何意义的代码。它实际上甚至不是有效的C,因为你不能在不首先执行转换的情况下为指针分配整数 - 这可以通过类型转换完成。