|
View:
New views
8 Messages
—
Rating Filter:
Alert me
|
|
|
"gcc" complains about a constant being non constant...(sorry for dup)(Sorry if this is a dup, somehow my from address got mangled with the from
addr having this message being sent from my system's MAILER DAEMON! Weird.) I have a "proglet", included below (twice, in fact! :-), first with line numbering for referring to the error messages, and a 2nd time without line numbers to allow for easy cut & pasting to try it in your local environment. The error output appears to indicate a problem with compile-time constant folding. gcc --version shows: gcc (SUSE Linux) 4.3.2 [gcc-4_3-branch revision 141291] Compile time output: ct.c:10: error: initializer element is not constant ct.c:11: error: initializer element is not constant Here's the proglet w/line numbering for reference: ------ 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <strings.h> 4 5 typedef const char * String; 6 7 static const String days [] ={"Sun", "Mon", "Tue", "Wed", "Thu" , "Fri", "Sat"}; 8 static const int sizeof_days = sizeof(days); 9 static const int sizeof_String = sizeof(String); 10 static const int numdays = sizeof_days / sizeof_String; 11 static const int last_index=numdays-1; 12 13 int main (){ 14 printf("numdays=%d, lastidx=%d\n",numdays,last_index); 15 } -------- if, in line 8, sizeof(days) is a constant, AND in line 9, sizeof(String) is a constant, then how can their division (in line 10) NOT be a constant? Similarly, how would a "constant value" minus one, (as in line 11) also not be a constant? This seems too obvious for it not to have been caught before. Is this a designed feature deficit, or did I really stumble upon a bug in such mature code that it wouldn't have been reported and fixed years ago? :-) I've also included same program, below, without line numbers (for easy cut & paste to a test file). Am I missing something about constant folding, or is it this some unlikely fluke? Thanks, Linda --------------------- #include <stdio.h> #include <stdlib.h> #include <strings.h> typedef const char * String; static const String days [] ={"Sun", "Mon", "Tue", "Wed", "Thu" , "Fri", "Sat"}; static const int sizeof_days = sizeof(days); static const int sizeof_String = sizeof(String); static const int numdays = sizeof_days / sizeof_String; static const int last_index=numdays-1; int main (){ printf("numdays=%d, lastidx=%d\n",numdays,last_index); } ----------------------------- |
|
|
Re: "gcc" complains about a constant being non constant...(sorry for dup)Linda A. Walsh wrote:
> (Sorry if this is a dup, somehow my from address got mangled with the from > addr having this message being sent from my system's MAILER DAEMON! > Weird.) > > I have a "proglet", included below (twice, in fact! :-), first with line > numbering for referring to the error messages, and a 2nd time without > line numbers to allow for easy cut & pasting to try it in your local > environment. > > The error output appears to indicate a problem with compile-time constant > folding. > > gcc --version shows: > gcc (SUSE Linux) 4.3.2 [gcc-4_3-branch revision 141291] > > Compile time output: > ct.c:10: error: initializer element is not constant > ct.c:11: error: initializer element is not constant > > Here's the proglet w/line numbering for reference: > ------ > 1 #include <stdio.h> > 2 #include <stdlib.h> > 3 #include <strings.h> > 4 5 typedef const char * String; > 6 7 static const String days [] ={"Sun", "Mon", "Tue", "Wed", "Thu" , > "Fri", "Sat"}; > 8 static const int sizeof_days = sizeof(days); > 9 static const int sizeof_String = sizeof(String); > 10 static const int numdays = sizeof_days / sizeof_String; > 11 static const int last_index=numdays-1; > 12 13 int main (){ > 14 printf("numdays=%d, lastidx=%d\n",numdays,last_index); > 15 } > -------- > > if, in line 8, sizeof(days) is a constant, AND in line 9, > sizeof(String) is > a constant, then how can their division (in line 10) NOT be a constant? Simple: sizeof(days) is a constant, but sizeof_days is not. Reason: because the C language standard says so. A const variable is not a constant. It'd be nice if it were. Andrew. |
|
|
|
|
|
Re: "gcc" complains about a constant being non constant...Bill McEnaney wrote: > Maybe we need to distinguish between a const variable and a literal. >>> if, in line 8, sizeof(days) is a constant, AND in line 9, >>> sizeof(String) is >>> a constant, then how can their division (in line 10) NOT be a constant? >> Simple: sizeof(days) is a constant, but sizeof_days is not. Reason: > because >> the C language standard says so. A const variable is not a constant. > It'd be --- Sorry to say, but whoever the 'rocket scientist' that thought up this nonsense was, should be shot. I can use sizeof(days)/sizeof(String)-1 as a direct initializer into a 'const' variable -- and THAT works: typedef const char * String; static const String suffixes [] = {"B", "KB", "MB", "GB", "TB"}; static const int index_of_last_suffix = sizeof(suffixes)/(sizeof (String)) - 1; As long as I don't try to assign "sizeof(suffixes)/sizeof(String) to a 'const' declared integer, first, and then use that as an intermediate step, I'm fine. But If I want to first assign the quotient to a const int for 'num_items', and then use that value with "-1" to init a 2nd constant, it fails. Sure seems like a C-design bug -- i.e. may be designed that way, but it's certainly non-intuitive to see const int a=b/c; const int d=a-1; FAIL, while const int d=b/c-1; works Certainly breaks or voids the concept of equivalent expressions being equal. Do I remember incorrectly, or is this fixed in C++? Maybe it should be 'fixed' in gnu-c unless they are running under strict POSIX-anal-retentive mode? ;^) Sigh... |
|
|
Re: "gcc" complains about a constant being non constant...Linda A. Walsh wrote:
> > Bill McEnaney wrote: >> Maybe we need to distinguish between a const variable and a literal. That would IMO be a mistake. We should use the ISO terminology, which is "constant expression". >>>> if, in line 8, sizeof(days) is a constant, AND in line 9, >>>> sizeof(String) is >>>> a constant, then how can their division (in line 10) NOT be a constant? >>> Simple: sizeof(days) is a constant, but sizeof_days is not. Reason: >> because >>> the C language standard says so. A const variable is not a constant. >> It'd be > --- > Sorry to say, but whoever the 'rocket scientist' that thought up > this nonsense was, should be shot. Gosh, I hate sentences that begin "Sorry, but ..." :-) > I can use sizeof(days)/sizeof(String)-1 as a direct initializer into > a 'const' variable -- and THAT works: > typedef const char * String; > > static const String suffixes [] = {"B", "KB", "MB", "GB", "TB"}; > > static const int index_of_last_suffix = sizeof(suffixes)/(sizeof > (String)) - 1; > > As long as I don't try to assign "sizeof(suffixes)/sizeof(String) to > a 'const' declared integer, first, and then use that as an intermediate > step, I'm fine. But If I want to first assign the quotient to a const int > for 'num_items', and then use that value with "-1" to init a 2nd > constant, it fails. > > Sure seems like a C-design bug -- i.e. may be designed that way, but > it's certainly non-intuitive to see > const int a=b/c; > const int d=a-1; FAIL, while > const int d=b/c-1; works > > Certainly breaks or voids the concept of equivalent expressions being > equal. But they're not equivalent. The key thing to remember here: A const variable is not a constant. const in C is just a type qualifier. If there's one thing wrong here, it's that const is badly named: it really means "readonly". > Do I remember incorrectly, or is this fixed in C++? Yes, it is different in C++. Here's the C definition: "An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof operator." and the C++ definition: "An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions. Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types. Only type conversions to integral or enumeration types can be used. In particular, except in sizeof expressions, functions, class objects, pointers, or references shall not be used, and assignment, increment, decrement, function-call, or comma operators shall not be used." Andrew. |
|
|
Re: "gcc" complains about a constant being non constant...(sorry for dup)"Linda A. Walsh" <gcc@...> writes:
> Compile time output: > ct.c:10: error: initializer element is not constant > ct.c:11: error: initializer element is not constant If you compile the program as C++ rather than C, then these errors go away, and GCC 4.3.1 propagates the constants to the printf call: movl $6, 8(%esp) movl $7, 4(%esp) movl $.LC0, (%esp) call printf This is one difference in the meaning of const between C and C++. Another difference is that in C++, const variables defined outside of functions are static by default, although one can override that with extern. That doesn't matter in your program because the variables were static already. |
|
|
Re: "gcc" complains about a constant being non constant...Andrew Haley wrote:
> Linda A. Walsh wrote: >> Certainly breaks or voids the concept of equivalent expressions being >> equal. > > But they're not equivalent. > The key thing to remember here: > A const variable is not a constant. > const in C is just a type qualifier. ---- You are right -- However, The C Compiler still could do better. It's not a bug, but would be an RFE in my circumstance. The reason is that all of my 'const inst' were formed from Pre-processor known values (none really came from actual runtime computed data. I rewrote the program to make it more clear about what the improvement could have been. I wasn't misunderstanding the word const (though I could see my meaning was unclear) -- I was using it also as a descriptive element to remind me that everything that fed into it came from compile-time constants. #include <stdio.h> #include <stdlib.h> #include <strings.h> /* start with assumptions true */ /* Note on abbreviations used in defines: * Ar = Array * Asigd= Assigned * Bltn = Builtin * others, I hope are obvious */ #define PreProc_Groks_sizeof_ConstLenAr_div_sizeof_BltnType_min_one_is_Const 1 #define PreProc_Groks_sizeof_BltnType_AsigdTo_const_int_is_const 0 #define PreProc_Groks_sizeof_ConstLenAr_AsigdTo_const_int_is_const 0 #define PreProc_Groks_const_ints_as_const 1 static const const char * days [] ={ "Sun", "Mon", "Tue", "Wed", "Thu" , "Fri", "Sat"}; #if PreProc_Groks_sizeof_ConstLenAr_div_sizeof_BltnType_min_one_is_Const static const int last_index = sizeof(days) / sizeof(const char *)-1; #endif #if PreProc_Groks_sizeof_BltnType_AsigdTo_const_int_is_const static const int szof_charptr = sizeof(const char *); #endif #if PreProc_Groks_sizeof_ConstLenAr_AsigdTo_const_int_is_const static const int szof_days = sizeof(days); #endif #if PreProc_Groks_sizeof_BltnType_AsigdTo_const_int_is_const static const int sizeof_charptr = (const) szof_charptr; #endif #if PreProc_Groks_sizeof_ConstLenAr_AsigdTo_const_int_is_const static const int sizeof_days = (const) szof_days; #endif static const int num_days = (const) sizeof(days) / sizeof(const char *); /* fundamental issue boils down to this: PreProc does not understand consts * assigned values that are only constants determined at Pre Preocessing time * are not "folded" at Pre-Precessing time when they could. * * Not a bug -- just an optimization that could be done * (an RFE...so nevermind...) * */ #if PreProc_Groks_const_ints_as_const static const int alt_last_index = (const) num_days - 1; #endif int main () { printf("last_index = %d", last_index); #if PreProc_Groks_const_ints_as_const printf(", alt_last_index = %d", alt_last_index); #endif printf("\n"); } /* vim: ts=4:sw=4 */ The fact that C++ "fixes" this isn't really a difference in the language, it's just a 'next-generation' of the compile time constant folding. In "C" you'd have to do the same thing using "#define"'s which just looked uglier... Can you think of any backward incompatibility if "C were to rold compile time constants the same way C++ did? Obviously, that optimization would have to be disabled if one tried to take the address of one of the values that has been folded as a constant. If you don't have r/o-segment or text-write segment disabled, you could do this in C: static const int c=1+1; int * trouble=&c; ++*trouble; static const int d=c; The pre-processor would have to do the same type of optimization disabling detection due to anonymous memory assignments that are sometimes disabled for similar reasons when detectable at runtime. Hopefully in C++ that'd throw an exception... It'd have to say that anyone who got that 'fancy' at compile time should be strung up and tickled harshly in front of their peers. :-), but it'd probably eventually happen by accident...to anyone. -l |
|
|
Re: "gcc" complains about a constant being non constant..."Linda A. Walsh" <gcc@...> writes:
> The fact that C++ "fixes" this isn't really a difference in the language, it's just a 'next-generation' of the compile time constant folding. In "C" you'd > have to do the same thing using "#define"'s which just looked uglier... I think it is clearly a difference in the language, in that the respective language standards spell out how things should be handled. > Can you think of any backward incompatibility if "C were to rold compile > time constants the same way C++ did? The C language standard was carefully written to not require the compiler to implement target arithmetic. This is particularly an issue for floating point operations, but it also arises for, e.g., signed magnitude machines, which were a consideration at the time the C standard was first written. The C standard specifies that the preprocessor is explicitly permitted to use host arithmetic, but such permission would not be appropriate for constants which are not handled by the preprocessor. Ian |
| Free embeddable forum powered by Nabble | Forum Help |