2

I somehow can't comprehend how the storage duration of compound literals defined in blocks is automatic, and the reasoning is as follows:

let us assume that the compound literal is defined in a function or block that is called repeatedly; when this function is called for the first time, how can the computer create the literal if it is not in static memory to begin with?? ( what I mean is how does he know its value?? for example is it (int [2]) {2,4} or (int [5]) {5,4,2,1,4}) and if it somehow exists anywhere, how does the computer know its contents again? ( when he tries to construct it again for the second and every subsequent call) after its first pass away.

the case with other literals such as string literals and normal literals is that they are in static memory, and this is very reasonable because how can the computer know its value if he hasn't stored this value somewhere.

can anyone explain this properly to me??

Lockon2000
  • 343
  • 1
  • 3
  • 14
  • 2
    Your question is a bit vague. I don't think you managed to explain very well what you are asking. Maybe edit it? – sashoalm Feb 21 '15 at 19:55
  • maybe you are right, but to be honest I really tried my best already to explain it, for now I will wait a little maybe there is someone out there who understands it as it is. – Lockon2000 Feb 21 '15 at 19:58
  • I don't see how compound literals are any different to automatic variables, a compound literal is mostly syntactic sugar for a temporary variable (which could be placed at the same position in most cases). – mafso Feb 21 '15 at 20:15
  • 1
    If there is `int tmp[2] = { 2, 4 };` somewhere in a function, where does the compiler store {2,4}? Or even: If there is `int tmp = 42;`, where is the 42 stored? – mafso Feb 21 '15 at 20:26
  • @mafso; ^^Question of the year! – haccks Feb 21 '15 at 20:33
  • I'm guessing that the OP is asking: If some code made and stored the compound literal `{2, 4}`, how does other, later code that happens to use the same value, realize that and then locate the previously made `{2, 4}`? That is, *how is that done?* – RBarryYoung Feb 21 '15 at 20:40

3 Answers3

4

Perhaps calling the object a "compound literal" is a bit misleading. It is actually not really so literal.

It's helpful to consider an actual example, even if it's a bit dumb:

/* This is NOT the way to solve this problem */
double cubic(double x, double a, double b, double c, double d) {
  double* powers = (double []){1, x, x*x, x*x*x};
  double* coefficients = (double []){a, b, c, d};
  double sum = 0;
  for (int i = 0; i < 4; ++i) sum += powers[i]*coefficients[i];
  return sum;
}

There are two compound literals in that function, and it is clear that neither of them could be pre-constructed, since they depend on function arguments.

Fortunately, the C compiler is a compiler. It is not limited to creating new datastructures from a copy of an existing constant. It can produce code which allocates the two arrays on the stack ("automatic storage") and then fills them in appropriately.

It's not difficult for the compiler to allocate stack space for these compound literals, because it knows exactly how big they are. In effect, the code produced would be just the same as if I had written:

