问题
I read that ;
A compound literal is a C99 feature that can be used to create an array with no name. Consider the example:
int *p = (int []){3, 0, 3, 4, 1};
p
points to the first element of a five- element array containing3, 0, 3, 4
, and1
.
Actually I want to know, Is this array will stored in memory or not as it doesn't have a name?
In other words in case of
char* str = "hello"
Where the string "hello"
will stored in memory?
回答1:
C 2011 (N1570) 6.5.2.5 5 says:
If the compound literal occurs outside the body of a function, the object has static storage duration; otherwise, it has automatic storage duration associated with the enclosing block.
So the compound literal you show has automatic storage duration. The C standard does not specify where such objects are in memory. It is up to the C implementation to organize memory. Typically, an object with automatic storage duration is created on the stack, but there are other methods by which an implementation might manage such objects.
In particular, suppose you record the value of p
elsewhere and recursively call the routine containing this compound literal. When the routine initializes p
again, there is a second instance of the compound literal. They are actually different objects, and the C standard requires that their addresses be different. So, if you print the two pointers, they will have different values. However, if the optimizer is able to determine that you do not do this, and that two pointers to different instances of the compound literal are never compared, and there is no other observable behavior (as defined by the C standard) that can distinguish them, then the C implementation is free to use one actual instance of the compound literal instead of creating a new one each time. In this case, the compiler could keep the compound literal in a data section instead of on the stack.
Here is code that demonstrates two instances of the same compound literal have different addresses:
#include <math.h>
#include <stdio.h>
void foo(int *q)
{
int *p = (int []) { 2, 3 };
if (!q)
foo(p);
else
printf("p = %p, q = %p.\n", (void *) p, (void *) q);
}
int main(void)
{
foo(0);
return 0;
}
String literals are different. C 2011 (N1570) 6.4.5 6 says:
In translation phase 7, a byte or code of value zero is appended to each multibyte character sequence that results from a string literal or literals.78) The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence.
So a string literal denotes an object with static storage duration. There is only one instance of it even if a routine containing it is called recursively.
回答2:
Using pointer arithmetic. So
p[0], p[1], ...
or
*p, *(p + 1), ...
Here's the thing. In C, you have nice literals for primitive types like int
and char
, and even string literals. So, we can easily say things like
int length(char *s);
int len = length("Hello, World!");
In C99, the concept of compound literals was added to handle "array literal" and "struct literal". Therefore, we can now say things like:
int sum(int a[], int n);
int total = sum((int []){ 17, 42 }, 2);
This is using a compound literal to represent an "array literal".
Actually I want to know, Is this array will stored in memory or not as it doesn't have a name?
Yes, in memory.
I think your confusion stems from this. p
has a name. (int []){3, 0, 3, 4, 1}
does not. It just so happens that p
's value is the address of (int []){3, 0, 3, 4, 1}
. Of course (int []){3, 0, 3, 4, 1}
is in memory; it will be in the data segment for your executable. You just don't have any name with which to refer to it.
回答3:
Conceptually as like you assigns string to a char pointer in C, similarly you are assigning an array of integers to p
of type int*
:
When you declares: int *p = (int []){3, 0, 3, 4, 1};
it can be assume to be store in memory like:
p 23 27 31 35 36 37
+----+ +----+----+----+----+----+----+
| 23 | | 3 | 0 | 3 | 4 | 1 | ? |
+----+ +----+----+----+----+----+----+
▲ ▲ ▲ ▲ ▲ ▲
| | | | | // garbage value
p p+1 p+2 p+3 p+4
So basically array allocates continues memory. And you can access elements of array as follows:
p[0] == 3
p[1] == 0
p[2] == 3
p[3] == 4
p[4] == 1
Note:
We do char* str = "hello";
While type of string literals in C is char[N]
not char*
. But thing is in most expressions char[N]
can decays into char*
.
Point:
When you declares an array, for example:
int p[] = {3, 0, 3, 4, 1};
then here p
type is int[5]
and &p
pointer to an array
= types is: int(*)[5]
Whereas in declaration:
int *p = (int []){3, 0, 3, 4, 1};
p
pointer to first element and type of p
is int*
and &p
type is int**
. (this is similar to string assignment to char pointer).
In first case p[i] = 10;
is legal for 0 <= i <= 4
, But in second case you are writing on read only memory-illegal memory operation-segmentation fault.
point:
Not following is also valid declaration:
int *p = (int *){3, 0, 3, 4, 1};
Q Actually I want to know, Is this array will stored in memory or not as it doesn't have a name?
Of-course array's stored in memory but its just pointed by p
(p
is not name of array), no other name is for it. Suppose if you do:
int *p = (int []){3, 0, 3, 4, 1};
int i = 10;
p = &i;
Now you have lost the address of array, its exactly similar to:
char* s = "hello";
char c = 'A';
s = &c;
and now you loses the address of "hello"
.
Memory for constant comes from static segment, when you declares. Any int-array of char string literal get store there. When your declaration runs address assigned to pointer variables. But constant don't have any name-but value. In both cases array and string "hello"
becomes the part of executable in data section. (you can disassemble to find there values).
回答4:
Two ways:
&((int[]){3,0,3,4,1})[3]
and
((int[]){3,0,3,4,1})+3
Be aware that if the literal is inside a function, pointers to it are invalidated when the enclosing block is exited.
来源:https://stackoverflow.com/questions/17890301/where-does-the-compound-string-literals-get-stored-in-the-memory