Your original code is invalid. It contains at least two constraint violations: it provides initializers for objects that don't exist, and it tries to use an initializer 1
(of type int
) for an int*
object. A compiler could (and IMHO should) simply reject it. gcc is being overly permissive by compiling your code after merely warning about the errors. The resulting code has undefined behavior.
const char *cptr = "Hello";
The above is valid. "Hello"
is an expression of array type (specifically of type char[6]
). In most contexts, including this one, such an expression is implicitly converted to a pointer to the array's 0th element. Note that I've added const
so the compiler will at least warn if I attempt to modify the data that cptr
points to.
int *iptr = { 1, 2, 3, 4, 5 }; // invalid
This is invalid. You might expect that it's handled similarly to cptr
. The problem is that { 1, 2, 3, 4, 5 }
is not an expression; it's valid only in an initializer. It could be a valid initializer for an array object, but since it's not an expression, the array-to-pointer conversion rule doesn't apply.
Assuming your compiler supports C99 or later (specifically the compound literal feature), you can write:
int *iptr = (int[]){ 1, 2, 3, 4, 5 };
(This is not a cast; the syntax is similar, but the { ... }
is not an expression.)
The compound literal is an expression of array type, specifically int[5]
, and the array-to-pointer conversion applies.
One caveat: A string literal creates an array object, and that object has static storage duration, meaning that it exists throughout the execution of the program. A compound literal creates an object with static storage duration only if it appears outside any function; inside a function, it creates an object with automatic storage duration, meaning that it ceases to exist when you reach the end of the current block. In this case, it's defined inside the main
function, so it's not likely to be an issue. But it's something to watch out for. For example, this is safe:
const char *new_string(void) {
const char *result = "hello";
return result;
}
but this is not:
int *new_array(void) {
int *result = (int[]){ 1, 2, 3, 4, 5 };
return result; /* BAD! */
}
because the array ceases to exist when you leave the function. To avoid that, you can create the array object explicitly to make it static:
int *new_array(void) {
static const int arr[] = { 1, 2, 3, 4, 5 };
int *result = arr; /* or &arr[0] */
return result; /* or "return arr;" */
}