14

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.

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]

4
  • The same question like this stackoverflow.com/questions/1970698/… Commented Dec 3, 2012 at 5:26
  • Yeah but I was having a different problem, which @WhozCraig caught for me. Commented Dec 3, 2012 at 5:29
  • possible duplicate of Do I cast the result of malloc? Commented Dec 3, 2012 at 8:50
  • Please listen to your compiler, he told you what your error was. For your real question on how to define 2D arrays: don't do emulations of 2d arrays by pointers to pointers. A big matrix in modern C can e.g be simply allocated by double (*array)[n] = malloc(sizeof(double[n][m])); Commented Dec 3, 2012 at 8:53

6 Answers 6

17

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.

With this approach you can use the two indexes:

Sign up to request clarification or add additional context in comments.

2 Comments

Shouldn’t line 2 be sizeof(int*)?
You are right! A typing error. I think it worked in this case because sizeof(int) == sizeof(int *)(in my PC).
14

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 not forget to do.

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

  • Something that returns int
  • Takes an unknown number of arguments, so the caller can pass whatever it wants (including the wrong things).

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, int were 32-bit, but data pointers were 64-bit? For example, lets assume char *get_str() is declared in some header file you're not including, and implemented in a .c file you compile and link with your program, that looks like this:

#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 int and char* are not compatible (shortly after it warns you get_str is assumed to return int). But what if you force the compiler's hand by telling it to make a char* one way or another:

#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_str is a 64-bit pointer, but the caller is 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.


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

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, _malloc is found (no parameter signature via name mangling like C++), wired up, and your program is ready to party. But on your platform int and data pointers are not the same size, thus you end up with several undesirable consequences:

  • The cast hides the real error.
  • A bogus pointer is manufactured from half the bits of the real returned 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 most undesirable, the code will exhibit normal behavior if compiled on an implementation where 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.

Don't treat casting like some silver bullet. It isn't. In C, it is needed far less 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.

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

4 Comments

this may be it, indeed I did not #include <stdlib.h>
@WIllJBD The second is more important. Never cast a malloc when compiling C. It isn't needed and hides this error, which can be dreadful when compiling on a platform where int is a different size than a pointer.
And that was it, both now compile fine. Thanks!
@WIllJBD glad you found it.
5

To allocate the array:

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

Then use code like:

array[10 * row + column] = value; 

(Where row goes from 0 to 159 inclusive and column goes from 0 to 9 inclusive.)

Comments

0

I have a note for rendon's answer:

For his code, Visual C++ says for every "=" operations: 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 struct instead of ints but I think either way should it work.

1 Comment

Are you using C++? This works in C; in C++, you should use new[] instead.
0

Don't mind me I'm just adding an example using 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"); } } 

1 Comment

will the subsequent calloc be contiguous to do the pointer arithmetic ? In case of multi threading, won't there be a possibility of losing contiguous memory to other thread, if other thread also does a malloc/calloc ?
-1

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.