Firstly, according to the C standard, is the C array index variable interpreted as a signed or unsigned integer?
Secondly, what does Keil do?
Surely, the index variable is handled according to its defined type - signed or unsigned??
I'm not sure that it does. C compilers will, after all, cast all sorts of things to int at the drop of a hat. I've run some code through a code analysis package which says that I can't declare an array of 65530 chars because 65530 isn't a valid int. Keil seems quite happy though, and the code runs.
"I can't declare an array of 65530 chars because 65530 isn't a valid int."
That's talking about the array size that you specify in its definition - not about an index.
Whether or not 65530 is valid as an 'int' would depend entirely on the particular compiler that you're using; Also, the maximum size allowable for an array is probably implementation-defined.
The 'C' standard defines 'int' and 'unsigned int' as distinct types - thus 'int' is assumed to be signed.
For a literal integer constant, the 'C' standard says, "The type of an integer constant is the first of the corresponding list in which its value can be represented. Unsuffixed decimal: int, long int, unsigned long int; Unsuffixed hex or octal: int, unsigned int, long int, unsigned long int"
Use the 'u' suffix to make it specifically unsigned, if required.
Some compilers uses the same number of bits in numeric constants intended for the compiler as the actual processor has. Some compilers has extra precision.
If the compiler evaluates constant expressions with 32 bits, then 65530 will fit. If the compiler uses 16-bit precision (unless otherwise informed) then 65530 is too large.
As Andy notes, you can write 65530u to tell that your constant is unsigned. Depending on where you use your constant, it may be needed to specify an 'l' or 'ul' after the integer to specify that the constant must be evaluated as large.
The problem here is that for a 16-bit target, you should not use the constant 65530, even if the compiler accepts it. To make the code portable you must add the 'u' suffix to tell that the constant is unsigned.
Thanks for chapter and verse on the literals. I'm bouncing it back to the guys from the analysis tool, as it's not clear to me whether the problem is in the declaration of the array or in the access.
The analysis tool is most probably correct, so I don't think you have any extra information to send back to them.
You should not try
char myarray[65530];
on a 8 or 16-bit processor, since you are specifically using a long integer to specify the array size.
A numeric constsant that doesn't specify a 'u' or 'l' suffix must be an int, a long int or a long long int. The compiler has to pick the smallest that is large enough.
65530 does not fit in a 16-bit int, so it must be a long int. Since the max size of an array is architecture-dependant, it is quite reasonable that a compiler complains that it doesn't support a long parameter to specify the array size.
Note that most compilers will issue warnings if an integer is larger than the int data type and doesnt specify a 'l' or 'll' suffix to inform that the constant is intentionally large.
What about:
char myarray[65530U];
The closest I can find in the C99 spec is section 6.7.5.2:
In addition to optional type qualifiers and the keyword static, the [ and ] may delimit an expression or *. If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero. The element type shall not be an incomplete or function type. The optional type qualifiers and the keyword static shall appear only in a declaration of a function parameter with an array type, and then only in the outermost array type derivation.
This suggests that on my C166 16 bit target, the following is legal:
char a[32000]; // no problems int b[32000]; // still fits in 64k page long c[32000]; // legal but too big for a page
However,
char d[64000]; // 64000 isn't an int
No, the standard only says that it should be of an integer data type. long int is also an integer data type, so
char d[64000];
is valid even if int is 16-bit and the value 64000 too large to store in an int. However, since the standard doesn't specify the max total size requirements of an array, or the minimum range an array index must be able to span, it is up to the compiler vendor (or the architecture) to set the limit.
A lot of 8 and 16-bit devices are not able to address more than a 16-bit range. Some may support (with more or less compiler magic) to support a huge data type breaking the 64kB wall. Hence, a source analysation program is correct to warn if it detects code that uses a long int for declaring the array size - a lot of compilers will fail to compile the code.
A compiler that does not accept 65530 does not break any C requirements that I have found.
On the other hand: It should be considered a bonus if the Keil compiler supports long int as array size - or notes that the constant 65530 is a long int but that the value still fits in a 16 bit unsigned int, and so is within the capability of the architecture.