假设我们有一个像这样的字符指针:
static char *example[]={"doctor","who","hello"};
我对这个例子中发生的事情感到有些困惑。
指针example
是否只有自己的地址?
我在数组中拥有的字符串的内存地址是否与*example
不同
和彼此?
指针example
是否只是简单地引用每个地址并初始化其中的内容
每个地址如字符串声明所示?
我只是在使用C几个月,所以我只是想抓住事情的细节,我听说指针是C中最重要的方面。
答案 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]);
总结一下:
char
的指针数组与第一个元素具有相同的地址。 char
),该字符串有自己的地址。 希望这很清楚。
答案 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
或一元&
运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字。