通过将指针整数和 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 *amountamount = 9; 结果是一样的。我认为我所做的是正确的(因为我还记得我的讲师告诉我)?另外,我试图稍后通过引用将它传递给一个函数。还有其他方法可以做到吗? 如果你想模拟“通过引用传递”,你可以使用地址运算符&amp;传递一个指向变量的指针。和int amount = 9; ...; some_function(&amp;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 = &amp;a, null, int *pt = NULL; 其他指针int a; int *pa = &amp;a; int *pb = pa; 的值。 int *amount = xxx; 其中 xxx 是整数值是代码异味。我知道的唯一正确的用例是当您直接访问硬件时(在内核模式或嵌入式系统中)。在这种情况下,您可能会将 io 端口或显示内存映射到众所周知的地址。例如在 MS/DOS 中,文本屏幕显示映射到地址 0xB0000。 啊!我明白了,我认为您的意思是“或”而不是“的”?谢谢! @WealthyPlayer:是的,很抱歉。 FR 键对我来说太近了:-( 没问题 :-) 你已经回答了我的问题,我应该感谢你。【参考方案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?

#define _clr(x) memset(x,0xff,sizeof(int)*n) 是啥意思?

一维数组和指针

C和指针