问题描述:
1 #include <stdio.h> 2 3 int main(void) 4 { 5 //program 6.3 Arrays of strings 6 char str2[3][10]; 7 8 for(int i=0;i<3;++i){ 9 for(int j = 0;j<10;j++){ 10 str2[i][j]='a'; 11 //printf("%p ", &str2[i][j]); 12 } 13 //printf("\n"); 14 } 15 16 for(int i=0;i<3;++i){ 17 for(int j = 0;j<12;j++){ // 索引 j->1218 printf("%c",str2[i][j] ); 19 //printf("%p ",&str2[i][j]); 20 } 21 printf("\n"); 22 } 23 return 0; 24 }
运行结果:
aaaaaaaaaaaa
aaaaaaaaaaaa
aaaaaaaaaaNULNUL
显然代码第18行数组索引越界(java:IndexOutOfBoundsException),但程序编译运行通过,且越界索引对应的数组值补为a和NULL。

如上图所示, &numbers[1][0] = &number[0][4] + sizeof(number) / strnlen_s( number, sizeof(str));
即number[1][0]的地址等于number[0][4]的地址加上数组number的类型所占字节数(如int占4字节)。
通过打印数组每个元素地址观察得出原因
1 #include <stdio.h> 2 3 int main(void) 4 { 5 //program 6.3 Arrays of strings 6 char str2[3][10]; 7 8 for(int i=0;i<3;++i){ 9 for(int j = 0;j<10;j++){ 10 str2[i][j]='a'; 11 } 12 } 13 14 for(int i=0;i<3;++i){ 15 for(int j = 0;j<12;j++){ 16 printf("%c",str2[i][j] ); 17 printf("%p ",&str2[i][j]); 18 } 19 printf("\n"); 20 } 21 return 0; 22 }
运行结果:
a0x7ffee509c710 a0x7ffee509c711 a0x7ffee509c712 a0x7ffee509c713 a0x7ffee509c714 a0x7ffee509c715 a0x7ffee509c716 a0x7ffee509c717 a0x7ffee509c718 a0x7ffee509c719 a0x7ffee509c71a a0x7ffee509c71b
a0x7ffee509c71a a0x7ffee509c71b a0x7ffee509c71c a0x7ffee509c71d a0x7ffee509c71e a0x7ffee509c71f a0x7ffee509c720 a0x7ffee509c721 a0x7ffee509c722 a0x7ffee509c723 a0x7ffee509c724 a0x7ffee509c725
a0x7ffee509c724 a0x7ffee509c725 a0x7ffee509c726 a0x7ffee509c727 a0x7ffee509c728 a0x7ffee509c729 a0x7ffee509c72a a0x7ffee509c72b a0x7ffee509c72c a0x7ffee509c72d NUL0x7ffee509c72e NUL0x7ffee509c72f
注意标注的两组彩色地址,想象中出现越界的str2[0][10]、str2[0][11]与str2[1][0]、str2[1][1]地址是一致的,故越界索引的数组值为a。即str2[0][10]==str2[1][0],str2[0][11]==str2[1][1]。
延伸
1 char str1[][10] = {"AAAAAAAAAA","BBBBBBBBB","CCCCCCCCCC","DDDDDDDDD"}; //10个A 2 char str2[][10] = {"AAAAAAAAAA","BBBBBBBBB","CCCCCCCCC","SSS"}; //9个A
编译报错 str1:initializer-string for array of chars is too long
C中的字符串总是由\0字符结束,所以字符串的长度永远比字符串中的字符数多1.
1 unsigned int count = 0; 2 while (str1[count]) 3 ++count;
'\0'字符的ASCII码是0,对应于布尔值false。其他ASCII码都不是0,对应布尔值true。因此,只要str1[count]不是'\0',循环就继续执行。
1 #include <stdio.h> 2 3 int main() 4 { 5 6 //program 6.3 Arrays of strings 7 //char str[][10] = {"AAAAAAAAAA","BBBBBBBBB","CCCCCCCCC","DDDDDDDDD"}; 8 //char str2[][10] = {"AAAAAAA","BBBBBBBB","CCCCCCCC","SSS"}; 9 char str2[3][10]; 10 11 for(int i=0;i<3;++i){ 12 for(int j = 0;j<10;j++){ 13 str2[i][j]='a'; 14 //printf("%p ", &str2[i][j]); 15 } 16 //printf("\n"); 17 } 18 19 for(int i=0;i<3;++i){ 20 for(int j = 0;j<10;j++){ 21 printf("%c",str2[i][j] ); 22 //printf("%p ",&str2[i][j]); 23 } 24 printf("\n"); 25 } 26 27 return 0; 28 }
输出结果:
1. aaaaaaaaaa
2. aaaaaaaaaa 3. aaaaaaaaaa
本文一开始使用测试程序使用for循环对数组对应索引进行赋值则没有使用'\0'做为结束标志,三个字符串间没有分隔标志,可以说它们并不是字符串而是单一的字符。
由于本人刚入门,文中不免有这样或者那样的错误,希望各位朋友们不吝赐教指正。
最后由于考研时间原因,列出此程序小弟还有的一处疑惑
1 #include <stdio.h> 2 3 int main() 4 { 5 char str2[3][10]; 6 7 for(int i=0;i<3;++i){ 8 for(int j = 0;j<10;j++){ 9 str2[i][j]='a'; 10 } 11 } 12 13 for(int i=0;i<3;++i){ 14 for(int j = 0;j<15;j++){ 15 printf("%c",str2[i][j] ); 16 //printf("%p ",&str2[i][j]); 17 } 18 printf("\n"); 19 } 20 return 0; 21 }
运行结果:
aaaaaaaaaaaaaaa
aaaaaaaaaaaaaaa
aaaaaaaaaaNULNUL`QR
红色标记的字符经多次编译发现其字符会变动
再次编译结果:
aaaaaaaaaaaaaaa
aaaaaaaaaaaaaaa
aaaaaaaaaaNULNULDLEȜ