/*
 * By Patrick Reynolds (reynolds .at. cs duke edu)
 * Too trivial to copyright.  It's in the public domain!
 *
 * To build:
 *   gcc align.c -o align
 *
 * To run:
 *   ./align
 *
 * Note that optimizing compilers will almost certainly reorder the data
 * segment, throwing off the values you get for structure alignments.
 * Annoyingly, some compilers don't let you disable optimizations.
 * GCC by default (with optimizations off) doesn't reorder data segments.
 * So use GCC.
 */

#include <stdio.h>

typedef struct { char a; } s_char;
typedef struct { short a; } s_short;
typedef struct { int a; } s_int;
typedef struct { long a; } s_long;
typedef struct { long long a; } s_long_long;
typedef struct { float a; } s_float;
typedef struct { double a; } s_double;
typedef struct { int *a; } s_intp;

int main() {
  int i = 0x01020304;
  char *ch = (char*)&i;
	// Put these in a struct, because when they're individual stack variables,
	// gcc arranges them to be more compact.
	struct {
		char c1;        char ch0;  char c2;
		double d1;      char ch1;  double d2;
		float f1;       char ch2;  float f2;
		short s1;       char ch3;  short s2;
		int i1;         char ch4;  int i2;
		long long ll1;  char ch5;  long long ll2;
		int *p1;        char ch6;  int *p2;
		long l1;        char ch7;  long l2;
		s_char sc1;     char ch8;  s_char sc2;
		s_short ss1;    char ch9;  s_short ss2;
		s_int si1;      char ch10; s_int si2;
		s_long sl1;     char ch11; s_long sl2;
		s_long_long sll1;char ch12;s_long_long sll2;
		s_float sf1;    char ch13; s_float sf2;
		s_double sd1;   char ch14; s_double sd2;
		s_intp sp1;     char ch15; s_intp sp2;
	} foo;

  if (ch[0] == 0x01 && ch[1] == 0x02 && ch[2] == 0x03 && ch[3] == 0x04)
    printf("Big endian (%d %d %d %d)\n",     ch[0], ch[1], ch[2], ch[3]);
  else if (ch[0] == 0x04 && ch[1] == 0x03 && ch[2] == 0x02 && ch[3] == 0x01)
    printf("Little endian (%d %d %d %d)\n",  ch[0], ch[1], ch[2], ch[3]);
  else
    printf("Unknown endian (%d %d %d %d)\n", ch[0], ch[1], ch[2], ch[3]);

  printf("sizes:\n");
  printf("  char:      %ld\n", sizeof(char));
  printf("  short:     %ld\n", sizeof(short));
  printf("  int:       %ld\n", sizeof(int));
  printf("  long:      %ld\n", sizeof(long));
  printf("  long long: %ld\n", sizeof(long long));
  printf("  float:     %ld\n", sizeof(float));
  printf("  double:    %ld\n", sizeof(double));
  printf("  int*:      %ld\n", sizeof(int*));
  printf("alignments:\n");
  printf("  char:      %ld (%p %p %p)\n",
    (char*)&foo.c2  - (char*)&foo.c1  - sizeof(char),       &foo.c1,  &foo.ch0, &foo.c2);
  printf("  short:     %ld (%p %p %p)\n",
    (char*)&foo.s2  - (char*)&foo.s1  - sizeof(short),      &foo.s1,  &foo.ch3, &foo.s2);
  printf("  int:       %ld (%p %p %p)\n",
    (char*)&foo.i2  - (char*)&foo.i1  - sizeof(int),        &foo.i1,  &foo.ch4, &foo.i2);
  printf("  long:      %ld (%p %p %p)\n",
    (char*)&foo.l2  - (char*)&foo.l1  - sizeof(long),       &foo.l1,  &foo.ch7, &foo.l2);
  printf("  long long: %ld (%p %p %p)\n",
    (char*)&foo.ll2 - (char*)&foo.ll1 - sizeof(long long),  &foo.ll1, &foo.ch5, &foo.ll2);
  printf("  float:     %ld (%p %p %p)\n",
    (char*)&foo.f2  - (char*)&foo.f1  - sizeof(float),      &foo.f1,  &foo.ch2, &foo.f2);
  printf("  double:    %ld (%p %p %p)\n",
    (char*)&foo.d2  - (char*)&foo.d1  - sizeof(double),     &foo.d1,  &foo.ch1, &foo.d2);
  printf("  int*:      %ld (%p %p %p)\n",
    (char*)&foo.p2  - (char*)&foo.p1  - sizeof(int*),       &foo.p1,  &foo.ch6, &foo.p2);
  printf("structure alignments:\n");
  printf("  char struct:      %ld (%p %p %p)\n",
    (char*)&foo.sc2  - (char*)&foo.sc1  - sizeof(s_char),   &foo.sc1,  &foo.ch8, &foo.sc2);
  printf(" short struct:      %ld (%p %p %p)\n",
    (char*)&foo.ss2  - (char*)&foo.ss1  - sizeof(s_short),  &foo.ss1,  &foo.ch9, &foo.ss2);
  printf("   int struct:      %ld (%p %p %p)\n",
    (char*)&foo.si2  - (char*)&foo.si1  - sizeof(s_int),    &foo.si1,  &foo.ch10,&foo.si2);
  printf("  long struct:      %ld (%p %p %p)\n",
    (char*)&foo.sl2  - (char*)&foo.sl1  - sizeof(s_long),   &foo.sl1,  &foo.ch11,&foo.sl2);
  printf(" llong struct:      %ld (%p %p %p)\n",
    (char*)&foo.sll2  - (char*)&foo.sll1  - sizeof(s_long_long),&foo.sll1,&foo.ch12,&foo.sll2);
  printf(" float struct:      %ld (%p %p %p)\n",
    (char*)&foo.sf2  - (char*)&foo.sf1  - sizeof(s_float),  &foo.sf1,  &foo.ch13,&foo.sf2);
  printf("double struct:      %ld (%p %p %p)\n",
    (char*)&foo.sd2  - (char*)&foo.sd1  - sizeof(s_double), &foo.sd1,  &foo.ch14,&foo.sd2);
  printf("  int* struct:      %ld (%p %p %p)\n",
    (char*)&foo.sp2  - (char*)&foo.sp1  - sizeof(s_intp),   &foo.sp1,  &foo.ch15,&foo.sp2);

	return 0;
}
