我在C中有以下代码:
int main(){
int array[] = {1,2,3,3,4,5,6,7,8};
printf("%d\n", array[8]);
printf("%d\n", array[9]);
}
当我执行它时,我得到的结果是8和32767.我很困惑为什么。
更新
对3,3事感到抱歉。 让我困惑的是数字32767,如果它是一个未定义的行为,为什么它总是32767?我发现了一件令人讨厌的事情:int main(){
int arrayB[] = {7,4,3,4,1};
for(int i = 0; *(arrayB+i); i++){
printf("%d\n",*(arrayB+i) );
}
}
我写了这个,而32767号又出现了。和令人毛骨悚然的部分是如果我将数组更改为任何其他长度(删除或添加数字),它工作得很好!
答案 0 :(得分:7)
你得到了未定义的行为。
你不能打印9元素arrray的第10个元素,这是无效的代码。
8
只获得array[8]
,因为初始化列表中有3
两次。
你的数组在内存中看起来像这样:
+---+---+---+---+---+---+---+---+---+
index: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
+---+---+---+---+---+---+---+---+---+
data: | 1 | 2 | 3 | 3 | 4 | 5 | 6 | 7 | 8 |
+---+---+---+---+---+---+---+---+---+
因此,您可以看到array[8]
处的数据实际上是8,但这是数组中的最后一个元素。如果使用大于8
的索引进行索引,则会得到未定义的行为。
答案 1 :(得分:1)
该数组有9个有效位,但您必须考虑它们在C中以0开始编入索引。
所以如果你想要第一个值:array [0];
如果你想要最后一个值:array [8];
array [9]不是有效位置。
希望有所帮助。
答案 2 :(得分:1)
在C中,未初始化的变量得到垃圾值,这种情况发生在你的情况下,因为没有定义数组[9],因为C中的索引从0开始而不是1。
答案 3 :(得分:1)
在C中,数组元素从零到长度减一。如果你使用GCC编译器,你可以添加选项-fsanitize=address
来检测这样的一对一错误。
来源:
$ cat test.c
#include <stdio.h>
int main(void)
{
int array[] = {1, 2, 3, 3, 4, 5, 6, 7, 8};
printf("%d\n", array[8]);
printf("%d\n", array[9]);
return 0;
}
编译命令:
$ gcc -ansi -g -pedantic -Wall -fsanitize=address -o test test.c
输出:
$ ./test
8
=================================================================
==4517== ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff70a43794 at pc 0x400b2b bp 0x7fff70a43740 sp 0x7fff70a43738
READ of size 4 at 0x7fff70a43794 thread T0
#0 0x400b2a (/tmp/test+0x400b2a)
#1 0x7f1ff1180ec4 (/lib/x86_64-linux-gnu/libc-2.19.so+0x21ec4)
#2 0x400788 (/tmp/test+0x400788)
Address 0x7fff70a43794 is located at offset 68 in frame <main> of T0's stack:
This frame has 1 object(s):
[32, 68) 'array'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
Shadow bytes around the buggy address:
0x10006e1406a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006e1406b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006e1406c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006e1406d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006e1406e0: 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00
=>0x10006e1406f0: 00 00[04]f4 f4 f4 f3 f3 f3 f3 00 00 00 00 00 00
0x10006e140700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006e140710: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006e140720: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006e140730: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006e140740: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap righ redzone: fb
Freed Heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
ASan internal: fe
==4517== ABORTING
在启用所有警告的情况下始终进行编译也是一个好主意。
答案 4 :(得分:0)
数组索引从0
开始。所以你不应该访问第10个元素。
array[0] is storing 1.
array[1] is storing 2.
array[2] is storing 3.
array[3] is storing 3.
array[4] is storing 4.
array[5] is storing 5.
array[6] is storing 6.
array[7] is storing 7.
array[8] is storing 8.
当您尝试访问array[9]
时,您将获得未定义的行为。