Path: csiph.com!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: const and the C type system Date: Mon, 02 Oct 2017 09:40:34 -0700 Organization: None to speak of Lines: 128 Message-ID: References: <89577a10-c851-42ee-a68a-825a25baded0@googlegroups.com> <2c5a4b5b-ec8b-44fe-a77c-e26a0e1c5bb9@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="6cf03bc409832187b50b684a697bfd95"; logging-data="2000"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19NxGVWTOwI7Z7CbLeGofJ7" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) Cancel-Lock: sha1:zF2wTG1zXq35v/7w8ARItrsOHKg= sha1:2qC5ZT8ADA7NCT/OZFNYD5wM+U8= Xref: csiph.com comp.lang.c:120701 bartc writes: > On 02/10/2017 03:12, Keith Thompson wrote: >> bartc writes: >>> OK, I understand: this is a problem at file-scope. And it's the same >>> problem that stops you using such a value for a fixed array bound or for >>> a case-label. >> >> Do you understand that the initializer for a static object must be a >> constant expression either at file scope or at block scope? You say you >> didn't get a complaint from gcc. I'm skeptical. Did you try that exact >> code, or did you omit the "static" keyword? Please try it again with >> the exact code that you posted above. > > c:\c>type c.c > #include > > int main(void){ > static const int a = 100; > static const double b = 200.1; > static const double c = a+b; > static const long long int d = 5000000000; > static const double e = d*c; > static const unsigned long long f = 0xffffffffffffffff; > > printf("a=%d\n",a); > printf("b=%f\n",b); > printf("c=%f\n",c); > printf("d=%lld\n",d); > printf("e=%f\n",e); > printf("f=%llX\n",f); > } > > c:\c>\tdm\bin\gcc -O3 c.c > > The problem seems to be the -O3 option. Without it, gcc will complain as > you say. So it's a gcc problem. > > No doubt you guys will again try to twist things around and say that > it's a Bart problem, No, it appears to be a bug in gcc. C11 6.10p10 says: An implementation may accept other forms of constant expressions. If gcc were taking advantage of that permission, the lack of a diagnostic would necessarily be a conformance issue. But the fact that the behavior changes with optimization level make me think it's not a deliberate feature. So I think it's a bug in gcc; it's failing to diagnose a constraint violation. The commands you've shown don't actually demonstrate a bug since gcc is not conforming by default, but when I compile the same source with "gcc -std=c11 -pedantic -O3", it still fails to produce a diagnostic. > but the fact reminds that with -O3, nothing was > said, so that I genuinely thought a,b,c,d,e,f were all just synonyms for > their values. If I specify this lot, it still says nothing about it > (I've no idea what those format warnings are about): OK, given that gcc didn't complain, it was probably reasonable for you to assume that the code was valid. > c:\c>\tdm\bin\gcc -O3 -std=c11 -Wall -Wextra -Wpedantic -c c.c > > c.c: In function 'main': > c.c:14:10: warning: unknown conversion type character 'l' in format > [-Wformat=] > printf("d=%lld\n",d); > ^ > c.c:14:10: warning: too many arguments for format [-Wformat-extra-args] > c.c:16:10: warning: unknown conversion type character 'l' in format > [-Wformat=] > printf("f=%llX\n",f); > ^ > c.c:16:10: warning: too many arguments for format [-Wformat-extra-args] That's weird. What version of gcc are you using ("gcc --version")? gcc 6.3.0 doesn't complain about the format strings. An very old version of gcc might not recognize the "%lld" format, which was introduced in C99, but then it shouldn't have recognized the "-std=c11" option. >> The point is that static objects are created and initialized before >> main() begins, and C has no mechanism for running code at that point. > > So how does gcc manage it with -O3? The above program worked. Some expressions that are not constant expressions (as defined by the C standard) can still be evaluated at compile time. The value of a const-qualfied object with a constant initializer is one such expression. A conforming compiler can generate code that reduces the value of such an object to a constant, but it must still diagnose any use of the name of such an object in a context that requires a constant expression. I suspect that gcc is internally failing to distinguish between language-defined constant expressions and expressions that it can evaluate at compile time; it's incorrectly discarding information that it needs so it can produce a diagnostic. [...] >> Knowing that "const" doesn't mean "constant" might have prevented that >> misunderstanding. > > THIS IS THE WHOLE POINT! You're TRYING to use 'const' to implement > something equivalent to (my) 'constant'. I meant knowing that "const" doesn't mean "constant" *in C as it's currently defined*. For purposes of your test program, we're talking about the requirements of C11, not of any proposed future changes. C++ already uses "const" to implement something similar to your proposed "constant". As I've already said, the C++ feature blurs the distinction between "const" and "constant", which is in my opinion a drawback. In spite of that, I think it's a worthwhile addition just because it's useful functionality. On the other hand, I think that a limited form of C++'s more recent "constexpr" might be a better solution (and, with the limitations I'm thinking of, should be no more difficult to implement than your proposal). Quite possibly if "constexpr" had been added to C++ sooner, there would have been no need for it to change the semantics of "const". -- Keith Thompson (The_Other_Keith) kst-u@mib.org Working, but not speaking, for JetHead Development, Inc. "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister"