Hi Martin, On 9/3/22 16:35, Martin Uecker wrote: > Am Samstag, den 03.09.2022, 15:41 +0200 schrieb Alejandro Colomar: >> Hi Martin, >> >> On 9/3/22 14:47, Martin Uecker wrote: >> [...] >> >>> GCC will warn if the bound is specified inconsistently between >>> declarations and also emit warnings if it can see that a buffer >>> which is passed is too small: >>> >>> https://godbolt.org/z/PsjPG1nv7 >> >> That's very good news! >> >> BTW, it's nice to see that GCC doesn't need 'static' for array >> parameters. I never understood what the static keyword adds there. >> There's no way one can specify an array size an mean anything other than >> requiring that, for a non-null pointer, the array should have at least >> that size. > > From the C standard's point of view, > > void foo(int n, char buf[n]); > > is semantically equivalent to > > void foo(int, char *buf); > > and without 'static' the 'n' has no further meaning > (this is different for pointers to arrays). I know. I just don't understand the rationale for that decission. :/ > > The static keyword implies that the pointer is be valid and > non-zero and that there must be at least 'n' elements > accessible, so in some sense it is stronger (it implies > alid non-zero pointers), but at the same time it does not > imply a bound. That stronger meaning, I think is a mistake by the standard. Basically, [static n] means the same as [n] combined with [[gnu::nonnull]]. What the standard should have done would be to keep those two things separate, since one may want to declare non-null non-array pointers, or possibly-null array ones. So the standard should have standardized some form of nonnull for that. But the recent discussion about presenting nonnull pointers as [static 1] is horrible. But let's wait till the future hopefully fixes this. > > But I agree that 'n' without 'static' should simply imply > a bound and I think we should use it this way even when > the standard currently does not attach a meaning to it. Yep. [...] >> What about taking something from K&R functions for this?: >> >> int foo(q; w; int a[q], int q, int s[w], int w); >> >> By not specifying the types, the syntax is again short. >> This is left-to-right, so no problems with global variables, and no need >> for complex parsers. >> Also, by not specifying types, now it's more obvious to the naked eye >> that there's a difference: > > I am ok with the syntax, but I am not sure how this would > work. If the type is determined only later you would still > have to change parsers (some C compilers do type > checking and folding during parsing, so need the types > to be known during parsing) and you also still have the > problem with the mutual dependencies. This syntax resembles a lot K&R syntax. Any C compiler that supports them (and I guess most compilers out there do) should be easily convertible to support this syntax (at least more easily than other alternatives). But this is just a guess. > > We thought about using this syntax > > int foo(char buf[.n], int n); > > because it is new syntax which means we can restrict the > size to be the name of a parameter instead of allowing > arbitrary expressions, which then makes forward references > less problematic. It is also consistent with designators in > initializers and could also be extend to annotate > flexible array members or for storing pointers to arrays > in structures: It's not crazy. I don't have much to argue against it. > > struct { > int n; > char buf[.n]; > }; > > struct { > int n; > char (*buf)[.n]; > }; Perhaps some doubts about how this would work for nested structures, but not unreasonable. Cheers, Alex -- Alejandro Colomar