指向变量与数组的外部指针

时间:2017-04-25 11:59:43

标签: c arrays pointers extern

我知道这个话题已经解决了几次,但我仍然没有得到它。

参考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示例中可以看到的相同行为。

隐藏间接在哪里?

非常感谢你。

3 个答案:

答案 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,因为你不能在不首先执行转换的情况下为指针分配整数 - 这可以通过类型转换完成。