#define adr(x) ((word) &(x)) char tmsec[20]; struct par_struct AL[] = { //par.nr, lv, ln, eh, adress bk, pt, ft { 1, 2, 8, 0, 0, ptUSER, 40}, { 2, 2, 8, 0, 0, ptUSER, 41}, { 3, 2, 1, 0, 0, ptUSER, 42}, { 4, 0, 0, 1, adr(Tmsec), };
Arguing from the point of view of the C programming language itself, your code is broken. adr(Tmsec) is not a compile-time constant (because it's the linker's job to position the variable Tmsec somewhere, not the compiler's), and thus it can't be used to initialize a static variable. I.e. the fact that it appeared to work on C51 was a coincidence, and some might say an unlucky one at that.
That's interesting. I compiled the following code without any problems at all:
char array[6]; int i=(int)&array;
char array[7]; int i=(int)&array;
Actually I think I've found what the size of the array has to do with this. It must be connected with the data threshold setting. The near modifier makes things work:
char near array[20]; int i=(int)&array;
It should work with the far modifier as well (especially if the compiler wants to be ISO C 1999 compliant. You'll have to cite me chapter and verse of the standard you base that claim on before I agree that the address of an object qualifies as a compile time constant suitable for use as an initializer for a static (non variadic-array) object.
The ISO C 1999 standard. Chapter 6.7.8 'Initialization', constraints: 4 All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals. Chapter 6.6 'Constant expressions', semantics: 7 More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following: - an arithmetic constant expression, - a null pointer constant, - an address constant, or - an address constant for an object type plus or minus an integer constant expression. 8 An arithmetic constant expression shall have arithmetic type and shall only have operands that are integer constants, floating constants, enumeration constants, character constants, and sizeof expressions. Cast operators in an arithmetic constant expression shall only convert arithmetic types to arithmetic types, except as part of an operand to a sizeof operator whose result is an integer constant. 9 An address constant is a null pointer, a pointer to an lvalue designating an object of static storage duration, or a pointer to a function designator; it shall be created explicitly using the unary & operator or an integer constant cast to pointer type, or implicitly by the use of an expression of array or function type. The array-subscript [] and member-access . and -> operators, the address & and indirection * unary operators, and pointer casts may be used in the creation of an address constant, but the value of an object shall not be accessed by use of these operators. Actually, after reading it all again I get the impression that addresses of static objects are allowed as initializers, but only as pointers and not as integers. Sorry, my mistake apparently. - mike
"You'll have to cite me chapter and verse of the standard you base that claim on before I agree that the address of an object qualifies as a compile time constant suitable for use as an initializer for a static (non variadic-array) object." Surely it must be so - otherwise how would we do tables of function pointers...? As well as assigning addresses, the linker also fixes-up references to those addresses; therefore, the compiler can take the address of an object as a copile-time constant. Well, that's what I think, anyway... ;-)
You're interpreting the standard better than my memory did, Mike. The address itself would have been eligible for an initializer, but the cast turned it into an implementation-defined thing, which the implementation can rightfully refuse to allow in an initializer. And of course, as soon as keywords like 'near' or 'far' become involved, you're well outside the region where any language standard would apply in the first place.