double cubic(double x, double a, double b, double c, double d) {
  double _powers_values_[4];
  _powers_values_[0] = 1;
  _powers_values_[1] = x;
  _powers_values_[2] = x*x;
  _powers_values_[3] = x*x*x;
  double* powers = _powers_values_;
  // ...

and that is pretty well what you would see if you looked at the generate code for the original function.

Also note that both powers and coefficients are mutable, so I could have modified them in the function:

/* This is NOT the way to solve this problem */
double cubic(double x, double a, double b, double c, double d) {
  double* powers = (double []){1, x, x*x, x*x*x};
  double* coefficients = (double []){a, b, c, d};
  for (int i = 0; i < 4; ++i) coefficients[i] *= powers[i];
  for (int i = 1; i < 4; ++i) coefficients[i] += coefficients[i+1];
  return coefficients[3];
}

Of course, a compound literal might just have constant values:

double* coefficients = (double []){17, 6, -3, 2.5};

But as written, that array is still mutable, so the compiler needs to arrange for the function to have a new copy of the values. If I wanted to, I could make it clear that the array is immutable:

const double* coefficients = (const double []){17, 6, -3, 2.5};

Now the compiler is allowed to use a static literal, instead of making an unnecessary copy. But, in theory, the compound literal still has automatic scope, and returning a pointer to it from the function would be undefined behaviour.

rici
  • 234,347
  • 28
  • 237
  • 341
  • thanks! your answer taught me something new. I didn't know that compound literals could contain variables. but now to my question: form your code it is clear that the compiler can produce code that allocates place for the literal and then have the value supplied by the function argument ( that is the case for the x, a, b, c, d) but what about the ( 1 ) in the first literal?? what does the compiler make with this one ? – Lockon2000 Feb 21 '15 at 20:31
  • @Lockon2000: It's pretty common for the hardware to allow you to specify a small constant like `1` as part of a machine instruction, although that's less common with floating point constants. So it's possible that the `1` doesn't exist in memory anywhere prior to the assignment, or it is possible that the compiler copies into the newly created array from any instance of a constant `1` which exists elsewhere in the code. That's an implementation detail, which doesn't matter at all. (On some machines, `0` is *calculated* as `x-x` where `x` is whatever happened to be in the register.) – rici Feb 21 '15 at 20:35
  • about your last modification, in the last lines you say " Now the compiler is allowed to use a (static literal), instead of making an unnecessary copy. But, (in theory), the compound literal still has (automatic scope), and returning a pointer to it from the function would be undefined behavior. " so the duration for constants in compound literals is really static although not treated accordingly. – Lockon2000 Feb 21 '15 at 20:37
  • @Lockon2000: *might be static*. You don't know, and the compiler isn't obliged to tell you. You need to assume that it is automatic. But that's referring to the compound literal as a whole object. The constants that are used to compute the values of the literal are no different from any other constants in your code. If you write `x += 1.0;` you have no way of knowing where that `1.0` sits in memory -- if it does --, but *you don't care*. You only care that `x` has 1.0 added to it. If the machine had a `floating increment` instruction, the compiler could use that. – rici Feb 21 '15 at 20:41
  • ok, this is exactly what I was searching for. thanx! really and my apologies to everyone for my rather vague question. – Lockon2000 Feb 21 '15 at 20:45
2

You question is not explained properly. If you want to know about the scope of compound literals, then standard says that:

C11: 6.5.2.5 Compound literals (P5):

[...] 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.

Initialization with compound literals is done as follows:

[...] If the block is entered recursively, a new instance of the object is created each time. The initial value of the object is indeterminate. If an initialization is specified for the object, it is performed each time the declaration or compound literal is reached in the execution of the block; otherwise, the value becomes indeterminate each time the declaration is reached.

Compound literals are created on the fly and are unnamed array/struct literals. They are stored in data segment of memory like other variable but with exception that you can't access it with name.

Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
  • ok, your second part is really close to what I am asking about, but not quite it yet so I will try to explain more. the questions is how can a computer make an initialization for some variable if he doesn't know the value for the initialization. in short: where is the compound literal stored until the program initializes some variable to it or even call a function with it as an argument?? if it isn't stored permanently somewhere ( i.e. has static storage duration ), then how does the computer know which specific value it has??? – Lockon2000 Feb 21 '15 at 20:21
  • I added a para. Is this what you are asking for? – haccks Feb 21 '15 at 20:32
-1

the compiles does not know the value of automatic variables. The will contain whatever values were already there. Sometimes (eg in loops) they may happen to contain the value from the last time, but that's by luck, not intent.

The compiler places automatic variables on the stack, intermingled with function parameters and return addresses. Unless the code explicitly initializes them, automatic variables will have the value of whetever bit pattern occupied those memory locations from before.

Andras
  • 2,995
  • 11
  • 17
  • I am sorry, but this is not what I asked about. the second part of the answer right below is closer to what I am searching for, although still not it. of course I know that my vague explanation is the reason. – Lockon2000 Feb 21 '15 at 20:15
  • uninitialized automatic variables contain indeterminate values. What you are describing is a possible manifestation of undefined behaviour (there are other possibilities) – M.M Jun 26 '18 at 03:38