0

I have an object of type int** which I want to fill with integers that were originally strings, in this case fill it with the integer 1234 that was originally a string "1234".

int** num_list = malloc(10*sizeof(int*));

for(int i=0; i<10; i++) {
   num_list[i] = atoi("1234");
}

free(num_list);

The error / warning I get is assignment makes pointer to integer without a cast [-Wint -conversion]. I'm still new to C language and after failing with various attempts of making this work correctly I came to ask here, why is this happening and how can this work without issues? I cannot change the type of the list, it needs to stay as int** because all my work depends on this type and I cannot change it to something else.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
tenepolis
  • 145
  • 4
  • 1
    You have an array of ten pointers, pointing to nothing. – wildplasser Jul 07 '21 at 12:01
  • 1
    Are you sure you want an `int **`? Based on what you're doing, it looks like all you need is an `int *`. An `int *` can simulate an array of integers, which is what it looks like you're using here. An `int **`, on the other hand, would simulate a *two dimensional* array of integers. – Steve Summit Jul 07 '21 at 12:03
  • You try to assign an `int` value (the return value of `atoi`) to an array element `num_list[i]` which is of type `int *` – Bodo Jul 07 '21 at 12:03
  • @wildplasser If I make them point to the string "1234" first, and then iterate over the list and convert them with atoi() as done above, would that work? Or there is a better way of doing this? – tenepolis Jul 07 '21 at 12:03
  • Do not care about Warnings.... Errors are horrible then this..... Still Warning itself defined why you are getting this. – Lalit Verma Jul 07 '21 at 12:03
  • @SteveSummit Yes I'm trying to make a list which has 0 to n entries. So for example with num_list[4] I can see what value is behind that – tenepolis Jul 07 '21 at 12:05
  • 1
    If you want `num_list[4]` to be an integer like 1234, then `num_list` must either be an array of `int` or a pointer to `int`. I see where you said you must use `int **`, but if so, then `num_list[4]` is never going to be an `int`. If `num_list` is a pointer to a pointer to an `int`, then `num_list[4]` is going to be a pointer to an `int`. – Steve Summit Jul 07 '21 at 12:07
  • 1
    @LalitVerma no! Care about warnings! This warning is telling him that his code is almost guaranteed to crash and is far easier to debug than an actual crash. Fix all your warnings so that when you get one like this you see it! – Andy Newman Jul 07 '21 at 12:08
  • @LalitVerma *Do not care about Warnings...* What?!?! The people who wrote the compiler you're using to turn your code into something that can run think your code is so dodgy that they made the extra effort to tell you "Hey, we think this is dodgy code and you should look at it closely and probably fix it." Do you ***really*** think it's a good idea to ignore the experts you're relying on to convert your code into an executable when they say your code is dodgy? – Andrew Henle Jul 07 '21 at 12:13
  • @LalitVerma Warnings almost always mean "here is a severe bug in your program that must be fixed" and not "here is a cosmetic issue you may ignore", like some beginners seem to believe. – Lundin Jul 07 '21 at 14:05
  • [“Pointer from integer/integer from pointer without a cast” issues](https://stackoverflow.com/questions/52186834/pointer-from-integer-integer-from-pointer-without-a-cast-issues) – Lundin Jul 07 '21 at 14:08

2 Answers2

3

You dont need to have int** (pointer to a pointer) use just int*

int* num_list = malloc(10*sizeof(int));

for(int i=0; i<10; i++) {
   num_list[i] = atoi("1234");
}

free(num_list);
OKEE
  • 450
  • 3
  • 15
3

You could do this:

int** num_list_1 = malloc(10*sizeof(int*));

for(int i=0; i<10; i++) {
   num_list_1[i] = malloc(sizeof int);
   num_list_1[i][0] = atoi("1234");
}

for(int i=0; i<10; i++) {
   free(num_list_1[i]);
}

free(num_list_1);

Or you could do this:

int** num_list_2 = malloc(10*sizeof(int*));
num_list_2[0] = malloc(10*sizeof(int));

for(int i=1; i<10; i++) {
   num_list_2[i] = NULL;
}

for(int i=0; i<10; i++) {
   num_list_2[0][i] = atoi("1234");
}

Notice that in the first example the key assignment is

num_list_1[i][0] = atoi("1234");

while in the second example it is

num_list_2[0][i] = atoi("1234");

Another way to write the first (not the second) example would be

*num_list_1[i] = atoi("1234");

The first example looks like this in memory:

            +---+
num_list_1: | * |
            +-|-+
              |
              v
            +---+    +------+
            | *----> | 1234 |
            +---+    +------+     +------+
            | *-----------------> | 1234 |
            +---+    +------+     +------+
            | *----> | 1234 |
            +---+    +------+
              .
              .
              .
            +---+    +------+
            | *----> | 1234 |
            +---+    +------+

The second example looks like this:

            +---+
num_list_2: | * |
            +-|-+
              |
              v
            +---+    +------+------+------+     +------+
            | *----> | 1234 | 1234 | 1234 | ... | 1234 |
            +---+    +------+------+------+     +------+
            | 0 |
            +---+
            | 0 |
            +---+
              .
              .
              .
            +---+
            | 0 |
            +---+

Notice that in each case, num_list_1 and num_list_2 point to an array of pointers, and each of those second-level pointers actually points to an int (or to several ints in the case of num_list_2).

If you could use int * (as in SlLoWre's answer) it would look like this:

            +---+    +------+------+------+     +------+
  num_list: | *----> | 1234 | 1234 | 1234 | ... | 1234 |
            +---+    +------+------+------+     +------+

But, again, if you want this picture, num_list has to be an int *, not an int **.

The requirement to use int ** seems strange. The only reason I can imagine that you would use an int ** would be if you are using a function to construct the array, and the function is returning the pointer by reference. That would look like this:

void allocate_array(int **num_list_p)
{
    *num_list_p = malloc(10*sizeof(int*));

    for(int i=0; i<10; i++) {
       (*num_list_p)[i] = atoi("1234");
    }
}

int main()
{
    int *num_list;
    allocate_array(&num_list);
    for(int i = 0; i < 10; i++) {
        printf("%d: %d\n", i, num_list[i]);
    }
}

Also, one last thing: You probably knew this, but in real code, we would always check the return value of malloc to make sure it wasn't NULL.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103