引用字符变量时存储指针变量的地址在哪里?

时间:2013-09-02 21:13:25

标签: c pointers

假设我们有一个像这样的字符指针:

static char *example[]={"doctor","who","hello"};

我对这个例子中发生的事情感到有些困惑。

  1. 指针example是否只有自己的地址?

  2. 我在数组中拥有的字符串的内存地址是否与*example不同 和彼此?

  3. 指针example是否只是简单地引用每个地址并初始化其中的内容 每个地址如字符串声明所示?

  4. 我只是在使用C几个月,所以我只是想抓住事情的细节,我听说指针是C中最重要的方面。

4 个答案:

答案 0 :(得分:5)

  

变量example是否只拥有自己的地址?

是的,变量有自己的地址。

  

我在数组中的字符串是否都有一个与*example不同的内存地址    和彼此?

是的,每个字符串都有自己的地址,彼此不同。它也与变量example的地址不同。但是,表达式*example与变量example不同。见下一步。

  

指针示例是否只是简单地引用每个地址,并初始化每个地址中的内容,如字符串声明所示?

变量example引用字符串数组,意思是example其地址)是地址数组。

答案 1 :(得分:1)

static char* example[]example声明为指向char的指针数组。该数组初始化为三个字符串文字,因此example[0]"doctor"example[1]"who"example[2]"hello"

由于example是一个数组,因此数组标识符example将计算为数组第一个元素的地址。如果您尝试这样的事情:

printf ("%p %p %p\n", example, &example, &example[0]);

你会发现它们都具有相同的价值。但是,所有这些都是语义上不同的类型

example的类型为array of pointers to char

&example的类型为pointer to array of pointers to char

&example[0]的类型为pointer to pointer to char

数组的每个元素都有自己的地址。试试这个:

printf ("%p %p %p\n", &example[0], &example[1], &example[2]);

第一个将是与数组相同的地址,但其他地址将偏离该地址的系统指针的大小(对于32位系统通常为4个字节,对于64位为8个字节)系统)。

数组char中每个指针指向的example是字符串文字的第一个char。每个字符串文字都有自己的地址,可能在只读内存段中。你也可以试试这个:

printf ("%p %p\n", &example[0], example[0]); 

&example[0]是指向char的指针数组中第一个指针的地址。

example[0]是指针数组中的第一个指针。想想一组int。该数组的每个元素都有一个地址和一个值,后者是int。由于example是指针数组,example的每个元素都将具有地址和值,后者是指针

您可以重复&example[1]等练习

printf ("%p %p\n", &example[1], example[1]);
printf ("%p %p\n", &example[2], example[2]);

总结一下:

  1. 指向 char指针数组与第一个元素具有相同的地址。
  2. 每个后续元素,即阵列中的每个后续指针,都有自己的地址。
  3. 每个指针都指向一个字符串(第一个char),该字符串有自己的地址。
  4. 希望这很清楚。

答案 2 :(得分:0)

如果您声明

char *example[] = {"doctor","who","hello"};

你得到一个大小为3的数组,每个数组都有一个char *指针。它与

相同
char *example[3] = {"doctor","who","hello"};

但是,我们真的需要看看如何在代码中声明示例来回答。

答案 3 :(得分:0)

图片可能有所帮助。以下内容并不代表任何特定的体系结构 - 所有地址值都是凭空而来的。


Item          Address            0x00  0x01  0x02  0x03
----          -------            ----  ----  ----  ----
              0x00004000          'd'   'o'   'c'   't'
              0x00004004          'o'   'r'  0x00   'w'
              0x00004008          'h'   'o'  0x00   'h'
              0x0000400c          'e'   'l'   'l'   'o'
              0x00004010         0x00    ??    ??    ??
...           ...                ...
example:      0x80001000         0x00  0x00  0x40  0x00
              0x80001004         0x00  0x00  0x40  0x07
              0x80001008         0x00  0x00  0x40  0x0b

字符串文字"doctor""who""hello"都以这样的方式存储,即在程序的生命周期内分配它们(它们具有静态存储持续时间) ),它们可以存储在只读数据段 1 中。

字符串文字"doctor"存储在地址0x00004000"who"存储在地址0x00004007"hello"存储在地址0x0000400b }。

数组example凭借static关键字也具有静态存储持续时间,但实际上可能存储在与字符串文字不同的内存区域中。数组从地址0x80001000开始,每个元素占用四个字节,因此&example[0] == 0x80001000&example[1] == 0x80001004&example[2] == 0x80001008

请注意,名为example的变量没有单独的存储位置,指向数组的第一个元素。在C中,第一个元素的地址与数组本身的地址相同。 这很重要,是C语言中最常被误解的方面之一。数组不是指针;相反,在大多数情况下,数组表达式将转换(“衰减”)为指针表达式 2 ,表达式的值将是第一个元素的地址。如果你真的感兴趣,那么Dennis Ritchie在this paper中概述了这种行为的原因。向下滚动到“胚胎C”部分进行说明。

example[0]中存储的值是字符串文字"doctor"的地址。同样,example[1]存储字符串文字"who"的地址,example[3]存储字符串文字"hello"的地址。

<小时/> 1。因此,尝试修改字符串文字内容的行为是 undefined - 它可能按预期工作,可能会崩溃,或者可能无法完全编译。编译器不需要以任何特定方式处理该情况,因此不同编译器之间的行为会有所不同。您永远不应该尝试修改字符串文字的内容。

2。此规则的例外情况是,数组表达式是sizeof或一元&运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字。