ventajas resueltos programar lenguaje historia empezar ejercicios ejemplos dev desventajas como clases caracteristicas c++ c cross-platform portability

resueltos - ¿Qué pertenece a una herramienta educativa para demostrar las suposiciones injustificadas que las personas hacen en C/C++?



historia de dev c++ (23)

¡Muy interesante!

Otras cosas que puedo pensar podrían ser útiles para verificar:

  • ¿Los punteros de función y los punteros de datos existen en el mismo espacio de direcciones? (Se rompe en las máquinas de arquitectura de Harvard, como el modo pequeño de DOS. Sin embargo, no sé cómo lo probarías).

  • si toma un puntero de datos NULL y lo convierte al tipo de entero apropiado, ¿tiene el valor numérico 0? (Se rompe en algunas máquinas realmente antiguas --- vea http://c-faq.com/null/machexamp.html .) Ídem con puntero de función. Además, pueden ser valores diferentes.

  • ¿Incrementa un puntero más allá del final de su objeto de almacenamiento correspondiente y luego lo vuelve a generar resultados razonables? (No sé de ninguna máquina que realmente se rompa, pero creo que la especificación C no le permite siquiera pensar en punteros que no apuntan a (a) el contenido de una matriz o (b) el elemento inmediatamente después de la matriz o (c) NULL. Consulte http://c-faq.com/aryptr/non0based.html .)

  • ¿comparar dos punteros a diferentes objetos de almacenamiento con <y> producir resultados consistentes? (Puedo imaginar esta ruptura en máquinas basadas en segmentos exóticos, la especificación prohíbe tales comparaciones, por lo que el compilador tendría derecho a comparar la parte de desplazamiento del puntero solamente, y no la parte del segmento).

Hmm. Trataré de pensar en algunos más.

Editar: se agregaron algunos enlaces aclaratorios a las excelentes preguntas frecuentes de C.

Me gustaría preparar una pequeña herramienta educativa para SO, que debería ayudar a los programadores principiantes (e intermedios) a reconocer y desafiar sus suposiciones injustificadas en C, C ++ y sus plataformas.

Ejemplos:

  • "enteros envuelven"
  • "Todos tienen ASCII"
  • "Puedo almacenar un puntero a la función en un vacío *"

Pensé que un pequeño programa de prueba podría ejecutarse en varias plataformas, que ejecuta las suposiciones "plausibles" que, según nuestra experiencia en SO, usualmente hacen muchos desarrolladores convencionales sin experiencia o semiexperiencia y registran las formas en que se dividen en diversas máquinas.

El objetivo de esto no es probar que es "seguro" hacer algo (lo que sería imposible de hacer, las pruebas prueban solo cualquier cosa si se rompen), sino demostrarle al individuo más incomprendido cómo la expresión más discreta romper en una máquina diferente, si tiene un comportamiento definido o no definido. .

Para lograr esto, me gustaría preguntarle:

  • ¿Cómo se puede mejorar esta idea?
  • ¿Qué pruebas serían buenas y cómo deberían verse?
  • ¿Ejecutarías las pruebas en las plataformas en las que puedes tener acceso y publicarás los resultados, de modo que terminemos con una base de datos de plataformas, cómo difieren y por qué se permite esta diferencia?

Aquí está la versión actual para el juguete de prueba:

#include <stdio.h> #include <limits.h> #include <stdlib.h> #include <stddef.h> int count=0; int total=0; void expect(const char *info, const char *expr) { printf("..%s/n but ''%s'' is false./n",info,expr); fflush(stdout); count++; } #define EXPECT(INFO,EXPR) if (total++,!(EXPR)) expect(INFO,#EXPR) /* stack check..How can I do this better? */ ptrdiff_t check_grow(int k, int *p) { if (p==0) p=&k; if (k==0) return &k-p; else return check_grow(k-1,p); } #define BITS_PER_INT (sizeof(int)*CHAR_BIT) int bits_per_int=BITS_PER_INT; int int_max=INT_MAX; int int_min=INT_MIN; /* for 21 - left to right */ int ltr_result=0; unsigned ltr_fun(int k) { ltr_result=ltr_result*10+k; return 1; } int main() { printf("We like to think that:/n"); /* characters */ EXPECT("00 we have ASCII",(''A''==65)); EXPECT("01 A-Z is in a block",(''Z''-''A'')+1==26); EXPECT("02 big letters come before small letters",(''A''<''a'')); EXPECT("03 a char is 8 bits",CHAR_BIT==8); EXPECT("04 a char is signed",CHAR_MIN==SCHAR_MIN); /* integers */ EXPECT("05 int has the size of pointers",sizeof(int)==sizeof(void*)); /* not true for Windows-64 */ EXPECT("05a long has at least the size of pointers",sizeof(long)>=sizeof(void*)); EXPECT("06 integers are 2-complement and wrap around",(int_max+1)==(int_min)); EXPECT("07 integers are 2-complement and *always* wrap around",(INT_MAX+1)==(INT_MIN)); EXPECT("08 overshifting is okay",(1<<bits_per_int)==0); EXPECT("09 overshifting is *always* okay",(1<<BITS_PER_INT)==0); { int t; EXPECT("09a minus shifts backwards",(t=-1,(15<<t)==7)); } /* pointers */ /* Suggested by jalf */ EXPECT("10 void* can store function pointers",sizeof(void*)>=sizeof(void(*)())); /* execution */ EXPECT("11 Detecting how the stack grows is easy",check_grow(5,0)!=0); EXPECT("12 the stack grows downwards",check_grow(5,0)<0); { int t; /* suggested by jk */ EXPECT("13 The smallest bits always come first",(t=0x1234,0x34==*(char*)&t)); } { /* Suggested by S.Lott */ int a[2]={0,0}; int i=0; EXPECT("14 i++ is strictly left to right",(i=0,a[i++]=i,a[0]==1)); } { struct { char c; int i; } char_int; EXPECT("15 structs are packed",sizeof(char_int)==(sizeof(char)+sizeof(int))); } { EXPECT("16 malloc()=NULL means out of memory",(malloc(0)!=NULL)); } /* suggested by David Thornley */ EXPECT("17 size_t is unsigned int",sizeof(size_t)==sizeof(unsigned int)); /* this is true for C99, but not for C90. */ EXPECT("18 a%b has the same sign as a",((-10%3)==-1) && ((10%-3)==1)); /* suggested by nos */ EXPECT("19-1 char<short",sizeof(char)<sizeof(short)); EXPECT("19-2 short<int",sizeof(short)<sizeof(int)); EXPECT("19-3 int<long",sizeof(int)<sizeof(long)); EXPECT("20 ptrdiff_t and size_t have the same size",(sizeof(ptrdiff_t)==sizeof(size_t))); #if 0 { /* suggested by R. */ /* this crashed on TC 3.0++, compact. */ char buf[10]; EXPECT("21 You can use snprintf to append a string", (snprintf(buf,10,"OK"),snprintf(buf,10,"%s!!",buf),strcmp(buf,"OK!!")==0)); } #endif EXPECT("21 Evaluation is left to right", (ltr_fun(1)*ltr_fun(2)*ltr_fun(3)*ltr_fun(4),ltr_result==1234)); { #ifdef __STDC_IEC_559__ int STDC_IEC_559_is_defined=1; #else /* This either means, there is no FP support *or* the compiler is not C99 enough to define __STDC_IEC_559__ *or* the FP support is not IEEE compliant. */ int STDC_IEC_559_is_defined=0; #endif EXPECT("22 floating point is always IEEE",STDC_IEC_559_is_defined); } printf("From what I can say with my puny test cases, you are %d%% mainstream/n",100-(100*count)/total); return 0; }

Ah, e hice esta wiki de la comunidad desde el principio porque pensé que la gente quería editar mi blabber cuando leen esto.

ACTUALIZACIÓN Gracias por su aporte. He agregado algunos casos de tus respuestas y veré si puedo configurar un github para esto como sugirió Greg.

ACTUALIZACIÓN : he creado un repositorio github para esto, el archivo es "gotcha.c":

Responda aquí con parches o nuevas ideas, para que puedan ser discutidos o aclarados aquí. Los fusionaré en gotcha.c luego.


Algunos de ellos no se pueden probar fácilmente desde dentro de C porque es probable que el programa se bloquee en las implementaciones donde la suposición no es válida.

"Está bien hacer cualquier cosa con una variable con valor de puntero. Solo necesita contener un valor de puntero válido si lo desreferencia".

void noop(void *p); /* A no-op function that the compiler doesn''t know to optimize away */ int main () { char *p = malloc(1); free(p); noop(p); /* may crash in implementations that verify pointer accesses */ noop(p - 42000); /* and if not the previous instruction, maybe this one */ }

Lo mismo ocurre con los tipos de punto integral y flotante (que unsigned char ), que tienen representaciones de trampa.

"Los cálculos enteros se ajustan. Entonces, este programa imprime un entero negativo grande".

#include <stdio.h> int main () { printf("%d/n", INT_MAX+1); /* may crash due to signed integer overflow */ return 0; }

(C89 solamente). "Está bien caer al final de la pista main ".

#include <stdio.h> int main () { puts("Hello."); } /* The status code is 7 on many implementations. */


Aquí hay uno divertido: ¿Qué pasa con esta función?

float sum(unsigned int n, ...) { float v = 0; va_list ap; va_start(ap, n); while (n--) v += va_arg(ap, float); va_end(ap); return v; }

[Respuesta (rot13): Inevnqvp nethzragf borl gur byq X & E cebzbgvba ehyrf, juvpu zrnaf lbh pnaabg hfr ''sybng'' (ser ''pune'' ser ''fubeg'') va in_net! Naq gur pbzcvyre vf erdhverq abg gb gerng guvf nf n pbzcvyr-gvzr reebe. (TPP qbrf rzvg n jneavat, gubhtu.)]


Bueno, las suposiciones de portabilidad clásica que aún no se mencionan son

  • suposiciones sobre el tamaño de los tipos integrales
  • endianness

Creo que deberías hacer un esfuerzo para distinguir entre dos clases muy diferentes de suposiciones "incorrectas". Una buena mitad (desplazamiento a la derecha y extensión de señal, codificación compatible con ASCII, memoria lineal, indicadores de datos y funciones compatibles, etc.) son suposiciones bastante razonables para la mayoría de los codificadores C, e incluso podrían incluirse como parte del estándar. si C se estuviera diseñando hoy y si no tuviésemos IBM junk grandfathered-in heredado. La otra mitad (cosas relacionadas con el alias de memoria, el comportamiento de las funciones de biblioteca cuando se superponen la memoria de entrada y salida, suposiciones de 32 bits como punteros encajan en int o que puede usar malloc sin un prototipo, esa convención de llamadas es idéntica para variadis y non -funciones variables, ...) entran en conflicto con las optimizaciones que los compiladores modernos quieren realizar o con la migración a máquinas de 64 bits u otra tecnología nueva.


EDITAR: actualizado a la última versión del programa

Solaris-SPARC

gcc 3.4.6 en 32 bits

We like to think that: ..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. ..13 The smallest bits always come first but ''(t=0x1234,0x34==*(char*)&t)'' is false. ..14 i++ is strictly 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 72% mainstream

gcc 3.4.6 en 64 bit

We like to think that: ..05 int has the size of pointers but ''sizeof(int)==sizeof(void*)'' 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. ..13 The smallest bits always come first but ''(t=0x1234,0x34==*(char*)&t)'' is false. ..14 i++ is strictly 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. ..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 68% mainstream

y con SUNStudio 11 32 bit

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. ..13 The smallest bits always come first but ''(t=0x1234,0x34==*(char*)&t)'' is false. ..14 i++ is strictly 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. From what I can say with my puny test cases, you are 79% mainstream

and with SUNStudio 11 64 bit

We like to think that: ..05 int has the size of pointers but ''sizeof(int)==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. ..13 The smallest bits always come first but ''(t=0x1234,0x34==*(char*)&t)'' is false. ..14 i++ is strictly 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. From what I can say with my puny test cases, you are 75% mainstream


El orden de evaluación de las subexpresiones, incluido

  • los argumentos de una llamada de función y
  • operandos de operadores (p. ej., + , - , = , * , / ), con la excepción de:
    • los operadores lógicos binarios ( && y || ),
    • el operador condicional ternario ( ?: y
    • el operador de coma ( , )

no especificado

Por ejemplo

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; }


Hace mucho tiempo, yo estaba enseñando C de un libro de texto que tenía

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

como una pregunta de muestra. Falló para un alumno, ya que sizeof produce valores de tipo size_t , not int , int en esta implementación era de 16 bits y size_t era 32, y era big-endian. (La plataforma era Lightspeed C en Macintoshes basados ​​en 680x0. Dije que fue hace mucho tiempo).


Incluye un cheque para tamaños enteros. La mayoría de las personas asume que un int es más grande que un corto es más grande que un char. Sin embargo, estos podrían ser todos falsos: sizeof(char) < sizeof(int); sizeof(short) < sizeof(int); sizeof(char) < sizeof(short) sizeof(char) < sizeof(int); sizeof(short) < sizeof(int); sizeof(char) < sizeof(short)

Este código puede fallar (se bloquea el acceso desalineado)

unsigned char buf[64]; int i = 234; int *p = &buf[1]; *p = i; i = *p;


Necesita incluir el ++ y las suposiciones de las personas.

a[i++]= i;

Por ejemplo, es sintácticamente legal, pero produce resultados variables dependiendo de muchas cosas para razonar.

Cualquier declaración que tenga ++ (o -- ) y una variable que ocurra más de una vez es un problema.


Un par de cosas sobre los tipos de datos incorporados:

  • char y signed char son en realidad dos tipos distintos (a diferencia de int y signed int que hacen referencia al mismo tipo de entero con signo).
  • los enteros con signo no son necesarios para usar el complemento de dos. El complemento de uno y el signo + magnitud también son representaciones válidas de números negativos. Esto hace que las operaciones de bits que implican números negativos se definan como implementadas .
  • Si asigna un número entero fuera de rango a una variable entera con signo, el comportamiento está definido por la implementación .
  • En C90, -3/5 podría devolver 0 o -1 . Redondear hacia cero en caso de que un operando fuera negativo solo está garantizado en C99 hacia arriba y C ++ 0x hacia arriba.
  • No hay garantías de tamaño exactas para los tipos incorporados. El estándar solo cubre requisitos mínimos, como un int tiene al menos 16 bits, un long tiene al menos 32 bits, un long long tiene al menos 64 bits. Un float puede representar al menos 6 dígitos decimales más significativos correctamente. Un double puede representar al menos 10 dígitos decimales más significativos correctamente.
  • IEEE 754 no es obligatorio para representar números de coma flotante.

Es cierto que en la mayoría de las máquinas tendremos complemento dos y flotadores IEEE 754.


You can use text-mode ( fopen("filename", "r") ) to read any sort of text file.

While this should in theory work just fine, if you also use ftell() in your code, and your text file has UNIX-style line-endings, in some versions of the Windows standard library, ftell() will often return invalid values. The solution is to use binary mode instead ( fopen("filename", "rb") ).


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 se bloquea. "O_O"

gcc 4.4@x86_64-suse-linux

We like to think that: ..05 int has the size of pointers but ''sizeof(int)==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 strictly 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. ..26 sizeof() does not evaluate its arguments but ''(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 pointers but ''sizeof(int)==sizeof(void*)'' is false. ..08 overshifting is okay but ''(1<<bits_per_int)==0'' is false. ..14 i++ is strictly 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. ..26 sizeof() does not evaluate its arguments but ''(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 pointers but ''sizeof(int)==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 strictly 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. ..21a Function Arguments are evaluated right to left but ''(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 arrays but ''(diff=&p1-&p2, &p2+diff==&p1)'' is false. ..26 sizeof() does not evaluate its arguments but ''(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 pointers but ''sizeof(int)==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. ..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. ..21a Function Arguments are evaluated right to left but ''(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 arrays but ''(diff=&p1-&p2, &p2+diff==&p1)'' is false. ..26 sizeof() does not evaluate its arguments but ''(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 pointers but ''sizeof(int)==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 strictly 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. ..21a Function Arguments are evaluated right to left but ''(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 arguments but ''(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 / Memoria pequeña

We like to think that: ..09a minus shifts backwards but ''(t=-1,(15<<t)==7)'' is false. ..16 malloc()=NULL means out of memory but ''(malloc(0)!=NULL)'' 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. ..25a pointer arithmetic works outside arrays but ''(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 / Memoria Media

We like to think that: ..09a minus shifts backwards but ''(t=-1,(15<<t)==7)'' is false. ..10 void* can store function pointers but ''sizeof(void*)>=sizeof(void(*)())'' is false. ..16 malloc()=NULL means out of memory but ''(malloc(0)!=NULL)'' 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. ..25a pointer arithmetic works outside arrays but ''(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 / memoria compacta

We like to think that: ..05 int has the size of pointers but ''sizeof(int)==sizeof(void*)'' is false. ..09a minus shifts backwards but ''(t=-1,(15<<t)==7)'' is false. ..16 malloc()=NULL means out of memory but ''(malloc(0)!=NULL)'' is false. ..19-2 short<int but ''sizeof(short)<sizeof(int)'' is false. ..20 ptrdiff_t and size_t have the same size but ''(sizeof(ptrdiff_t)==sizeof(size_t))'' 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. ..25a pointer arithmetic works outside arrays but ''(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 emulador)

texto alternativo http://i34.tinypic.com/2hh0zmc.png

Los actualizaré más tarde:

Borland C ++ Builder 6.0 en 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

(debe compilarse como C ++ porque el compilador CLR no admite C puro)

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 usa el modelo LLP64: tanto int como long están definidos como 32 bits, lo que significa que ninguno es lo suficientemente largo para un puntero.

avr-gcc 4.3.2 / ATmega168 (Arduino Diecimila)

Las suposiciones fallidas son:

..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

El Atmega168 tiene una PC de 16 bits, pero el código y los datos están en espacios de direcciones separados. Los Atmegas más grandes tienen una PC de 22 bits.

gcc 4.2.1 en MacOSX 10.6, compilado con -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


An assumption that some may do in C++ is that a struct is limited to what it can do in C. The fact is that, in C++, a struct is like a class except that it has everything public by default.

C++ struct:

struct Foo { int number1_; //this is public by default //this is valid in C++: private: void Testing1(); int number2_; protected: void Testing2(); };


FYI, For those who have to translate their C skills to Java, here are a few gotchas.

EXPECT("03 a char is 8 bits",CHAR_BIT==8); EXPECT("04 a char is signed",CHAR_MIN==SCHAR_MIN);

In Java, char is 16-bit and signed. byte is 8-bit and signed.

/* not true for Windows-64 */ EXPECT("05a long has at least the size of pointers",sizeof(long)>=sizeof(void*));

long siempre es de 64 bits, las referencias pueden ser de 32 bits o de 64 bits (si tiene más de una aplicación con más de 32 GB) las JVM de 64 bits suelen usar referencias de 32 bits.

EXPECT("08 overshifting is okay",(1<<bits_per_int)==0); EXPECT("09 overshifting is *always* okay",(1<<BITS_PER_INT)==0);

El cambio está enmascarado de modo que i << 64 == i == i << -64, i << 63 == i << -1

EXPECT("13 The smallest bits always come first",(t=0x1234,0x34==*(char*)&t));

ByteOrder.nativeOrder () puede ser BIG_ENDIAN o LITTLE_ENDIAN

EXPECT("14 i++ is strictly left to right",(i=0,a[i++]=i,a[0]==1));

i = i++ nunca cambia i

/* suggested by David Thornley */ EXPECT("17 size_t is unsigned int",sizeof(size_t)==sizeof(unsigned int));

El tamaño de las colecciones y matrices siempre es de 32 bits, independientemente de si la JVM es de 32 bits o de 64 bits.

EXPECT("19-1 char<short",sizeof(char)<sizeof(short)); EXPECT("19-2 short<int",sizeof(short)<sizeof(int)); EXPECT("19-3 int<long",sizeof(int)<sizeof(long));

char es de 16 bits, short de 16 bits, int de 32 bits y long de 64 bits.


How about right-shifting by excessive amounts--is that allowed by the standard, or worth testing?

Does Standard C specify the behavior of the following program:

void print_string(char *st) { char ch; while((ch = *st++) != 0) putch(ch); /* Assume this is defined */ } int main(void) { print_string("Hello"); return 0; }

On at least one compiler I use, that code will fail unless the argument to print_string is a "char const *". Does the standard permit such a restriction?

Some systems allow one to produce pointers to unaligned ''int''s and others don''t. Might be worth testing.


How about this one:

No data pointer can ever be the same as a valid function pointer.

This is TRUE for all flat models, MS-DOS TINY, LARGE, and HUGE models, false for MS-DOS SMALL model, and almost always false for MEDIUM and COMPACT models (depends on load address, you will need a really old DOS to make it true).

I can''t write a test for this

And worse: pointers casted to ptrdiff_t may be compared. This not true for MS-DOS LARGE model (the only difference between LARGE and HUGE is HUGE adds compiler code to normalize pointers).

I can''t write a test because the environment where this bombs hard won''t allocate a buffer greater than 64K so the code that demonstrates it would crash on other platforms.

This particular test would pass on one now-defunct system (notice it depends on the internals of malloc):

char *ptr1 = malloc(16); char *ptr2 = malloc(16); if ((ptrdiff_t)ptr2 - 0x20000 == (ptrdiff_t)ptr1) printf("We like to think that unrelated pointers are equality comparable when cast to the appropriate integer, but they''re not.");


Standard math functions on different systems don''t give identical results.


Via Codepad.org ( C++: g++ 4.1.2 flags: -O -std=c++98 -pedantic-errors -Wfatal-errors -Werror -Wall -Wextra -Wno-missing-field-initializers -Wwrite-strings -Wno-deprecated -Wno-unused -Wno-non-virtual-dtor -Wno-variadic-macros -fmessage-length=0 -ftemplate-depth-128 -fno-merge-constants -fno-nonansi-builtins -fno-gnu-keywords -fno-elide-constructors -fstrict-aliasing -fstack-protector-all -Winvalid-pch ) .

Note that Codepad did not have stddef.h . I removed test 9 due to codepad using warnings as errors. I also renamed the count variable since it was already defined for some reason.

We like to think that: ..08 overshifting is okay but ''(1<<bits_per_int)==0'' 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. From what I can say with my puny test cases, you are 84% mainstream


Visual Studio Express 2010 on 32-bit x86.

Z:/sandbox>cl testtoy.c Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. testtoy.c testtoy.c(54) : warning C4293: ''<<'' : shift count negative or too big, undefined behavior Microsoft (R) Incremental Linker Version 10.00.30319.01 Copyright (C) Microsoft Corporation. All rights reserved. /out:testtoy.exe testtoy.obj Z:/sandbox>testtoy.exe 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


gcc 3.3.2 on AIX 5.3 (yeah, we need to update gcc)

We like to think that: ..04 a char is signed but ''CHAR_MIN==SCHAR_MIN'' is false. ..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. ..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


EXPECT("## pow() gives exact results for integer arguments", pow(2, 4) == 16);

Otra es sobre el modo texto en fopen . La mayoría de los programadores asumen que el texto y el binario son los mismos (Unix) o que el modo de texto agrega /r caracteres (Windows). Pero C ha sido portado a sistemas que usan registros de ancho fijo, en los cuales fputc(''/n'', file) en un archivo de texto significa agregar espacios o algo hasta que el tamaño del archivo sea un múltiplo de la longitud del registro.

Y aquí están mis resultados:

gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3 en x86-64

We like to think that: ..05 int has the size of pointers but ''sizeof(int)==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 strictly 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. From what I can say with my puny test cases, you are 78% mainstream


  • Errores de discretización debido a la representación de coma flotante. Por ejemplo, si utiliza la fórmula estándar para resolver ecuaciones cuadráticas, o diferencias finitas para derivadas aproximadas, o la fórmula estándar para calcular las variaciones, la precisión se perderá debido al cálculo de las diferencias entre números similares. El algoritmo Gauß para resolver sistemas lineales es malo porque se acumulan errores de redondeo, por lo que uno usa descomposición QR o LU, descomposición de Cholesky, SVD, etc. La suma de números de coma flotante no es asociativa. Hay valores denormal, infinito y NaN. a + b - ab .

  • Cadenas: diferencia entre caracteres, puntos de código y unidades de código. Cómo se implementa Unicode en los diversos sistemas operativos; Codificaciones Unicode. No es posible abrir un archivo con un nombre de archivo Unicode arbitrario con C ++ de forma portátil.

  • Condiciones de carrera, incluso sin enhebrar: si comprueba si existe un archivo, el resultado podría perder validez en cualquier momento.

  • ERROR_SUCCESS = 0