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.
A couple of things:
First,
does not do the same thing as
In the first case, the
*is only there to indicate thatamounthas pointer type, and we are initializing the pointer value (i.e, the address) to9, 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
9to the objectamountis pointing to.Why didn’t this break when you passed
amounttoprintf? Basically, you invoked undefined behavior by passing an argument of the wrong type (%dexpects anint, you passed anint *). One of the possible results of undefined behavior is getting the expected result. For whatever reason,printfwas able to treat thatint *value as anint. 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
amountin your code, you should not have declared it as a pointer, but as a regularint:Secondly, as a rule, you do not want to assign the result of
reallocto the original pointer. Ifreallocfails, it will returnNULLand leave the original block of memory as-is. However, if you assign thatNULLback to your original pointer, you will lose any access to that memory. Best practice is to assign the result ofreallocto a temporary, and then verify that the temporary is valid before assigning it back to the original:Note the use of
sizeof *arrayinstead ofsizeof (int).sizeofis an operator like unary*or unary+, and its operand can either be a parenthesized type name or an expression. The expression*arrayhas typeint, sosizeof *array == sizeof (int). This helps make code a bit easier to read, and if you ever change the type ofarray(say todouble *), you won’t have to update therealloccall. It’s also very useful when allocating multidimensional array types - would you rather writeor
?