通过将指针整数和 sizeof(int) 相乘来使用 realloc 不起作用
Posted
技术标签:
【中文标题】通过将指针整数和 sizeof(int) 相乘来使用 realloc 不起作用【英文标题】:Using realloc by multiplying a pointer integer and sizeof(int) not working 【发布时间】:2018-11-22 20:13:29 【问题描述】:代码:
void main()
int *array = calloc(5, sizeof(int));
int *amount = 9;
array[0] = 1;
array[1] = 2;
array[3] = 5;
int i = 0;
while (i < 5)
printf("%d ", array[i]);
i += 1;
printf("%d", amount); //Printing
array = realloc(array, amount * sizeof(int)); //Problem is here
printf("\n");
i = 0;
while (i < 9)
printf("%d ", array[i]);
i += 1;
free(array);
它说“二进制*的无效操作数(有'int *'和'unsigned int'),但是当我尝试打印“数量”时,它实际上是9?我正在尝试使用指针整数,以便我可以通过引用传递它。
【问题讨论】:
int *amount = 9;
应该做什么?这使得amount
指向地址9
,那里可能没有任何用处。为什么将amount
设为开头的指针?这应该解决什么问题?
一个奇怪的事情是你将 9 分配给 int 指针。
是的 - 为什么是指针?摆脱那颗星星!
@Someprogrammerdude 据我所知,您可以在声明变量时立即初始化指针指向的值,即int *amount = 9;
。我尝试这样做:int *amount
和amount = 9;
结果是一样的。我认为我所做的是正确的(因为我还记得我的讲师告诉我)?另外,我试图稍后通过引用将它传递给一个函数。还有其他方法可以做到吗?
如果你想模拟“通过引用传递”,你可以使用地址运算符&
传递一个指向变量的指针。和int amount = 9; ...; some_function(&amount);
一样,使用解引用运算符*
来访问函数内部指针所指向的内容。
【参考方案1】:
您只是在使用您的实现允许在指针和整数之间进行安全转换的事实,但是:
int *amount = 9; // only use that for memory mapped hardware registers
printf("%d", amount); //re-interpreting the pointer value as an int
array = realloc(array, amount * sizeof(int)); // hopefully you got a diagnostic
太可怕了。指针只能是指向有效对象的空指针。句号。而指针算法只在数组内部才有意义。
如果一个变量应该包含整数值,那么它应该是一个整数类型:
int amount = 9;
printf("%d", amount); //Printing
array = realloc(array, amount * sizeof(int)); //Problem is here
如果你需要一个指向它的指针,只需声明它并使用它作为一个指针:
int amount = 9;
int *p_amount = &amount;
printf("%d - %d\n", amount, *p_amount); //Printing
array = realloc(array, (*p_amount) * sizeof(int)); //No problem now
【讨论】:
我不太明白您所说的“指针应该只是指向有效对象的空指针”和“仅将其用于内存映射的硬件寄存器”的意思。你能用更简单的术语解释一下吗? @WealthyPlayer:指针应该只分配地址。int a; int *pt = &a
, null, int *pt = NULL;
其他指针int a; int *pa = &a; int *pb = pa;
的值。 int *amount = xxx;
其中 xxx 是整数值是代码异味。我知道的唯一正确的用例是当您直接访问硬件时(在内核模式或嵌入式系统中)。在这种情况下,您可能会将 io 端口或显示内存映射到众所周知的地址。例如在 MS/DOS 中,文本屏幕显示映射到地址 0xB0000。
啊!我明白了,我认为您的意思是“或”而不是“的”?谢谢!
@WealthyPlayer:是的,很抱歉。 F
和 R
键对我来说太近了:-(
没问题 :-) 你已经回答了我的问题,我应该感谢你。【参考方案2】:
amount
的类型为 int *
。 printf
打印 9 的原因不是 amount
指向值 9,而是将值 9 转换为指针。
现在在您的array = realloc(array, amount * sizeof(int));
声明中。您尝试乘以指针(不是amount
指向的值)。问问自己这应该是什么语义。而不是你可能想要的int *amount = 9;
int *amount = calloc(1, sizeof(int));
*amount = 9;
它声明一个指针并为一个整数分配空间,而不是你可能想要的array = realloc(array, amount * sizeof(int));
array = realloc(array, *amount * sizeof(int));
您应该尝试学习指针和指针算术的概念。仅仅声明一个指针并不会在它的末尾保留空间。
【讨论】:
嗯,我明白了。那么可以肯定地说,从一开始(即int *amount = 9
),我就已经误解了该行的含义吗?我想我现在知道它是如何工作的,我也在等待答案时尝试阅读gribblelab.org/CBootCamp/8_Pointers.html。谢谢!
是的。你想要一些指向值 9 的东西,但得到一些指向位置 9 的东西。有时 C 和 C++ 对于一条线的确切含义可能会非常棘手。【参考方案3】:
amount
应定义为 int
而不是 int *
。
int amount = 9;
【讨论】:
【参考方案4】:有几点:
首先,
int *amount = 9;
不做与
相同的事情*amount = 9;
在第一种情况下,*
仅表示amount
具有指针类型,我们将指针 值(即地址)初始化为9
,这很可能不是一个有效的指针值,尝试取消引用它可能会导致运行时错误。
在第二种情况下,我们将整数值 9
分配给 amount
指向的对象。
当您将amount
传递给printf
时,为什么没有中断?基本上,您通过传递错误类型的参数调用了未定义的行为(%d
期望 int
,您传递了 int *
)。未定义行为的可能结果之一是获得预期结果。无论出于何种原因,printf
能够将该int *
值视为int
。大多数编译器应该标记该类型不匹配,但您可能会注意提高警告级别以查看它。
二进制*
运算符有一个约束,即两个操作数都具有算术类型。 int *
不是算术类型,因此是诊断类型。
根据您在代码中实际使用amount
的方式,您不应将其声明为指针,而应将其声明为常规int
:
int amount = 9;
其次,通常,您不希望将realloc
的结果分配给原始指针。如果realloc
失败,它将返回NULL
并保持原来的内存块不变。但是,如果您将 NULL
分配回原始指针,您将失去对该内存的任何访问权限。最佳做法是将realloc
的结果分配给一个临时对象,然后在将其分配回原始对象之前验证该临时对象是否有效:
int *tmp = realloc( array, amount * sizeof *array );
if ( tmp )
array = tmp;
else
// handle realloc error
注意使用sizeof *array
而不是sizeof (int)
。 sizeof
是类似一元 *
或一元 +
的运算符,其操作数可以是带括号的类型名称或表达式。 表达式 *array
的类型为int
,所以sizeof *array == sizeof (int)
。这有助于使代码更易于阅读,并且如果您更改了array
的类型(比如double *
),您将不必更新realloc
调用。在分配多维数组类型时也很有用——你宁愿写吗
int (*arr)[10] = malloc( sizeof (int) * 10 * rows);
或
int (*arr)[10] = malloc( sizeof *arr * rows );
?
【讨论】:
我明白了,谢谢你非常清楚的回答!不过,有些问题是,realloc
是如何或何时失效的?这是非常技术性和困难的问题,我应该暂时忽略它吗?感谢您提供有关使用 sizeof(pointervariable)
而不是显式键入变量类型的提示:-D
哦,我如何打印出指针指向的内存地址(即我应该使用什么类型,因为%d
不正确)?
@WealthyPlayer:使用%p
打印指针值。如果没有足够大的可用内存块来满足请求,realloc
将失败。除非您尝试留出 非常大 的内存块,或者如果您进行了大量的小分配以使堆非常碎片化(即,您可能有这么多 Mb 可用,但不在一个连续的块中)。我在实践中从未遇到过,但需要注意。
好的,谢谢!我也读过这篇文章(答案也来自你:-D):***.com/questions/18217525/…,我发现它对理解动态内存分配的目的非常有帮助。以上是关于通过将指针整数和 sizeof(int) 相乘来使用 realloc 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
为啥“memset(arr, -1, sizeof(arr)/sizeof(int))”不能将整数数组清除为-1?
为啥“memset(arr, -1, sizeof(arr)/sizeof(int))”不能将整数数组清除为-1?