为什么printf会显示多个数组元素?

时间:2014-05-08 22:45:47

标签: c pointers

char names[][2] = {"abcdefg", "hijklmn", "qrstuv"};
printf("%c\n",*(*(names+0)+0));
printf("%s\n",names);

此代码中的最后一行打印abhiqr。但是,改变" 2"将使程序从每个数组字符串(即abchijqrs)打印 n 个字符。

为什么会这样?

另外,在中间行,我不明白为什么我有一个理论:我需要两个间接操作,因为名字实际上是指向其他指针(数组)的指针,第一个引用会让我 STILL 带指针?

我可以使用哪些资源详细了解C指针?

3 个答案:

答案 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

希望这有帮助!