What belongs in an educational tool to demonstrate the unwarranted assumptions people make in C/C++? What belongs in an educational tool to demonstrate the unwarranted assumptions people make in C/C++? c c

What belongs in an educational tool to demonstrate the unwarranted assumptions people make in C/C++?


The order of evaluation of subexpressions, including

  • the arguments of a function call and
  • operands of operators (e.g., +, -, =, * , /), with the exception of:
    • the binary logical operators (&& and ||),
    • the ternary conditional operator (?:), and
    • the comma operator (,)

is Unspecified

For example

  int Hello()  {       return printf("Hello"); /* printf() returns the number of                                   characters successfully printed by it                               */  }  int World()  {       return printf("World !");  }  int main()  {      int a = Hello() + World(); //might print Hello World! or World! Hello      /**             ^                      |                 Functions can be called in either order      **/      return 0;  } 



sdcc 29.7/ucSim/Z80

We like to think that:..09a minus shifts backwards   but '(t=-1,(15<<t)==7)' is false...19-2 short<int   but 'sizeof(short)<sizeof(int)' is false...22 floating point is always IEEE   but 'STDC_IEC_559_is_defined' is false...25 pointer arithmetic works outside arrays   but '(diff=&var.int2-&var.int1, &var.int1+diff==&var.int2)' is false.From what I can say with my puny test cases, you are Stop at 0x0013f3: (106) Invalid instruction 0x00dd

printf crashes. "O_O"


gcc 4.4@x86_64-suse-linux

We like to think that:..05 int has the size of pointersbut 'sizeof(int)==sizeof(void*)' is false...08 overshifting is okaybut '(1<<bits_per_int)==0' is false...09a minus shifts backwardsbut '(t=-1,(15<<t)==7)' is false...14 i++ is strictly left to rightbut '(i=0,a[i++]=i,a[0]==1)' is false...15 structs are packedbut 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false...17 size_t is unsigned intbut 'sizeof(size_t)==sizeof(unsigned int)' is false...26 sizeof() does not evaluate its argumentsbut '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.From what I can say with my puny test cases, you are 79% mainstream

gcc 4.4@x86_64-suse-linux(-O2)

We like to think that:..05 int has the size of pointersbut 'sizeof(int)==sizeof(void*)' is false...08 overshifting is okaybut '(1<<bits_per_int)==0' is false...14 i++ is strictly left to rightbut '(i=0,a[i++]=i,a[0]==1)' is false...15 structs are packedbut 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false...17 size_t is unsigned intbut 'sizeof(size_t)==sizeof(unsigned int)' is false...26 sizeof() does not evaluate its argumentsbut '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.From what I can say with my puny test cases, you are 82% mainstream

clang 2.7@x86_64-suse-linux

We like to think that:..05 int has the size of pointersbut 'sizeof(int)==sizeof(void*)' is false...08 overshifting is okaybut '(1<<bits_per_int)==0' is false...09a minus shifts backwardsbut '(t=-1,(15<<t)==7)' is false...14 i++ is strictly left to rightbut '(i=0,a[i++]=i,a[0]==1)' is false...15 structs are packedbut 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false...17 size_t is unsigned intbut 'sizeof(size_t)==sizeof(unsigned int)' is false...21a Function Arguments are evaluated right to leftbut '(gobble_args(0,ltr_fun(1),ltr_fun(2),ltr_fun(3),ltr_fun(4)),ltr_result==4321)' is false.ltr_result is 1234 in this case..25a pointer arithmetic works outside arraysbut '(diff=&p1-&p2, &p2+diff==&p1)' is false...26 sizeof() does not evaluate its argumentsbut '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.From what I can say with my puny test cases, you are 72% mainstream

open64 4.2.3@x86_64-suse-linux

We like to think that:..05 int has the size of pointersbut 'sizeof(int)==sizeof(void*)' is false...08 overshifting is okaybut '(1<<bits_per_int)==0' is false...09a minus shifts backwardsbut '(t=-1,(15<<t)==7)' is false...15 structs are packedbut 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false...17 size_t is unsigned intbut 'sizeof(size_t)==sizeof(unsigned int)' is false...21a Function Arguments are evaluated right to leftbut '(gobble_args(0,ltr_fun(1),ltr_fun(2),ltr_fun(3),ltr_fun(4)),ltr_result==4321)' is false.ltr_result is 1234 in this case..25a pointer arithmetic works outside arraysbut '(diff=&p1-&p2, &p2+diff==&p1)' is false...26 sizeof() does not evaluate its argumentsbut '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.From what I can say with my puny test cases, you are 75% mainstream

intel 11.1@x86_64-suse-linux

We like to think that:..05 int has the size of pointersbut 'sizeof(int)==sizeof(void*)' is false...08 overshifting is okaybut '(1<<bits_per_int)==0' is false...09a minus shifts backwardsbut '(t=-1,(15<<t)==7)' is false...14 i++ is strictly left to rightbut '(i=0,a[i++]=i,a[0]==1)' is false...15 structs are packedbut 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false...17 size_t is unsigned intbut 'sizeof(size_t)==sizeof(unsigned int)' is false...21a Function Arguments are evaluated right to leftbut '(gobble_args(0,ltr_fun(1),ltr_fun(2),ltr_fun(3),ltr_fun(4)),ltr_result==4321)' is false.ltr_result is 1234 in this case..26 sizeof() does not evaluate its argumentsbut '(i=10,sizeof(char[((i=20),10)]),i==10)' is false.From what I can say with my puny test cases, you are 75% mainstream

Turbo C++/DOS/Small Memory

We like to think that:..09a minus shifts backwardsbut '(t=-1,(15<<t)==7)' is false...16 malloc()=NULL means out of memorybut '(malloc(0)!=NULL)' is false...19-2 short<intbut 'sizeof(short)<sizeof(int)' is false...22 floating point is always IEEEbut 'STDC_IEC_559_is_defined' is false...25 pointer arithmetic works outside arraysbut '(diff=&var.int2-&var.int1, &var.int1+diff==&var.int2)' is false...25a pointer arithmetic works outside arraysbut '(diff=&p1-&p2, &p2+diff==&p1)' is false.From what I can say with my puny test cases, you are 81% mainstream

Turbo C++/DOS/Medium Memory

We like to think that:..09a minus shifts backwardsbut '(t=-1,(15<<t)==7)' is false...10 void* can store function pointersbut 'sizeof(void*)>=sizeof(void(*)())' is false...16 malloc()=NULL means out of memorybut '(malloc(0)!=NULL)' is false...19-2 short<intbut 'sizeof(short)<sizeof(int)' is false...22 floating point is always IEEEbut 'STDC_IEC_559_is_defined' is false...25 pointer arithmetic works outside arraysbut '(diff=&var.int2-&var.int1, &var.int1+diff==&var.int2)' is false...25a pointer arithmetic works outside arraysbut '(diff=&p1-&p2, &p2+diff==&p1)' is false.From what I can say with my puny test cases, you are 78% mainstream

Turbo C++/DOS/Compact Memory

We like to think that:..05 int has the size of pointersbut 'sizeof(int)==sizeof(void*)' is false...09a minus shifts backwardsbut '(t=-1,(15<<t)==7)' is false...16 malloc()=NULL means out of memorybut '(malloc(0)!=NULL)' is false...19-2 short<intbut 'sizeof(short)<sizeof(int)' is false...20 ptrdiff_t and size_t have the same sizebut '(sizeof(ptrdiff_t)==sizeof(size_t))' is false...22 floating point is always IEEEbut 'STDC_IEC_559_is_defined' is false...25 pointer arithmetic works outside arraysbut '(diff=&var.int2-&var.int1, &var.int1+diff==&var.int2)' is false...25a pointer arithmetic works outside arraysbut '(diff=&p1-&p2, &p2+diff==&p1)' is false.From what I can say with my puny test cases, you are 75% mainstream

cl65@Commodore PET (vice emulator)

alt text


I'll be updating these later:


Borland C++ Builder 6.0 on Windows XP

..04 a char is signed   but 'CHAR_MIN==SCHAR_MIN' is false...08 overshifting is okay   but '(1<<bits_per_int)==0' is false...09 overshifting is *always* okay   but '(1<<BITS_PER_INT)==0' is false...09a minus shifts backwards   but '(t=-1,(15<<t)==7)' is false...15 structs are packed   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false...16 malloc()=NULL means out of memory   but '(malloc(0)!=NULL)' is false...19-3 int<long   but 'sizeof(int)<sizeof(long)' is false...22 floating point is always IEEE   but 'STDC_IEC_559_is_defined' is false.From what I can say with my puny test cases, you are 71% mainstream

Visual Studio Express 2010 C++ CLR, Windows 7 64bit

(must be compiled as C++ because the CLR compiler does not support pure C)

We like to think that:..08 overshifting is okay   but '(1<<bits_per_int)==0' is false...09a minus shifts backwards   but '(t=-1,(15<<t)==7)' is false...14 i++ is structly left to right   but '(i=0,a[i++]=i,a[0]==1)' is false...15 structs are packed   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false...19-3 int<long   but 'sizeof(int)<sizeof(long)' is false...22 floating point is always IEEE   but 'STDC_IEC_559_is_defined' is false.From what I can say with my puny test cases, you are 78% mainstream

MINGW64 (gcc-4.5.2 prerelase)

-- http://mingw-w64.sourceforge.net/

We like to think that:..05 int has the size of pointers   but 'sizeof(int)==sizeof(void*)' is false...05a long has at least the size of pointers   but 'sizeof(long)>=sizeof(void*)' is false...08 overshifting is okay   but '(1<<bits_per_int)==0' is false...09a minus shifts backwards   but '(t=-1,(15<<t)==7)' is false...14 i++ is structly left to right   but '(i=0,a[i++]=i,a[0]==1)' is false...15 structs are packed   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false...17 size_t is unsigned int   but 'sizeof(size_t)==sizeof(unsigned int)' is false...19-3 int<long   but 'sizeof(int)<sizeof(long)' is false...22 floating point is always IEEE   but 'STDC_IEC_559_is_defined' is false.From what I can say with my puny test cases, you are 67% mainstream

64 bit Windows uses the LLP64 model: Both int and long are defined as 32-bit, which means that neither is long enough for a pointer.


avr-gcc 4.3.2 / ATmega168 (Arduino Diecimila)

The failed assumptions are:

..14 i++ is structly left to right..16 malloc()=NULL means out of memory..19-2 short<int..21 Evaluation is left to right..22 floating point is always IEEE

The Atmega168 has a 16 bit PC, but code and data are in separate address spaces. Larger Atmegas have a 22 bit PC!.


gcc 4.2.1 on MacOSX 10.6, compiled with -arch ppc

We like to think that:..09a minus shifts backwards   but '(t=-1,(15<<t)==7)' is false...13 The smallest bits come always first   but '(t=0x1234,0x34==*(char*)&t)' is false...14 i++ is structly left to right   but '(i=0,a[i++]=i,a[0]==1)' is false...15 structs are packed   but 'sizeof(char_int)==(sizeof(char)+sizeof(int))' is false...19-3 int<long   but 'sizeof(int)<sizeof(long)' is false...22 floating point is always IEEE   but 'STDC_IEC_559_is_defined' is false.From what I can say with my puny test cases, you are 78% mainstream


A long time ago, I was teaching C from a textbook that had

printf("sizeof(int)=%d\n", sizeof(int));

as a sample question. It failed for a student, because sizeof yields values of type size_t, not int, int on this implementation was 16 bits and size_t was 32, and it was big-endian. (The platform was Lightspeed C on 680x0-based Macintoshes. I said it was a long time ago.)