2

In s1.c:

#include <stdio.h>
int foo();
struct t1 {
  int j; int k; int i;
} a; 
int main() {
  foo();
  printf("%d %d %d\n", a.i, a.j, a.k); }

In s.c:

struct t1 {
  int i; int j; int k;
} a;
int foo() {
  a.i = 5; a.j = 7; a.k = 9;
  return 0;
}

Compile with gcc s.c s1.c -o ee

Run with ./ee, I got the following output: 9 5 7.

I know this has something to do with linking, but what's the reason for that in deed?

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
Yizheng Shen
  • 231
  • 1
  • 12
  • 1
    Your structure declarations are different in the two modules. – Barmar May 11 '15 at 21:55
  • See http://stackoverflow.com/questions/1433204/how-do-i-use-extern-to-share-variables-between-source-files-in-c for the proper way to share a variable between source files. – Barmar May 11 '15 at 22:09

1 Answers1

4

This program is an exhibit of undefined behavior: when the declaration of the struct in one translation unit does not match its definition in the other translation unit, the program is ill-defined, and it can do anything.

In this case, you got lucky, and the program printed numbers in the opposite order. Although it did it on your system, there is no requirement for your program to do the same (or even to run!) on another standard-compliant system. This is because the types of fields match pairwise (j <==> i, k <===> j, i and <===> k). If you change the types of i, j, and k to char, double, and int, your program will probably print some garbage values or crash.

From C99, 6.2.7.1:

two structure, union, or enumerated types declared in separate translation units are compatible if their tags and members satisfy the following requirements: If one is declared with a tag, the other shall be declared with the same tag. If both are complete types, then the following additional requirements apply: there shall be a one-to-one correspondence between their members such that each pair of corresponding members are declared with compatible types, and such that if one member of a corresponding pair is declared with a name, the other member is declared with the same name. For two structures, corresponding members shall be declared in the same order. For two structures or unions, corresponding bit-fields shall have the same widths. For two enumerations, corresponding members shall have the same values. (emphasis added)

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    Can you provide a standard reference? I think it's defined if the types correspond, the member names don't have to be the same. – Barmar May 11 '15 at 22:02
  • @JonathanLeffler Thanks, Jonathan! I knew it was there, but it took me a while to search for it (I searched "translation unit"; I should have searched "compatible" :-) – Sergey Kalinichenko May 11 '15 at 22:16
  • YW; I knew roughly where to look as I've needed to reference it before. The verbiage in C11 is slightly different. _If both are complete types_ in C99 vs _If both are completed anywhere within their respective translation units_ in C11. – Jonathan Leffler May 11 '15 at 22:19