【问题标题】:Malloc compile error: a value of type "int" cannot be used to initialize an entity of type int (*)[30]Malloc 编译错误:“int”类型的值不能用于初始化 int (*)[30] 类型的实体
【发布时间】:2012-11-20 13:59:54
【问题描述】:

到目前为止,我一定已经尝试了 20 种方法。我真的需要帮助,无论我做什么,我都会收到与此类似的错误。

a value of type "int" cannot be used to initialize an entity of type "int (*)[30]"

即这会给我带来这样的错误

int(*array)[160] = malloc((sizeof *array) * 10);

做这样的事情

int** Make2DintArray(int arraySizeX, int arraySizeY) {
    int** theArray;
    theArray = (int**) malloc(arraySizeX*sizeof(int*));
    int i;
    for (i = 0; i < arraySizeX; i++)
    {
        theArray[i] = (int*) malloc(arraySizeY*sizeof(int));
    }
    return theArray;
}

会给我这个

"void *(size_t)" in "memory.c" at line 239 and: "int()" 

有没有人有办法成功分配一个 2dArray 的 int[160][10]

【问题讨论】:

  • 是的,但我遇到了另一个问题,@WhozCraig 为我发现了这个问题。
  • 请听你的编译器,他告诉你你的错误是什么。对于如何定义二维数组的真正问题:不要通过指向指针的指针来模拟二维数组。现代 C 中的一个大矩阵可以通过 double (*array)[n] = malloc(sizeof(double[n][m])); 简单地分配

标签: c pointers malloc


【解决方案1】:

试试这个:

int **array;
array = malloc(rows * sizeof(int *));
for (i = 0; i < rows; i++)
  array[i] = malloc(cols * sizeof(int));

// Some testing
for (i = 0; i < rows; i++) {
  for (j = 0; j < cols; j++)
    array[i][j] = 0; // or whatever you want
}

for (i = 0; i < rows; i++) {
  for (j = 0; j < cols; j++)
    printf("%d ", array[i][j]);
}

在您的情况下,rows = 160 和 cols = 10。是一种可能的解决方案。

通过这种方法,您可以使用两个索引:

【讨论】:

  • 第2行不应该是sizeof(int*)吗?
  • 你是对的!打字错误。我认为它在这种情况下有效,因为sizeof(int) == sizeof(int *)(在我的电脑中)。
【解决方案2】:

这两个对我来说都很好。第一个错误很常见,因为您在使用所述相同(例如malloc(size_t))中声明的函数之前忘记#include &lt;stdlib.h&gt;,我确实没有忘记这样做.

C 有一些有趣的编译时行为,其中包括调用以前从未见过的函数的能力(原型定义也没有实现)。在遇到这样的调用时,C 假定函数是:

  • 返回 int 的东西
  • 采用未知数量的参数,因此调用者可以传递它想要的任何东西(包括错误的东西)。

例如,函数被隐式假定为:

int func();

通常你甚至不会注意到,除了编译器发出的警告,这些警告会报告以下内容:

Warning: implicit declaration of `func` assumed to return `int`

如果您在球上,您的警告级别会在启用警告作为错误的情况下出现,并且会发现这一点。

但如果你不这样做呢?如果从函数返回的“事物”不能用实现int 中的数据大小来表示内容怎么办?例如,如果int 是 32 位的,但数据指针是 64 位的怎么办?例如,假设 char *get_str() 在您包含的某个头文件中声明,并在您编译并与程序链接的 .c 文件中实现,如下所示:

#include <stdio.h>

// Note: NO prototype for get_str
int main()
{
    char *s = get_str();
    printf("String: %s\n", s);
    return 0;
}

好吧,编译器应该吐了,告诉你intchar* 不兼容(在它警告你之后不久get_str 假定返回int)。但是,如果您通过告诉编译器以一种或另一种方式生成char* 来强制编译器怎么办:

#include <stdio.h>

// Note: NO prototype for get_str
int main()
{
    char *s = (char*)get_str(); // NOTE: added cast
    printf("String: %s\n", s);
    return 0;
}    

现在,如果没有启用错误警告,您将收到一个隐式声明警告,仅此而已。代码将编译。但它会 运行 吗?如果sizeof(int) != sizeof(char*),(32 位与 64 位)可能不会。 get_str 返回的值是一个 64 位指针,但 调用者 假设只返回 32 位,然后将其强制为 64 位指针。简而言之,演员隐藏了错误并打开了未定义行为的潘多拉魔盒。


那么所有这些与您的代码有何关系?通过不包括&lt;stdlib.h&gt;,编译器不知道malloc 是什么。所以它假设它的形式是:

int malloc();

