問題描述:
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Ȝ
