C语言数组指针初始化语法解惑:Java开发者的疑问
Great question—this is one of the most common (and totally understandable) points of confusion when switching from Java to C. Java abstracts away low-level memory mechanics, but C forces you to confront them directly, which leads to these "wait, why is it designed this way?" moments. Let's break this down step by step:
First: What int arr[5]; actually does
When you write int arr[5];, you're telling the compiler to allocate 5 consecutive integers on the stack—that's 5 blocks of sizeof(int) memory, laid end-to-end. The identifier arr is not a pointer variable. Instead, it's a name that refers to the entire array.
The confusion comes from this: in almost all expressions (like when you assign it to a pointer, or index into it with arr[2]), arr is implicitly converted to a pointer pointing to the first element of the array. But this is a temporary conversion, not the true nature of arr. You can see this difference with sizeof:
sizeof(arr)will return5 * sizeof(int)(the total size of the entire array)- If
arrwere a pointer,sizeof(arr)would return the size of a pointer (e.g., 8 bytes on 64-bit systems)
What int* arr[5]; actually is
You're exactly right—this declares an array of 5 pointers to integers. Each element in arr is a variable that holds the memory address of an int, not an int value itself. This is a completely different data structure from a regular int array. For example, you'd use this if you wanted to store pointers to 5 separate int variables, or to create a jagged array (arrays of arrays with varying lengths).
Why int* p = arr; is legal
As mentioned earlier, when you use arr in an expression (like assigning it to p), the compiler automatically converts it to a pointer to the first element of the array. This is a deliberate design choice in C to make array manipulation convenient. It lets you use pointer arithmetic (like p++ to move to the next element) to traverse the array, which is efficient at the hardware level.
But keep in mind: this conversion doesn't make arr a pointer. For example, if you take &arr, you get a pointer to the entire array (type int (*)[5]), not a pointer to a pointer. That's a subtle but important distinction.
Why C uses this design instead of int* for array declarations
C was designed to be close to hardware and maximally efficient. Here's why this syntax makes sense:
- Direct memory representation:
int arr[5]directly maps to a block of contiguous integers in memory—no extra pointer variable is needed. In Java, yourint[] arris a reference (a pointer under the hood) to an array object on the heap, but C lets you work directly with the stack-allocated memory block. - Efficiency: If C required
int*to declare arrays, you'd be adding an extra layer of indirection (storing pointers instead of values), which wastes memory and adds overhead. The implicit conversion lets you use pointer-style operations when you want, without sacrificing the efficiency of direct memory access. - Clarity: The syntax clearly distinguishes between a regular array of values (
int arr[5]) and an array of pointers (int* arr[5]). This makes the code's intent clearer to other developers.
Quick recap for Java devs
- In Java:
int[] arr = new int[5]creates an array object, andarris a reference (pointer) to that object. - In C:
int arr[5]creates a block of 5 ints on the stack, andarrrefers to that block. When you usearrin most expressions, it acts like a pointer to the first element—but it's not a pointer variable.
This is one of those C quirks that takes a little time to wrap your head around, but once you get the difference between arrays and pointers, it all clicks into place.
内容的提问来源于stack exchange,提问作者Marcel_marcel1991

