char names[][2] = {"abcdefg", "hijklmn", "qrstuv"};
printf("%c\n",*(*(names+0)+0));
printf("%s\n",names);
此代码中的最后一行打印abhiqr
。但是,改变" 2"将使程序从每个数组字符串(即abchijqrs
)打印 n 个字符。
为什么会这样?
另外,在中间行,我不明白为什么我有一个理论:我需要两个间接操作,因为名字实际上是指向其他指针(数组)的指针,第一个引用会让我 STILL 带指针?
我可以使用哪些资源详细了解C指针?
答案 0 :(得分:2)
这一行看起来不对:
char names[][2] = {"abcdefg", "hijklmn", "qrstuv"};
不应该是:
char names[][7+1] = {"abcdefg", "hijklmn", "qrstuv"};
原样(char names[][2]
),它将按如下方式初始化:
01?????
name[0] = "abcdefg";
^
Buffer overflow; name[1] points here...
01?????
name[1] = "hijklmn";
^
Buffer overflow; name[2] points here...
01????
name[2] = "qrstuv";
^
Buffer overflow; name[3] points here....
答案 1 :(得分:2)
你有两个问题,导致undefined behaviour。
1)如果大小为2
,则数组不能容纳大于两个字符长度的较大字符串文字。
2)您在第二次调用printf()
printf("%s\n",names);
使用%s
格式说明符,printf()
需要指向char(char *
)的指针。而你传递一个指向2个字符数组的指针(char (*)[2]
)。
由于修改字符串文字也是未定义的行为,因此您应该使用const
声明数组,以便不修改字符串文字。
虽然不同字符串文字的数量可能会有所不同,但如果声明了指针数组(每个指向字符串文字),则可以将其保留给编译器,这也有助于不用担心单个字符串文字的大小。 / p>
使用指针数组可以避免将字符串文字复制到数组中。所以你可以像这样声明指针数组:
const char *names[] = {"abcdefg", "hijklmn", "qrstuv"};
IMO,您应该阅读text book以全面了解指针,而不是在没有基础知识的情况下学习具体示例。
答案 2 :(得分:1)
关于中间线,它是这样的:
char *john = "john";
char *anna = "anna";
Memory:
(address 0:)|j|o|h|n|\0|
(address 5:)|a|n|n|a|\0|
a == 0; // The address
b == 5;
*a == 'j'; // The data in memory at address 0
*(a+1) == 'o'; // The data in memory at address 1
char names[][5] = {"john", "anna"};
Memory:
(address 0:)|1|3|8|
(address 3:)|j|o|h|n|\0|
(address 8:)|a|n|n|a|\0|
names == 1; // Address of pointer to the start of John's name
*names == 3; // Address of first letter to John's name
**names == 'j' // The data at address 3, which is John's name's first letter
希望这有帮助!