Why this constant expression is not constantError “initializer element is not constant” when trying to initialize variable with constWith arrays, why is it the case that a[5] == 5[a]?Why doesn't GCC optimize a*a*a*a*a*a to (a*a*a)*(a*a*a)?Why are elementwise additions much faster in separate loops than in a combined loop?Why static const members cannot appear in a constant expression like 'switch'Why is ZLIB uncompress hanging?Why does the C preprocessor interpret the word “linux” as the constant “1”?Global reach of char *argv[ ] and int argc C++int main(int argc, const char * argv[]) AND file inputC struct - cannot be definedVigénere Cipher in C

how to convert Timestring to seconds

Minimizing medical costs with HSA

Why did C++11 make std::string::data() add a null terminating character?

Is it possible that Curiosity measured its own methane or failed doing the spectrometry?

Should I increase my 401k contributions, or increase my mortgage payments

Why do we need a bootloader separate than our application program in MCU's?

What does this value mean in a BJT datasheet?

How come having a Deathly Hallow is not a big deal?

About opening an LLC with little to report in the beginning

How to figure out layers of the atmosphere?

Was Wolfgang Unzicker the last Amateur GM?

How frequently do Russian people still refer to others by their patronymic (отчество)?

Two queries on triangles, the sides of which have rational lengths

Can a wizard delay learning new spells from leveling up to learn different spells later?

How should I present a resort brochure in my general fiction?

Do intermediate subdomains need to exist?

Do I need to be legally qualified to install a Hive smart thermostat?

Convenience stores in India

Using Sed to add counter to keyword

Does Evolution Sage proliferate Blast Zone when played?

What do you call the angle of the direction of an airplane?

Can 4 Joy cons connect to the same Switch?

What is the addition in the re-released version of Avengers: Endgame?

Bypass with wrong cvv of debit card and getting OTP



Why this constant expression is not constant


Error “initializer element is not constant” when trying to initialize variable with constWith arrays, why is it the case that a[5] == 5[a]?Why doesn't GCC optimize a*a*a*a*a*a to (a*a*a)*(a*a*a)?Why are elementwise additions much faster in separate loops than in a combined loop?Why static const members cannot appear in a constant expression like 'switch'Why is ZLIB uncompress hanging?Why does the C preprocessor interpret the word “linux” as the constant “1”?Global reach of char *argv[ ] and int argc C++int main(int argc, const char * argv[]) AND file inputC struct - cannot be definedVigénere Cipher in C






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








10















I have the following C listing:



static const int constant = (0 | ((((1 << 6) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1) << ((((0 + 8) + 8) + 3) + 7))) | ((((1 << 7) - 1) << (((0 + 8) + 8) + 3)) & ((0) << (((0 + 8) + 8) + 3))) | ((((1 << 3) - 1) << ((0 + 8) + 8)) & ((0) << ((0 + 8) + 8))) | ((((1 << 8) - 1) << 0) & ((1) << 0)));

int main(int argc, char** argv)

return constant;




When I am trying to compile this with GCC-9.1 using this command line:



gcc-9 -Werror -Wpedantic main.c


I am getting this error:



main.c:1:29: error: initializer element is not a constant expression [-Werror=pedantic]


Why is that? Is this a compiler bug? Clearly, constant is initialized with a constant expression.










