【发布时间】:2020-01-12 07:59:13
【问题描述】:
如果我在 C 中(在 Windows 上)声明 2 个数组 arr1 和 arr2,并用整数 0 到 15 填充 arr1,则部分溢出将进入 arr2,但不是全部。为什么?
int arr1[10];
int arr2[10];
int arr3[10];
int i;
for (i = 0 ; i < 10 ; i++)
{
arr1[i] = 100 + i;
arr3[i] = 300 + i;
}
for (i = 0 ; i < 15 ; i++)
{
arr2[i] = 200 + i;
}
printf ("arr1: ");
for (i = 0 ; i < 10 ; i++)
printf ("%d, ", arr1[i]);
printf ("\n");
printf ("arr2: ");
for (i = 0 ; i < 10 ; i++)
printf ("%d, ", arr2[i]);
printf ("\n");
printf ("arr3: ");
for (i = 0 ; i < 10 ; i++)
printf ("%d, ", arr3[i]);
printf ("\n");
输出:
arr1: 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
arr2: 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
arr3: 212, 213, 214, 303, 304, 305, 306, 307, 308, 309,
预期:
arr1: 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
arr2: 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
arr3: 210, 211, 212, 213, 214, 305, 306, 307, 308, 309,
【问题讨论】:
-
因为未定义的行为没有任何保证的结果。它可以做你期望它做的事情,它可以使程序崩溃,或者完全不同的事情。它甚至不必以任何形式保持一致。干脆别干了,没用也不实用,而且当它停止工作并导致内存损坏等难以调试的问题时,它只会让人头疼。
-
当你覆盖数组时,你只是写入数组开头的内存地址加上 i * int 的大小。你怎么知道其他数组的分配位置?为什么你会假设它们只是在内存中一个接一个地堆叠?
-
这将是因为编译器将数组对齐到 16 字节边界,= 4 个整数。如果您使用 4 的倍数而不是 10,那么它们很可能会相互流入。但是这种行为可能因操作系统和编译器而异,因此不要依赖它(也不要完全停止)。如果你需要 arr1,2,3 是连续的,那么分配一个内存块并分配 arr2 和 arr3 指向你想要的地方。
-
未定义的行为不是严格随机的,但也可能是随机的。问你为什么没有得到你“期望”的行为就像在问,“昨晚我穿过马路,路牌上写着不要走路。我原以为会从警察那里得到一张乱穿马路的罚单。结果我被卡车。为什么?”
标签: c