I get syntax error for valid C-syntax. It seems like the compiler thinks that the initializer of the variable must come from a constant expression whereas a variable assignment should be accepted as well.
A workaround is to make the declaration separate from the initialization.
Same problem in both C51 and CX51.
foo_t f = {1, 2}; foo_t A[10] = { { 1, 2 } }; void foo(int i, foo_t* foo_p) { foo_t x = f; // C51: error C248: aggregate initialization needs curly braces foo_t y = A[i]; // C51: error C248: aggregate initialization needs curly braces foo_t z = foo_p[i]; // C51: non-address/-constant initializer foo_t w; w = foo_p[i]; // OK }
Adding the version numbers to my previous post.
Tool Version Numbers: Toolchain: PK51 Prof. Developers Kit Version: 8.18 Toolchain Path: C:\Keil\C51\BIN\ C Compiler: C51.Exe V8.18 Assembler: A51.Exe V8.01 Linker/Locator: BL51.Exe V6.20 Librarian: LIB51.Exe V4.24 Hex Converter: OH51.Exe V2.6 CPU DLL: S8051.DLL V3.65 Dialog DLL: DP51.DLL V2.54
It seems like the compiler thinks that the initializer of the variable must come from a constant expression whereas a variable assignment should be accepted as well.
I'm afraid our reasoning about what should be accepted is based on a later edition of the C standard than C51 supports. C51 supports the 1990 edition of the C standard (with some extensions, like //comments), and no, that standard doesn't allow non-constant initializers.
As stated here: http://www.keil.com/product/isoansi.asp
I do not have the standard available to check this but the following would be an invalid iso9899:1990 C-program,
typedef struct { int x; int y; } foo_t; void foo(int i, foo_t* foo_p) { foo_t p = { i, i }; }
but allow the previous. Keil C51 is the first compiler that I have used that rejects the former construct. Several compilers that follow the C89 standard accept the former construct in strict/pedantic modes, like e.g. gcc and IAR.
Keil C51 is the first compiler that I have used that rejects the former construct.
I'm aware that you won't like hearing this, but: that's irrelevant. Non-standard code gets accepted by compilers every day, especially when those compilers are on their way to support the next revision of the standard.
Several compilers that follow the C89 standard accept the former construct in strict/pedantic modes, like e.g. gcc and IAR.
GCC doesn't just support the C89 standard --- it supports either C90 or C99, at the flick of a switch. Neither does it exactly "accept" that code, if invoked in strict C90 mode:
> gcc -pedantic -std=c89 -c tlint.c tlint.c: In function 'foo': tlint.c:5: warning: initializer element is not computable at load time tlint.c:5: warning: initializer element is not computable at load time
PC-Lint also would have told you about this (warning 614)
The acceptance of "//" comments is probably a (if not the) prime example of this!
I do not have the standard text, so I cannot be sure about this, not as sure you are. I know that using a compiler to test what is standard or not is not the best way. But I also know that e.g. GCC is quite strict when told to be, and when I use several compilers only C51 rejects this code in strict mode. So it seems like more than one manufacturer has selected that interpretation.
As for your test it seems to me like you compiled the second code - which should give an error. Try and compile the code in the original post and you will see GCC accepting it without warnings. The important differences here is that the latter one uses expressions inside the aggregate whereas the first is a variable assignment. C99 added the possibility to use expressions inside the aggregate initializers.
As far as I know there is no technical differences between C89 and C90. As you probably know you may hand in the "--std=iso9899:1990" instead of c89 to GCC.
But I also know that e.g. GCC is quite strict when told to be,
And it did warn about that code. Which all that the standard requires to happen in case of a constraint violation like this.
So it seems like more than one manufacturer has selected that interpretation.
This is not a matter of interpretation. It's a matter of compilers supporting more than the language requires them to. Code relying on such extensions is unportable. In stricter language, your code is not a fully conforming C program, and compilers can pretty much do with it whatever they like.
The important differences here is that the latter one uses expressions inside the aggregate whereas the first is a variable assignment.
Ahem, no. All three warnings/errors in the initial test case were about initialized definitions, not assignments.