C语言 Malloc 编译错误:“int”类型的值不能用于初始化 int (*)[30] 类型的实体

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13677566/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:39:31  来源:igfitidea点击:

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

cpointersmalloc

提问by WIllJBD

I must have tried 20 ways of doing this by now. I really need help, no matter what I do i get a error similar to this one.

我现在一定已经尝试了 20 种方法来做到这一点。我真的需要帮助,无论我做什么,我都会遇到与此类似的错误。

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

i.e. this will get me such an error

即这会让我出现这样的错误

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

and doing something like this

并做这样的事情

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;
}

will get me this

会给我这个

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

does anyone have a solution for how to successful allocate a 2dArray of int[160][10]

有没有人有如何成功分配 int[160][10] 的 2dArray 的解决方案

回答by rendon

Try this:

尝试这个:

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]);
}

In your case rows = 160 and cols = 10. Is one possible solution.

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

With this approach you can use the two indexes:

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

回答by WhozCraig

Both of these compile fine for me. The first error is common when you forget to #include <stdlib.h>prior to using functions declared within said-same (such as malloc(size_t)), which I did notforget to do.

这两个对我来说都很好。当你忘了第一个错误是常见#include <stdlib.h>之前,使用功能中说,相同的(如声明malloc(size_t)),我也不会忘记这样做。

C has some interesting compile-time behaviors, among them the ability to invoke a function that has never been seen before (neither prototype definition norimplementation). Upon encountering such a call, C assumes the function is:

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

  • Something that returns int
  • Takes an unknown number of arguments, so the caller can pass whatever it wants (including the wrong things).
  • 返回的东西 int
  • 采用未知数量的参数,因此调用者可以传递它想要的任何东西(包括错误的东西)。

Eg., the function is implicitly assumed to be of the form:

例如,该函数被隐式假定为以下形式:

int func();

Often you won't even notice, save for warnings from your compiler that report something to the effect of:

通常你甚至不会注意到,除了来自编译器的警告,这些警告报告了以下影响:

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

and if you're on-the-ball, you have your warning levels turned up with warnings-as-errors enabled and will catch this.

如果你在球上,你的警告级别就会被调高,并启用警告作为错误,并且会捕捉到这一点。

But what if you don't? And what if the "thing" returned from the function cannot be content-represented by the data size in an implementation int? What if, for example, intwere 32-bit, but data pointers were 64-bit? For example, lets assume char *get_str()is declared in some header file you're notincluding, and implemented in a .c file you compile and link with your program, that looks like this:

但如果你不这样做呢?如果从函数返回的“事物”不能由实现中的数据大小内容表示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;
}

Well, the compiler should puke, telling you that intand char*are not compatible (shortly after it warns you get_stris assumed to return int). But what if you force the compiler's hand by tellingit to make a char*one way or another:

好吧,编译器应该吐出来,告诉你这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;
}    

Now, without warnings-as-errors enabled, you'll get a implicit declaration warning, and thats it. The code will compile. But will it run? If sizeof(int)!= sizeof(char*), (32-bit vs 64-bit) likely not. The value returned from get_stris a 64-bit pointer, but the calleris assuming only 32-bits is returned, then forcing it to a 64-bit pointer. In short, the cast has hidden the error and opened pandora's box of undefined behavior.

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



So how does all of this relate to your code? By not including <stdlib.h>the compiler doesn't know what mallocis. So it assumes it is of the form:

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

int malloc();

Then, by casting the result to (int**)you're telling the compiler "whatever comes out of this, make it a int**". At link time, _mallocis found (no parameter signature via name mangling like C++), wired up, and your program is ready to party. But on your platform intand data pointers are notthe same size, thus you end up with several undesirable consequences:

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

  • The cast hides the real error.
  • A bogus pointer is manufactured from half the bits of the realreturned pointer.
  • As a cruel dose of salt to the wound, the allocated memory is leaked, as there are no valid pointers anywhere that reference it (you just destroyed the only one by only keeping half of it).
  • Probably the mostundesirable, the code will exhibit normal behavior if compiled on an implementation wheresizeof(int) == sizeof(int**).
  • 演员表隐藏了真正的错误。
  • 假指针是由真实返回指针的一半位构成的。
  • 作为对伤口的残忍一剂盐,分配的内存被泄漏,因为在任何地方都没有引用它的有效指针(你只是通过只保留一半来破坏唯一的指针)。
  • 可能是不受欢迎的,如果在sizeof(int) == sizeof(int**).

So you build this on your 32-bit Debian box, all looks well. You turn in your homework to the professor who builds it on his 64bit Mac and it crashes, you fail the assignment, fail the class, drop out of college, and spend the next ten years petting the cat while watching Seinfeld reruns in your mom's basement wonder what went wrong. Ouch.

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

Don't treat casting like some silver bullet. It isn't. In C, it is needed farless often than people use it, and if used in the wrong place, can hide catastrophic errors. If you find a point in your code where something won't compile without a hard cast, look again. Unless you're absolutely, positively sure the cast is the right thing to do, odds are its wrong.

不要像对待银弹一样对待铸造。不是。在 C 中,它的使用频率低于人们使用它的频率,而且如果在错误的地方使用,可能会隐藏灾难性错误。如果您发现代码中的某个点没有强制转换就无法编译,请再次查看。除非你绝对、肯定地确定演员阵容是正确的,否则很可能是错误的

In this case it hid the real error, that you neglected to give enough info to your compiler to know what mallocreally does.

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

回答by David Schwartz

To allocate the array:

分配数组:

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

Then use code like:

然后使用如下代码:

array[10 * row + column] = value;

(Where rowgoes from 0 to 159 inclusive and columngoes from 0 to 9 inclusive.)

row从 0 到 159(含)和column从 0 到 9(含)。

回答by Zoltán Schmidt

I have a note for rendon's answer:

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

For his code, Visual C++ says for every "=" operations: error C2440: '=' : cannot convert from 'void *' to 'int **'

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

By making some changes, it works for me, but I'm not sure that it does the same, so I afraid of editing his code. Instead, here's me code, that seems to work for a first impression.

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

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;
    }
}

Actually, I did it with a custom structinstead of ints but I think either way should it work.

实际上,我是用自定义struct而不是ints来做的,但我认为无论哪种方式都可以。

回答by Reno

Don't mind me I'm just adding an example using calloc

别介意我只是用 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");
    }
}

回答by gkiko

2D array to store 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");
}