然后,通过将结果转换为(int**),您就是在告诉编译器“无论结果如何,都将其设为int**”。在链接时,找到_malloc(没有像 C++ 那样通过名称修改的参数签名),连接起来,你的程序准备好了。但是在您的平台上int 和数据指针的大小相同,因此您最终会产生一些不良后果:

  • 演员表隐藏了真正的错误。
  • 虚假指针是由返回的真实指针的一半位制造的。
  • 作为一种残酷的伤口盐,分配的内存被泄漏,因为在任何地方都没有引用它的有效指针(你只是通过只保留一半而破坏了唯一的指针)。
  • 可能是不受欢迎的,如果在实现时编译代码将表现出正常行为 sizeof(int) == sizeof(int**)

所以你在你的 32 位 Debian 机器上构建它,一切看起来都很好。你把作业交给在他的 64 位 Mac 上构建它的教授,然后它崩溃了,你不及格,不及格,大学辍学,在接下来的十年里抚摸这只猫,同时在你妈妈的地下室看 Seinfeld 重播想知道出了什么问题。哎哟。

不要将施法视为银弹。它不是。在 C 语言中, 需要它的频率低于人们使用它的频率,如果在错误的地方使用它,可能会隐藏灾难性的错误。如果您在代码中发现没有强制转换就无法编译的地方,再看一遍。除非您绝对、肯定地确定演员阵容是正确的,否则它的可能性错误

在这种情况下,它隐藏了真正的错误,即您忽略了向编译器提供足够的信息以了解 malloc 的真正作用。

【讨论】:

  • 可能是这个,确实我没有#include
  • @WIllJBD 第二个更重要。 从不在编译 C 时强制转换 malloc。它不需要并隐藏此错误,在 int 与指针大小不同的平台上编译时可能会很糟糕。
  • 就是这样,现在都可以正常编译了。谢谢!
  • @WIllJBD 很高兴你找到它。
【解决方案3】:

分配数组:

int *array = malloc(sizeof(int) * 160 * 10);

然后使用如下代码:

array[10 * row + column] = value;

(其中row 从 0 到 159(含),column 从 0 到 9(含)。

【讨论】:

    【解决方案4】:

    我有一个关于rendon 回答的注释:

    对于他的代码,Visual C++ 对每个“=”操作说:error C2440: '=' : cannot convert from 'void *' to 'int **'

    通过进行一些更改,它对我有用,但我不确定它是否相同,所以我害怕编辑他的代码。相反,这里是我的代码,这似乎适用于第一印象。

    int **a;    
    
    a = (int **)malloc(rows * sizeof(int));
    
    for (i = 0; i < rows; i++)
    {
        a[i] = (int *)malloc(cols * sizeof(int));
    }
    
    for (j=0;j<rows;j++)
    {
        for (i=0;i<cols;i++)
        {
            a[i][j] = 2;
        }
    }
    

    实际上,我使用自定义 struct 而不是 ints 做到了,但我认为无论哪种方式都应该有效。

    【讨论】:

    • 您使用的是 C++ 吗?这在 C 中有效;在 C++ 中,您应该改用 new[]
    • 是的,我使用 C++。谢谢。
    【解决方案5】:

    别介意,我只是在添加一个使用 calloc 的示例

    void allocate_fudging_array(int R, int C)
    {
        int **fudging_array = (int **) calloc(R, sizeof(int *));
        for(int k = 0; k < R; k++)
        {
            fudging_array[k] = (int*) calloc(C, sizeof(int));
        }
    }
    
    
    // a helper function to print the array 
    void print2darr(int **arr, int R, int C)
    {
        for(int i = 0; i < R; i++)
        {
            for(int j = 0; j < C; j++)
            {
                printf(" %d  ", arr[i][j]);
            }
            printf("\n");
        }
    }
    

    【讨论】:

    • 后续 calloc 是否会连续进行指针运算?在多线程的情况下,如果其他线程也执行 malloc/calloc ,是否有可能将连续内存丢失给其他线程?
    【解决方案6】:

    二维数组存储char *

    char ***array;
    int rows = 2, cols = 2, i, j;
    array = malloc(sizeof(char **)*rows);
    for (i = 0; i < rows; i++)
      array[i] = malloc(cols * sizeof(char *));
    
    array[0][0] = "asd";
    array[0][1] = "qwe";
    array[1][0] = "stack";
    array[1][1] = "overflow";
    
    for(i=0;i<rows;i++){
      for(j=0;j<cols;j++){
        printf("%s ",array[i][j]);
      }
      printf("\n");
    }
    

    【讨论】:

      猜你喜欢
      • 2019-02-21
      • 2022-01-25
      • 1970-01-01
      • 1970-01-01
      • 2019-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多