Using realloc by multiplying a pointer integer and sizeof(int) not working

440 Views Asked by At

Code:

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

It says "invalid operands to binary * (have 'int *' and 'unsigned int'), but when I tried printing "amount", it's actually 9? I'm trying to use a pointer integer so that I can pass it by reference.

4

There are 4 best solutions below

4
John Bode On BEST ANSWER

A couple of things:

First,

int *amount = 9;

does not do the same thing as

*amount = 9;

In the first case, the * is only there to indicate that amount has pointer type, and we are initializing the pointer value (i.e, the address) to 9, which is most likely not a valid pointer value, and attempting to dereference it may lead to a runtime error.

In the second case, we are assigning the integer value 9 to the object amount is pointing to.

Why didn’t this break when you passed amount to printf? Basically, you invoked undefined behavior by passing an argument of the wrong type (%d expects an int, you passed an int *). One of the possible results of undefined behavior is getting the expected result. For whatever reason, printf was able to treat that int * value as an int. Most compilers should flag that type mismatch, but you may heed to crank up the warning level to see it.

There’s a constraint on the binary * operator that both operands have arithmetic type. int * is not an arithmetic type, hence the diagnostic.

Based on how you are actually using amount in your code, you should not have declared it as a pointer, but as a regular int:

int amount = 9;

Secondly, as a rule, you do not want to assign the result of realloc to the original pointer. If realloc fails, it will return NULL and leave the original block of memory as-is. However, if you assign that NULL back to your original pointer, you will lose any access to that memory. Best practice is to assign the result of realloc to a temporary, and then verify that the temporary is valid before assigning it back to the original:

int *tmp = realloc( array, amount * sizeof *array );
if ( tmp )
{
  array = tmp;
}
else
{
  // handle realloc error
}

Note the use of sizeof *array instead of sizeof (int). sizeof is an operator like unary * or unary +, and its operand can either be a parenthesized type name or an expression. The expression *array has type int, so sizeof *array == sizeof (int). This helps make code a bit easier to read, and if you ever change the type of array (say to double *), you won’t have to update the realloc call. It’s also very useful when allocating multidimensional array types - would you rather write

int (*arr)[10] = malloc( sizeof (int) * 10 * rows);

or

int (*arr)[10] = malloc( sizeof *arr * rows );

?

5
Serge Ballesta On

You are just using the fact that your implementation allows for safe conversion between pointers and integers, but this:

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

is terrible. A pointer should only be a null pointer of point to a valid object. Full stop. And pointer arithmetics only makes sense inside an array.

If a variable is supposed to contain integer values, then it shall be of an integer type:

int amount = 9;
printf("%d", amount); //Printing
array = realloc(array, amount * sizeof(int)); //Problem is here

If you need a pointer to it, just declare it and use it as a pointer:

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
2
Iead On

amount has the type int *. The reason printf prints 9 is not that amount points to the value 9, but rather it is the value 9 casted to a pointer.

Now in your array = realloc(array, amount * sizeof(int)); statement. You try to multiply the pointer (not the value pointed to by amount). Ask yourself what the semantics of that should be. Rather than int *amount = 9; you probably want

int *amount = calloc(1, sizeof(int));
*amount = 9;

which declares a pointer and allocates space for one integer and rather than array = realloc(array, amount * sizeof(int)); you probably want

array = realloc(array, *amount * sizeof(int));

you should try to learn the concept of pointers and pointer arithmetics. Just declaring a pointer does not reserve space at the end of it.

0
eyalm On

amount should be defined as an int and not int *.

int amount = 9;