-2
#include <stdio.h>
int foo() { return 0; }
int a = foo();
int main() {
    return 0;
}

The code above can not be complied because of

From section 3.5.7 Initialization of the C standard:

All the expressions in an initializer for an object that has static storage duration or in an initializer list for an object that has aggregate or union type shall be constant expressions.

#include <iostream>
int foo() { return 0; }
int a = foo();
int main() {
    return 0;
}

However, I don't know why it can be complied in C++ without using constexpr

I want to mention that my main question is why it can be complied in C++ without using constexpr

Community
  • 1
  • 1
chris
  • 2,761
  • 17
  • 24
  • 4
    So basically you're asking, why your cooler can cool and why your notebook cannot, right? – Sourav Ghosh Mar 22 '16 at 14:30
  • 5
    Despite the similiarities, they're two completely different languages, always keep that in mind! – Reousa Asteron Mar 22 '16 at 14:30
  • Why can I iterate a string like `for c in "Hello": ...` in Python and not in C? – too honest for this site Mar 22 '16 at 14:32
  • 1
    @Olaf: You probably meant, why can you [do it in C++](http://coliru.stacked-crooked.com/a/147563394dfcf03c) and not in C. – Cheers and hth. - Alf Mar 22 '16 at 14:38
  • @Cheersandhth.-Alf: I strongly doubt that is valid C++ syntax. No, I mean OP compares two different languages, thus the question could as well be asking why Python code does not compile as C. Comparing apples and oranges. – too honest for this site Mar 22 '16 at 14:46
  • I think the OP is trying to learn/understand C++ and noting the similarity between C and C++ asks this question to understand the differences and how C++ does things (because it is a different language from C). – callyalater Mar 22 '16 at 14:59
  • 1
    @callyalater Thank you, that's why I ask this question. It seems that my expression is not good enough. – chris Mar 22 '16 at 15:13
  • @Olaf: What on Earth makes you doubt the syntax? Hello.' – Cheers and hth. - Alf Mar 22 '16 at 19:24
  • @Cheersandhth.-Alf: I answered in context of your comment to my comment. `for c in "Hello": ...` on Earth is certainly not valid C++. Not sure how is is on Gallifrey, though. – too honest for this site Mar 22 '16 at 19:45
  • 1
    @Olaf: So, when you wrote "THAT", in response to my comment, you meant your Python example and not the C++ example I linked to? That's, like, at the very least an **actively misleading** comment. Borderline untruthful. – Cheers and hth. - Alf Mar 22 '16 at 20:20
  • @Cheersandhth.-Alf: I don't think so. You clearly commented on part of my comment, so how would I know the related part of your comment means the text in the question? Maybe you should power up your sarcasm sensors? Or _at the very least_ just try to understand what other posters mean, instead of assuming bad intention. "No, I mean OP compares two different languages, thus the question could as well be asking why **Python** code does not compile as C. Comparing apples and oranges." should have been clear enough. – too honest for this site Mar 22 '16 at 20:32
  • @Olaf: What the f? You **don't think** you referred to your Python code, when you wrote *that* in response to my link to C++ code. Then logically you referred to the C++ code after all. But logic doesn't apply here, does it? The original comment was just free association on your part, reflecting familiarity with Python and less familiarity with C++, and you don't want to admit that. – Cheers and hth. - Alf Mar 22 '16 at 21:15

3 Answers3

4

C++ is a different programming language. It has different rules than C. For one, C++ supports non-constant initializers for static variables. They are executed prior to main(). That's why the code compiles and works in C++.

fuz
  • 88,405
  • 25
  • 200
  • 352
  • Most compilers will execute the initialization before main, but it is implementation defined. – callyalater Mar 22 '16 at 15:38
  • @callyalater So the initializers might not execute before `main()` does? Can you cite the standard on that? – fuz Mar 23 '16 at 10:56
  • Section 3.6.2(4). It is quoted in my answer below. – callyalater Mar 23 '16 at 13:43
  • @callyalater Thinking about this, I would say that most variables are indeed initialized on first use due to the binary image being loaded lazily (i.e. on page fault). – fuz Mar 23 '16 at 14:04
  • That makes sense. It seems like that it could be related to how a compiler does memory access optimizations, but that is just a guess. – callyalater Mar 23 '16 at 14:07
  • I wonder what g++ does in this case. Do you know or know where I could find out? – callyalater Mar 23 '16 at 14:36
  • @callyalater I have no idea. I'm not a C++ programmer either. – fuz Mar 23 '16 at 15:15
3

In your example, int a is a variable with static storage duration.

According to the C++ Standard, Section 3.6.2 (4),

It is implementation-defined whether the dynamic initialization of a non-local variable with static storage duration is done before the first statement of main. If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first odr-use (3.2) of any function or variable defined in the same translation unit as the variable to be initialized.

Depending on your compiler, a might get initialized before main or it will get initialized before its first use in main. (Most compilers do the former, because it tends to be easier to implement.)

So, in your example, int a = foo(); is declaring and initializing a variable with static storage duration, which is allowed in the C++ standard.

callyalater
  • 3,102
  • 8
  • 20
  • 27
  • When used `int a[foo()+10];` instead of `int a = foo();`I got error: variable length array declaration not allowed at file scope. I know that's why we need `constexpr`. However, why it would fail? Is that global array with `static` storage duration? Thank you. – chris Mar 22 '16 at 16:52
  • 1
    That is a little different because it introduces arrays into the mix which need to be effectively constant at compile time (though many C++ compilers provide added functionality that relaxes the `constexpr` requirement for array sizes). – callyalater Mar 22 '16 at 16:56
  • 1
    Arrays in C++ are laid out contiguously in memory which means that it's size must be known at compile time to reserve the proper amount of space. If `foo()` returned different values depending on execution, there would be no way to fix an array length in memory because it could vary. The compiler has no way to know if the return value from `foo` is effectively const and so it raises an error at compile time. [This answer](http://stackoverflow.com/a/4341919/4975646) for another question explains a little bit more. – callyalater Mar 22 '16 at 17:09
0

The likely reason that C++ can compile your code even without the 'constexpr' attribute on your declaration of foo() is that you have not declared int a to be a constexpr. Therefore, the compiler doesn't need to know the value of a, and it can be initialized at runtime.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
Logicrat
  • 4,438
  • 16
  • 22
  • @Alf Thanks for the edit. Darn autocorrect. I typed `constexpr` and just didn't notice when it got "corrected." :P – Logicrat Mar 22 '16 at 14:43