share|improve this question

















  • 2





    @PM77-1: That's not the issue. The question isn't whether the expression constant is a constant expression, it's whether its initializer is a constant expression.

    – Keith Thompson
    8 hours ago






  • 1





    Could it be that some subexpression overflows the range of int? (Note that clang doesn't complain.) Could be a gcc bug.

    – Keith Thompson
    8 hours ago






  • 1





    @vaigult I can' not reproduce the error.

    – Vlad from Moscow
    8 hours ago






  • 4





    You have UB as a result of an overflowing left-shift, so this example does not demonstrate a compiler bug. I'm not sure whether that fully explains the issue, however. Does GCC 9.1 still reject the code if you change the (1 << 6) to (1 << 5)?

    – John Bollinger
    7 hours ago






  • 3





    @JohnBollinger: For me, if I change the first (only) (1 << 6) to (1 << 5), the error message goes away. The term becomes ((((1 << 5) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1) << ((((0 + 8) + 8) + 3) + 7))) which avoids shifting 1 left by 32 (the left shifting in total is 31) when you change 6 to 5. That's probably a mix of 'good catch' and 'poor message' by the compiler.

    – Jonathan Leffler
    7 hours ago


















10















I have the following C listing:



static const int constant = (0 | ((((1 << 6) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1) << ((((0 + 8) + 8) + 3) + 7))) | ((((1 << 7) - 1) << (((0 + 8) + 8) + 3)) & ((0) << (((0 + 8) + 8) + 3))) | ((((1 << 3) - 1) << ((0 + 8) + 8)) & ((0) << ((0 + 8) + 8))) | ((((1 << 8) - 1) << 0) & ((1) << 0)));

int main(int argc, char** argv)

return constant;




When I am trying to compile this with GCC-9.1 using this command line:



gcc-9 -Werror -Wpedantic main.c


I am getting this error:



main.c:1:29: error: initializer element is not a constant expression [-Werror=pedantic]


Why is that? Is this a compiler bug? Clearly, constant is initialized with a constant expression.










share|improve this question

















  • 2





    @PM77-1: That's not the issue. The question isn't whether the expression constant is a constant expression, it's whether its initializer is a constant expression.

    – Keith Thompson
    8 hours ago






  • 1





    Could it be that some subexpression overflows the range of int? (Note that clang doesn't complain.) Could be a gcc bug.

    – Keith Thompson
    8 hours ago






  • 1





    @vaigult I can' not reproduce the error.

    – Vlad from Moscow
    8 hours ago






  • 4





    You have UB as a result of an overflowing left-shift, so this example does not demonstrate a compiler bug. I'm not sure whether that fully explains the issue, however. Does GCC 9.1 still reject the code if you change the (1 << 6) to (1 << 5)?

    – John Bollinger
    7 hours ago






  • 3





    @JohnBollinger: For me, if I change the first (only) (1 << 6) to (1 << 5), the error message goes away. The term becomes ((((1 << 5) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1) << ((((0 + 8) + 8) + 3) + 7))) which avoids shifting 1 left by 32 (the left shifting in total is 31) when you change 6 to 5. That's probably a mix of 'good catch' and 'poor message' by the compiler.

    – Jonathan Leffler
    7 hours ago














10












10








10








I have the following C listing:



static const int constant = (0 | ((((1 << 6) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1) << ((((0 + 8) + 8) + 3) + 7))) | ((((1 << 7) - 1) << (((0 + 8) + 8) + 3)) & ((0) << (((0 + 8) + 8) + 3))) | ((((1 << 3) - 1) << ((0 + 8) + 8)) & ((0) << ((0 + 8) + 8))) | ((((1 << 8) - 1) << 0) & ((1) << 0)));

int main(int argc, char** argv)

return constant;




When I am trying to compile this with GCC-9.1 using this command line:



gcc-9 -Werror -Wpedantic main.c


I am getting this error:



main.c:1:29: error: initializer element is not a constant expression [-Werror=pedantic]


Why is that? Is this a compiler bug? Clearly, constant is initialized with a constant expression.










share|improve this question














I have the following C listing:



static const int constant = (0 | ((((1 << 6) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1) << ((((0 + 8) + 8) + 3) + 7))) | ((((1 << 7) - 1) << (((0 + 8) + 8) + 3)) & ((0) << (((0 + 8) + 8) + 3))) | ((((1 << 3) - 1) << ((0 + 8) + 8)) & ((0) << ((0 + 8) + 8))) | ((((1 << 8) - 1) << 0) & ((1) << 0)));

int main(int argc, char** argv)

return constant;




When I am trying to compile this with GCC-9.1 using this command line:



gcc-9 -Werror -Wpedantic main.c


I am getting this error:



main.c:1:29: error: initializer element is not a constant expression [-Werror=pedantic]


Why is that? Is this a compiler bug? Clearly, constant is initialized with a constant expression.







c gcc






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 8 hours ago









ivaigultivaigult

3,2502 gold badges19 silver badges43 bronze badges




3,2502 gold badges19 silver badges43 bronze badges







  • 2





    @PM77-1: That's not the issue. The question isn't whether the expression constant is a constant expression, it's whether its initializer is a constant expression.

    – Keith Thompson
    8 hours ago






  • 1





    Could it be that some subexpression overflows the range of int? (Note that clang doesn't complain.) Could be a gcc bug.

    – Keith Thompson
    8 hours ago






  • 1





    @vaigult I can' not reproduce the error.

    – Vlad from Moscow
    8 hours ago






  • 4





    You have UB as a result of an overflowing left-shift, so this example does not demonstrate a compiler bug. I'm not sure whether that fully explains the issue, however. Does GCC 9.1 still reject the code if you change the (1 << 6) to (1 << 5)?

    – John Bollinger
    7 hours ago






  • 3





    @JohnBollinger: For me, if I change the first (only) (1 << 6) to (1 << 5), the error message goes away. The term becomes ((((1 << 5) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1) << ((((0 + 8) + 8) + 3) + 7))) which avoids shifting 1 left by 32 (the left shifting in total is 31) when you change 6 to 5. That's probably a mix of 'good catch' and 'poor message' by the compiler.

    – Jonathan Leffler
    7 hours ago













  • 2





    @PM77-1: That's not the issue. The question isn't whether the expression constant is a constant expression, it's whether its initializer is a constant expression.

    – Keith Thompson
    8 hours ago






  • 1





    Could it be that some subexpression overflows the range of int? (Note that clang doesn't complain.) Could be a gcc bug.

    – Keith Thompson
    8 hours ago






  • 1





    @vaigult I can' not reproduce the error.

    – Vlad from Moscow
    8 hours ago






  • 4





    You have UB as a result of an overflowing left-shift, so this example does not demonstrate a compiler bug. I'm not sure whether that fully explains the issue, however. Does GCC 9.1 still reject the code if you change the (1 << 6) to (1 << 5)?

    – John Bollinger
    7 hours ago






  • 3





    @JohnBollinger: For me, if I change the first (only) (1 << 6) to (1 << 5), the error message goes away. The term becomes ((((1 << 5) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1) << ((((0 + 8) + 8) + 3) + 7))) which avoids shifting 1 left by 32 (the left shifting in total is 31) when you change 6 to 5. That's probably a mix of 'good catch' and 'poor message' by the compiler.

    – Jonathan Leffler
    7 hours ago








2




2





@PM77-1: That's not the issue. The question isn't whether the expression constant is a constant expression, it's whether its initializer is a constant expression.

– Keith Thompson
8 hours ago





@PM77-1: That's not the issue. The question isn't whether the expression constant is a constant expression, it's whether its initializer is a constant expression.

– Keith Thompson
8 hours ago




1




1





Could it be that some subexpression overflows the range of int? (Note that clang doesn't complain.) Could be a gcc bug.

– Keith Thompson
8 hours ago





Could it be that some subexpression overflows the range of int? (Note that clang doesn't complain.) Could be a gcc bug.

– Keith Thompson
8 hours ago




1




1





@vaigult I can' not reproduce the error.

– Vlad from Moscow
8 hours ago





@vaigult I can' not reproduce the error.

– Vlad from Moscow
8 hours ago




4




4





You have UB as a result of an overflowing left-shift, so this example does not demonstrate a compiler bug. I'm not sure whether that fully explains the issue, however. Does GCC 9.1 still reject the code if you change the (1 << 6) to (1 << 5)?

– John Bollinger
7 hours ago





You have UB as a result of an overflowing left-shift, so this example does not demonstrate a compiler bug. I'm not sure whether that fully explains the issue, however. Does GCC 9.1 still reject the code if you change the (1 << 6) to (1 << 5)?

– John Bollinger
7 hours ago




3




3





@JohnBollinger: For me, if I change the first (only) (1 << 6) to (1 << 5), the error message goes away. The term becomes ((((1 << 5) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1) << ((((0 + 8) + 8) + 3) + 7))) which avoids shifting 1 left by 32 (the left shifting in total is 31) when you change 6 to 5. That's probably a mix of 'good catch' and 'poor message' by the compiler.

– Jonathan Leffler
7 hours ago






@JohnBollinger: For me, if I change the first (only) (1 << 6) to (1 << 5), the error message goes away. The term becomes ((((1 << 5) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1) << ((((0 + 8) + 8) + 3) + 7))) which avoids shifting 1 left by 32 (the left shifting in total is 31) when you change 6 to 5. That's probably a mix of 'good catch' and 'poor message' by the compiler.

– Jonathan Leffler
7 hours ago













1 Answer
1






active

oldest

votes


















12















I am getting this error:



main.c:1:29: error: initializer element is not a constant expression [-Werror=pedantic]


Why is that? Is this a compiler bug? Clearly, constant is initialized
with a constant expression.




"Constant expression" is a defined term in the language standard. I suspect that GCC is using it that way, as the standard does require your initializer to be a constant expression in that sense. Certainly the evaluation of your code needs to be performed in that light.



There are two language constraints on constant expressions:




Constant expressions shall not contain assignment, increment,
decrement, function-call, or comma operators, except when they are
contained within a subexpression that is not evaluated.




and




Each constant expression shall evaluate to a constant that is in the
range of representable values for its type.




The former is not a problem for you. The latter, however, is an issue on C implementations where type int has 31 or fewer value bits (including GCC on most platforms). Consider in particular this sub-expression:



(((1 << 6) - 1) << ((((0 + 8) + 8) + 3) + 7))


... but for sanity, let's remove some unnecessary parentheses and simplify the right-hand side of the outer << to get this, which preserves the relevant characteristics:



((1 << 6) - 1) << 26


All the individual numeric constants have type int, therefore so also do all the intermediate results (where the "26" in the simplified version corresponds to such an intermediate result in the original expression). The arithmetically-correct result for that left shift requires at least 32 value bits, and because your int (probably) doesn't have that many, since one bit is reserved for the sign, the behavior is undefined.



As such, there is no compiler bug here, though you might have a grounds for a quality of implementation complaint. Likewise, no compiler that accepts the code without warning or error is for that reason buggy. In a different sense, your code does violate a language constraint, and in that sense the compiler is obligated to emit a diagnostic, although the one it has chosen seems misleading.



Furthermore, others' comments on the question seem to confirm that the overflow is correlated with the error, since changing the called-out expression from using (1 << 6) to either (1 << 5) or (1u << 6) resolves the error for others who could reproduce it. Both yield overall expression without any sub-expressions that have undefined behavior.



Note well that it is almost always better to avoid signed integer types when you are doing bitwise manipulation. As such, neglecting any impact on the larger program from which this was drawn, I would be inclined to rewrite your example program as



static const unsigned int constant = (0 
| ((((1u << 6) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1u) << ((((0 + 8) + 8) + 3) + 7)))
| ((((1u << 7) - 1) << (((0 + 8) + 8) + 3)) & ((0u) << (((0 + 8) + 8) + 3)))
| ((((1u << 3) - 1) << ((0 + 8) + 8)) & ((0u) << ((0 + 8) + 8)))
| ((((1u << 8) - 1) << 0) & ((1u) << 0)));

int main(void)
// There's a potential issue with the conversion of the return value, too, but it
// does not affect the particular expression at issue here.
return constant;



Note that the type of the result of a bitwise shift is determined by the type of its left-hand operand only.






share|improve this answer

























  • Tl;dr Why does an expression that would produce UB affect the compiler output? Is that a part of UB cases?

    – machine_1
    5 hours ago











  • The error message is correct, but it could be improved by explaining why the expression is not a constant expression (in this case, that a subexpression overflows).

    – Keith Thompson
    5 hours ago











  • @machine_1, in general, "undefined behavior" applies to the combination of program and C implementation. It can manifest either at translation (compile) time or at run time. Certain undefined behaviors make sense only at run time -- for instance, if they are contingent on externally-provided data -- but this is not such a case.

    – John Bollinger
    5 hours ago










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56855913%2fwhy-this-constant-expression-is-not-constant%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









12















I am getting this error:



main.c:1:29: error: initializer element is not a constant expression [-Werror=pedantic]


Why is that? Is this a compiler bug? Clearly, constant is initialized
with a constant expression.




"Constant expression" is a defined term in the language standard. I suspect that GCC is using it that way, as the standard does require your initializer to be a constant expression in that sense. Certainly the evaluation of your code needs to be performed in that light.



There are two language constraints on constant expressions:




Constant expressions shall not contain assignment, increment,
decrement, function-call, or comma operators, except when they are
contained within a subexpression that is not evaluated.




and




Each constant expression shall evaluate to a constant that is in the
range of representable values for its type.




The former is not a problem for you. The latter, however, is an issue on C implementations where type int has 31 or fewer value bits (including GCC on most platforms). Consider in particular this sub-expression:



(((1 << 6) - 1) << ((((0 + 8) + 8) + 3) + 7))


... but for sanity, let's remove some unnecessary parentheses and simplify the right-hand side of the outer << to get this, which preserves the relevant characteristics:



((1 << 6) - 1) << 26


All the individual numeric constants have type int, therefore so also do all the intermediate results (where the "26" in the simplified version corresponds to such an intermediate result in the original expression). The arithmetically-correct result for that left shift requires at least 32 value bits, and because your int (probably) doesn't have that many, since one bit is reserved for the sign, the behavior is undefined.



As such, there is no compiler bug here, though you might have a grounds for a quality of implementation complaint. Likewise, no compiler that accepts the code without warning or error is for that reason buggy. In a different sense, your code does violate a language constraint, and in that sense the compiler is obligated to emit a diagnostic, although the one it has chosen seems misleading.



Furthermore, others' comments on the question seem to confirm that the overflow is correlated with the error, since changing the called-out expression from using (1 << 6) to either (1 << 5) or (1u << 6) resolves the error for others who could reproduce it. Both yield overall expression without any sub-expressions that have undefined behavior.



Note well that it is almost always better to avoid signed integer types when you are doing bitwise manipulation. As such, neglecting any impact on the larger program from which this was drawn, I would be inclined to rewrite your example program as



static const unsigned int constant = (0 
| ((((1u << 6) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1u) << ((((0 + 8) + 8) + 3) + 7)))
| ((((1u << 7) - 1) << (((0 + 8) + 8) + 3)) & ((0u) << (((0 + 8) + 8) + 3)))
| ((((1u << 3) - 1) << ((0 + 8) + 8)) & ((0u) << ((0 + 8) + 8)))
| ((((1u << 8) - 1) << 0) & ((1u) << 0)));

int main(void)
// There's a potential issue with the conversion of the return value, too, but it
// does not affect the particular expression at issue here.
return constant;



Note that the type of the result of a bitwise shift is determined by the type of its left-hand operand only.






share|improve this answer

























  • Tl;dr Why does an expression that would produce UB affect the compiler output? Is that a part of UB cases?

    – machine_1
    5 hours ago











  • The error message is correct, but it could be improved by explaining why the expression is not a constant expression (in this case, that a subexpression overflows).

    – Keith Thompson
    5 hours ago











  • @machine_1, in general, "undefined behavior" applies to the combination of program and C implementation. It can manifest either at translation (compile) time or at run time. Certain undefined behaviors make sense only at run time -- for instance, if they are contingent on externally-provided data -- but this is not such a case.

    – John Bollinger
    5 hours ago















12















I am getting this error:



main.c:1:29: error: initializer element is not a constant expression [-Werror=pedantic]


Why is that? Is this a compiler bug? Clearly, constant is initialized
with a constant expression.




"Constant expression" is a defined term in the language standard. I suspect that GCC is using it that way, as the standard does require your initializer to be a constant expression in that sense. Certainly the evaluation of your code needs to be performed in that light.



There are two language constraints on constant expressions:




Constant expressions shall not contain assignment, increment,
decrement, function-call, or comma operators, except when they are
contained within a subexpression that is not evaluated.




and




Each constant expression shall evaluate to a constant that is in the
range of representable values for its type.




The former is not a problem for you. The latter, however, is an issue on C implementations where type int has 31 or fewer value bits (including GCC on most platforms). Consider in particular this sub-expression:



(((1 << 6) - 1) << ((((0 + 8) + 8) + 3) + 7))


... but for sanity, let's remove some unnecessary parentheses and simplify the right-hand side of the outer << to get this, which preserves the relevant characteristics:



((1 << 6) - 1) << 26


All the individual numeric constants have type int, therefore so also do all the intermediate results (where the "26" in the simplified version corresponds to such an intermediate result in the original expression). The arithmetically-correct result for that left shift requires at least 32 value bits, and because your int (probably) doesn't have that many, since one bit is reserved for the sign, the behavior is undefined.



As such, there is no compiler bug here, though you might have a grounds for a quality of implementation complaint. Likewise, no compiler that accepts the code without warning or error is for that reason buggy. In a different sense, your code does violate a language constraint, and in that sense the compiler is obligated to emit a diagnostic, although the one it has chosen seems misleading.



Furthermore, others' comments on the question seem to confirm that the overflow is correlated with the error, since changing the called-out expression from using (1 << 6) to either (1 << 5) or (1u << 6) resolves the error for others who could reproduce it. Both yield overall expression without any sub-expressions that have undefined behavior.



Note well that it is almost always better to avoid signed integer types when you are doing bitwise manipulation. As such, neglecting any impact on the larger program from which this was drawn, I would be inclined to rewrite your example program as



static const unsigned int constant = (0 
| ((((1u << 6) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1u) << ((((0 + 8) + 8) + 3) + 7)))
| ((((1u << 7) - 1) << (((0 + 8) + 8) + 3)) & ((0u) << (((0 + 8) + 8) + 3)))
| ((((1u << 3) - 1) << ((0 + 8) + 8)) & ((0u) << ((0 + 8) + 8)))
| ((((1u << 8) - 1) << 0) & ((1u) << 0)));

int main(void)
// There's a potential issue with the conversion of the return value, too, but it
// does not affect the particular expression at issue here.
return constant;



Note that the type of the result of a bitwise shift is determined by the type of its left-hand operand only.






share|improve this answer

























  • Tl;dr Why does an expression that would produce UB affect the compiler output? Is that a part of UB cases?

    – machine_1
    5 hours ago











  • The error message is correct, but it could be improved by explaining why the expression is not a constant expression (in this case, that a subexpression overflows).

    – Keith Thompson
    5 hours ago











  • @machine_1, in general, "undefined behavior" applies to the combination of program and C implementation. It can manifest either at translation (compile) time or at run time. Certain undefined behaviors make sense only at run time -- for instance, if they are contingent on externally-provided data -- but this is not such a case.

    – John Bollinger
    5 hours ago













12












12








12








I am getting this error:



main.c:1:29: error: initializer element is not a constant expression [-Werror=pedantic]


Why is that? Is this a compiler bug? Clearly, constant is initialized
with a constant expression.




"Constant expression" is a defined term in the language standard. I suspect that GCC is using it that way, as the standard does require your initializer to be a constant expression in that sense. Certainly the evaluation of your code needs to be performed in that light.



There are two language constraints on constant expressions:




Constant expressions shall not contain assignment, increment,
decrement, function-call, or comma operators, except when they are
contained within a subexpression that is not evaluated.




and




Each constant expression shall evaluate to a constant that is in the
range of representable values for its type.




The former is not a problem for you. The latter, however, is an issue on C implementations where type int has 31 or fewer value bits (including GCC on most platforms). Consider in particular this sub-expression:



(((1 << 6) - 1) << ((((0 + 8) + 8) + 3) + 7))


... but for sanity, let's remove some unnecessary parentheses and simplify the right-hand side of the outer << to get this, which preserves the relevant characteristics:



((1 << 6) - 1) << 26


All the individual numeric constants have type int, therefore so also do all the intermediate results (where the "26" in the simplified version corresponds to such an intermediate result in the original expression). The arithmetically-correct result for that left shift requires at least 32 value bits, and because your int (probably) doesn't have that many, since one bit is reserved for the sign, the behavior is undefined.



As such, there is no compiler bug here, though you might have a grounds for a quality of implementation complaint. Likewise, no compiler that accepts the code without warning or error is for that reason buggy. In a different sense, your code does violate a language constraint, and in that sense the compiler is obligated to emit a diagnostic, although the one it has chosen seems misleading.



Furthermore, others' comments on the question seem to confirm that the overflow is correlated with the error, since changing the called-out expression from using (1 << 6) to either (1 << 5) or (1u << 6) resolves the error for others who could reproduce it. Both yield overall expression without any sub-expressions that have undefined behavior.



Note well that it is almost always better to avoid signed integer types when you are doing bitwise manipulation. As such, neglecting any impact on the larger program from which this was drawn, I would be inclined to rewrite your example program as



static const unsigned int constant = (0 
| ((((1u << 6) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1u) << ((((0 + 8) + 8) + 3) + 7)))
| ((((1u << 7) - 1) << (((0 + 8) + 8) + 3)) & ((0u) << (((0 + 8) + 8) + 3)))
| ((((1u << 3) - 1) << ((0 + 8) + 8)) & ((0u) << ((0 + 8) + 8)))
| ((((1u << 8) - 1) << 0) & ((1u) << 0)));

int main(void)
// There's a potential issue with the conversion of the return value, too, but it
// does not affect the particular expression at issue here.
return constant;



Note that the type of the result of a bitwise shift is determined by the type of its left-hand operand only.






share|improve this answer
















I am getting this error:



main.c:1:29: error: initializer element is not a constant expression [-Werror=pedantic]


Why is that? Is this a compiler bug? Clearly, constant is initialized
with a constant expression.




"Constant expression" is a defined term in the language standard. I suspect that GCC is using it that way, as the standard does require your initializer to be a constant expression in that sense. Certainly the evaluation of your code needs to be performed in that light.



There are two language constraints on constant expressions:




Constant expressions shall not contain assignment, increment,
decrement, function-call, or comma operators, except when they are
contained within a subexpression that is not evaluated.




and




Each constant expression shall evaluate to a constant that is in the
range of representable values for its type.




The former is not a problem for you. The latter, however, is an issue on C implementations where type int has 31 or fewer value bits (including GCC on most platforms). Consider in particular this sub-expression:



(((1 << 6) - 1) << ((((0 + 8) + 8) + 3) + 7))


... but for sanity, let's remove some unnecessary parentheses and simplify the right-hand side of the outer << to get this, which preserves the relevant characteristics:



((1 << 6) - 1) << 26


All the individual numeric constants have type int, therefore so also do all the intermediate results (where the "26" in the simplified version corresponds to such an intermediate result in the original expression). The arithmetically-correct result for that left shift requires at least 32 value bits, and because your int (probably) doesn't have that many, since one bit is reserved for the sign, the behavior is undefined.



As such, there is no compiler bug here, though you might have a grounds for a quality of implementation complaint. Likewise, no compiler that accepts the code without warning or error is for that reason buggy. In a different sense, your code does violate a language constraint, and in that sense the compiler is obligated to emit a diagnostic, although the one it has chosen seems misleading.



Furthermore, others' comments on the question seem to confirm that the overflow is correlated with the error, since changing the called-out expression from using (1 << 6) to either (1 << 5) or (1u << 6) resolves the error for others who could reproduce it. Both yield overall expression without any sub-expressions that have undefined behavior.



Note well that it is almost always better to avoid signed integer types when you are doing bitwise manipulation. As such, neglecting any impact on the larger program from which this was drawn, I would be inclined to rewrite your example program as



static const unsigned int constant = (0 
| ((((1u << 6) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1u) << ((((0 + 8) + 8) + 3) + 7)))
| ((((1u << 7) - 1) << (((0 + 8) + 8) + 3)) & ((0u) << (((0 + 8) + 8) + 3)))
| ((((1u << 3) - 1) << ((0 + 8) + 8)) & ((0u) << ((0 + 8) + 8)))
| ((((1u << 8) - 1) << 0) & ((1u) << 0)));

int main(void)
// There's a potential issue with the conversion of the return value, too, but it
// does not affect the particular expression at issue here.
return constant;



Note that the type of the result of a bitwise shift is determined by the type of its left-hand operand only.







share|improve this answer














share|improve this answer



share|improve this answer








edited 6 hours ago

























answered 6 hours ago









John BollingerJohn Bollinger

92.1k8 gold badges47 silver badges90 bronze badges




92.1k8 gold badges47 silver badges90 bronze badges












  • Tl;dr Why does an expression that would produce UB affect the compiler output? Is that a part of UB cases?

    – machine_1
    5 hours ago











  • The error message is correct, but it could be improved by explaining why the expression is not a constant expression (in this case, that a subexpression overflows).

    – Keith Thompson
    5 hours ago











  • @machine_1, in general, "undefined behavior" applies to the combination of program and C implementation. It can manifest either at translation (compile) time or at run time. Certain undefined behaviors make sense only at run time -- for instance, if they are contingent on externally-provided data -- but this is not such a case.

    – John Bollinger
    5 hours ago

















  • Tl;dr Why does an expression that would produce UB affect the compiler output? Is that a part of UB cases?

    – machine_1
    5 hours ago











  • The error message is correct, but it could be improved by explaining why the expression is not a constant expression (in this case, that a subexpression overflows).

    – Keith Thompson
    5 hours ago











  • @machine_1, in general, "undefined behavior" applies to the combination of program and C implementation. It can manifest either at translation (compile) time or at run time. Certain undefined behaviors make sense only at run time -- for instance, if they are contingent on externally-provided data -- but this is not such a case.

    – John Bollinger
    5 hours ago
















Tl;dr Why does an expression that would produce UB affect the compiler output? Is that a part of UB cases?

– machine_1
5 hours ago





Tl;dr Why does an expression that would produce UB affect the compiler output? Is that a part of UB cases?

– machine_1
5 hours ago













The error message is correct, but it could be improved by explaining why the expression is not a constant expression (in this case, that a subexpression overflows).

– Keith Thompson
5 hours ago





The error message is correct, but it could be improved by explaining why the expression is not a constant expression (in this case, that a subexpression overflows).

– Keith Thompson
5 hours ago













@machine_1, in general, "undefined behavior" applies to the combination of program and C implementation. It can manifest either at translation (compile) time or at run time. Certain undefined behaviors make sense only at run time -- for instance, if they are contingent on externally-provided data -- but this is not such a case.

– John Bollinger
5 hours ago





@machine_1, in general, "undefined behavior" applies to the combination of program and C implementation. It can manifest either at translation (compile) time or at run time. Certain undefined behaviors make sense only at run time -- for instance, if they are contingent on externally-provided data -- but this is not such a case.

– John Bollinger
5 hours ago








Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.







Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56855913%2fwhy-this-constant-expression-is-not-constant%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Sahara Skak | Bilen | Luke uk diar | NawigatsjuunCommonskategorii: SaharaWikivoyage raisfeerer: Sahara26° N, 13° O

The fall designs the understood secretary. Looking glass Science Shock Discovery Hot Everybody Loves Raymond Smile 곳 서비스 성실하다 Defas Kaloolon Definition: To combine or impregnate with sulphur or any of its compounds as to sulphurize caoutchouc in vulcanizing Flame colored Reason Useful Thin Help 갖다 유명하다 낙엽 장례식 Country Iron Definition: A fencer a gladiator one who exhibits his skill in the use of the sword Definition: The American black throated bunting Spiza Americana Nostalgic Needy Method to my madness 시키다 평가되다 전부 소설가 우아하다 Argument Tin Feeling Representative Gym Music Gaur Chicken 일쑤 코치 편 학생증 The harbor values the sugar. Vasagle Yammoe Enstatite Definition: Capable of being limited Road Neighborly Five Refer Built Kangaroo 비비다 Degree Release Bargain Horse 하루 형님 유교 석 동부 괴롭히다 경제력

19. јануар Садржај Догађаји Рођења Смрти Празници и дани сећања Види још Референце Мени за навигацијуу