在数组外部写入后使用realloc写入错误的数组值
第一个循环的输出为1..20。 第二个循环的输出为1..30。 然后第三个循环从1..9开始运行,出于某种原因,它在第十个值处输出81 奇怪的是,如果我为第三个循环重新分配了11个元素,并打印了11个值,它会打印出1..11 我错过了什么在数组外部写入后使用realloc写入错误的数组值,c,C,第一个循环的输出为1..20。 第二个循环的输出为1..30。 然后第三个循环从1..9开始运行,出于某种原因,它在第十个值处输出81 奇怪的是,如果我为第三个循环重新分配了11个元素,并打印了11个值,它会打印出1..11 我错过了什么 #include <stdio.h> int main() { unsigned int *P; P = malloc(20 * sizeof(int)); for (int i = 0; i < 20; i ++
#include <stdio.h>
int main() {
unsigned int *P;
P = malloc(20 * sizeof(int));
for (int i = 0; i < 20; i ++) {
(*(P + (i+1))) = (i+1);
printf("(%d) Pointer address: %x | Pointer value %d \n", (i+1), (P + (i+1)), *(P + (i+1)));
};
P = realloc(P, 30 * sizeof(int));
printf("------------------------------------------------------------ \n");
printf("After reallocation... \n");
printf("------------------------------------------------------------ \n");
for (int i = 0; i < 30; i ++) {
if (i > 19)
(*(P + (i+1))) = (i+1);
printf("(%d) Pointer address: %x | Pointer value %d \n", (i+1), (P + (i+1)), *(P + (i+1)));
};
P = realloc(P, 10 * sizeof(int));
printf("------------------------------------------------------------ \n");
printf("After deallocation... \n");
printf("------------------------------------------------------------ \n");
for (int i = 0; i < 10; i ++)
printf("(%d) Pointer address: %x | Pointer value %d \n", (i+1), (P + (i+1)), *(P + (i+1)));
return 0;
}
您的malloc/realloc太小,因此您在循环中访问的最后一个值可供编译器用于其他用途,因此到达循环末尾时的行为是未定义的,无论您在那里写入什么,在打印之前都可能会被覆盖,也可能不会被覆盖。在使用*P+i+1时,您需要向每一个添加+1,当i的范围为0..9时,您需要访问*P+9+1,它需要分配P+0,到P+10,它需要11个整数 例如,最后一个realloc应更改为: p=reallocP,10*sizeofint 到 p=reallocP,10+1*sizeofint
更好的是,如果您没有像问题的评论者所指出的那样拥有所有+1,并根据需要调整所有其他代码,您将拥有更干净的代码。数组索引从0开始,而不是从1开始。因此,可以使用*P+19访问数组的最后一个元素。当第一个循环中的i=19时,*P+i+1=i+1;写入*P+20,超出范围。越界访问内存是未定义的行为 删除代码中数组访问的所有+1,使其正常运行,即将所有p+i+1更改为p+i。此外,为了可读性,大多数程序员非常喜欢P[i]而不是*P+i。还有一些程序员更喜欢用&P[i]代替P+i——第i个元素的地址 另外,使用%x打印指针值是未定义的行为。%printf中的x需要其参数为unsigned int。将unsigned int*值传递给它是未定义的行为,这恰好在您的计算机上起作用,因为unsigned int的大小很可能与unsigned int*的大小相同。打印指针值的常用方法是使用%p printf说明符并将指针强制转换为void*。请注意,在大多数体系结构上,实际上并不需要强制转换为void*,因为所有指针的大小都相同,但不这样做在技术上是未定义的行为。如果仍要使用%x,则应将参数强制转换为正确的类型,如unsigneduintptr_tP+i 另外,您没有包括malloc和realloc函数的include。您至少应该看到编译器关于隐式声明的警告。这也是未定义的行为,因为隐式声明的函数与实际定义不匹配。隐式声明返回int,而malloc和realloc返回void* 记住错误处理。在无法分配内存的情况下,每个realloc和malloc都可以返回NULL 纠正这些错误后:
#include <stdio.h>
#include <stdlib.h>
int main() {
unsigned int *P;
P = malloc(20 * sizeof(unsigned int));
for (int i = 0; i < 20; i++) {
P[i] = i + 1;
printf("(%d) Pointer address: %p | Pointer value %d \n",
i + 1, (void*)(P + i), P[i]);
};
P = realloc(P, 30 * sizeof(unsigned int));
printf("------------------------------------------------------------ \n");
printf("After reallocation... \n");
printf("------------------------------------------------------------ \n");
for (int i = 0; i < 30; i ++) {
if (i > 19) {
P[i] = i + 1;
}
printf("(%d) Pointer address: %p | Pointer value %d \n",
i + 1, (void*)(P + i), P[i]);
};
P = realloc(P, 10 * sizeof(unsigned int));
printf("------------------------------------------------------------ \n");
printf("After deallocation... \n");
printf("------------------------------------------------------------ \n");
for (int i = 0; i < 10; i ++)
printf("(%d) Pointer address: %p | Pointer value %d \n",
i + 1, (void*)(P + i), P[i]);
return 0;
}
数组索引从0开始,而不是从1开始。。。从数组中删除所有+1。你为什么要写*P+i+1而不是简单的P[i+1]?@Barmar感觉不对。这是正常的方式。习惯它。当你有一个指向数组的指针时,把它当作一个数组来对待。P[i+1]感觉比*P+i+1更正确。后者极不自然。使用它可以传达某种程度的复杂程度,这对作者来说不是一种补充。
(1) Pointer address: 0x13c4260 | Pointer value 1
(2) Pointer address: 0x13c4264 | Pointer value 2
(3) Pointer address: 0x13c4268 | Pointer value 3
(4) Pointer address: 0x13c426c | Pointer value 4
(5) Pointer address: 0x13c4270 | Pointer value 5
(6) Pointer address: 0x13c4274 | Pointer value 6
(7) Pointer address: 0x13c4278 | Pointer value 7
(8) Pointer address: 0x13c427c | Pointer value 8
(9) Pointer address: 0x13c4280 | Pointer value 9
(10) Pointer address: 0x13c4284 | Pointer value 10
(11) Pointer address: 0x13c4288 | Pointer value 11
(12) Pointer address: 0x13c428c | Pointer value 12
(13) Pointer address: 0x13c4290 | Pointer value 13
(14) Pointer address: 0x13c4294 | Pointer value 14
(15) Pointer address: 0x13c4298 | Pointer value 15
(16) Pointer address: 0x13c429c | Pointer value 16
(17) Pointer address: 0x13c42a0 | Pointer value 17
(18) Pointer address: 0x13c42a4 | Pointer value 18
(19) Pointer address: 0x13c42a8 | Pointer value 19
(20) Pointer address: 0x13c42ac | Pointer value 20
------------------------------------------------------------
After reallocation...
------------------------------------------------------------
(1) Pointer address: 0x13c52d0 | Pointer value 1
(2) Pointer address: 0x13c52d4 | Pointer value 2
(3) Pointer address: 0x13c52d8 | Pointer value 3
(4) Pointer address: 0x13c52dc | Pointer value 4
(5) Pointer address: 0x13c52e0 | Pointer value 5
(6) Pointer address: 0x13c52e4 | Pointer value 6
(7) Pointer address: 0x13c52e8 | Pointer value 7
(8) Pointer address: 0x13c52ec | Pointer value 8
(9) Pointer address: 0x13c52f0 | Pointer value 9
(10) Pointer address: 0x13c52f4 | Pointer value 10
(11) Pointer address: 0x13c52f8 | Pointer value 11
(12) Pointer address: 0x13c52fc | Pointer value 12
(13) Pointer address: 0x13c5300 | Pointer value 13
(14) Pointer address: 0x13c5304 | Pointer value 14
(15) Pointer address: 0x13c5308 | Pointer value 15
(16) Pointer address: 0x13c530c | Pointer value 16
(17) Pointer address: 0x13c5310 | Pointer value 17
(18) Pointer address: 0x13c5314 | Pointer value 18
(19) Pointer address: 0x13c5318 | Pointer value 19
(20) Pointer address: 0x13c531c | Pointer value 20
(21) Pointer address: 0x13c5320 | Pointer value 21
(22) Pointer address: 0x13c5324 | Pointer value 22
(23) Pointer address: 0x13c5328 | Pointer value 23
(24) Pointer address: 0x13c532c | Pointer value 24
(25) Pointer address: 0x13c5330 | Pointer value 25
(26) Pointer address: 0x13c5334 | Pointer value 26
(27) Pointer address: 0x13c5338 | Pointer value 27
(28) Pointer address: 0x13c533c | Pointer value 28
(29) Pointer address: 0x13c5340 | Pointer value 29
(30) Pointer address: 0x13c5344 | Pointer value 30
------------------------------------------------------------
After deallocation...
------------------------------------------------------------
(1) Pointer address: 0x13c52d0 | Pointer value 1
(2) Pointer address: 0x13c52d4 | Pointer value 2
(3) Pointer address: 0x13c52d8 | Pointer value 3
(4) Pointer address: 0x13c52dc | Pointer value 4
(5) Pointer address: 0x13c52e0 | Pointer value 5
(6) Pointer address: 0x13c52e4 | Pointer value 6
(7) Pointer address: 0x13c52e8 | Pointer value 7
(8) Pointer address: 0x13c52ec | Pointer value 8
(9) Pointer address: 0x13c52f0 | Pointer value 9
(10) Pointer address: 0x13c52f4 | Pointer value 10