Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!cs.utexas.edu!uunet!mcvax!hp4nl!phigate!nlgvax!suhas From: suhas@nlgvax.UUCP (Suhas Joshi) Newsgroups: comp.lang.c Subject: Re: Is this a bug in some C compilers? Keywords: bug; cc; referencing a pointer as if it were a structure, storage Message-ID: <268@nlgvax.UUCP> Date: 20 Jul 89 15:45:11 GMT Reply-To: suhas@nlgvax.UUCP () Organization: Philips Research Geldrop Lines: 71 >Am I correct to say that the program is not correct C, and that all compilers >which compile it are wrong? The usage a.b when a is not a structure is allowed. But it is not portable. This is allowed so that strict typing is not enforced. So, as long as compilers issue a warning, it is acceptable. It is definitely not a bug. As long as a in a.b is lvalue, it is assumed to be a structure, if it is not. See K&R C book's C reference manual sections 7.1 and 14.1 for details. But my decision to post this was for other reason than pointing out this. The reason is how implicit assumption that fix0 and fix1 are allocated around t is wrong, and makes programs which rely on such assumption non-portable. The assumption is implicit due to the use of the following printf about addresses of fix0, fix1 and t. [ Stuff deleted ] >int fix0; >struct link * t; >int fix1; > >main () >{ > printf ("t lies at %1d, brk is at %1d\n", (int)(&t), (int)sbrk(0)); > printf ("Addresses of %1d byte objects around t : %1d and %1d\n", > sizeof(int), (int)(&fix0), (int)(&fix1)); [stuff deleted] See the following output generated by SUN 3 running SunOS 4.0, and note that out of 12 bytes allocated for fix0, fix1 and t. t has last 4, fix0 has first 4, and fix1 has middle 4. So, fix0 and fix1 are not around t in addresses but before t. t lies at 131400, brk is at 131408 Addresses of 4 byte objects around t : 131392 and 131396 Assignment worked. Value 5 has been put at address 131404 This happens because compile generates following assembly directives in the same order as the definitions of the variables in the source LL0: .data .comm _fix0,4 .comm _t,4 .comm _fix1,4 .text .proc [Assembly code deleted] But .comm tells assembler not to allocate storage but to leave it to linker. So, linker reserves 12 bytes, and later allocates 4 each to t, fix1 and fix0 in that order, from the last address in the 12 byte area. So, the allocation depends on how linker looks at the 12 bytes (low to high or high to low), and on the order in which t fix1 and fix0 are referenced., because that is the order in which linker has allocated. First printf refers to t, next refers to fix0 and fix1, but the order of references is fix1 and fix0 because of the order of parameter pushing on the stack. So, beware of dependencies on order of definition of data and assumptions about their allocation in the same order. Suhas M. Joshi. E-Mail: suhas@pcg.philips.nl Philips Research Labs., Tel: +31 40 892336 Project Centre Geldrop, Building XP Willem Alexanderlaan 7B, 5664 AN Geldrop The Netherlands -- Suhas M. Joshi. E-Mail: suhas@pcg.philips.nl Philips Research Labs., Tel: +31 40 892336 Project Centre Geldrop, Building XP Willem Alexanderlaan 7B, 5664 AN Geldrop The Netherlands