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 (
,
)
- los operadores lógicos binarios (
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
ysigned char
son en realidad dos tipos distintos (a diferencia deint
ysigned 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 devolver0
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, unlong
tiene al menos 32 bits, unlong long
tiene al menos 64 bits. Unfloat
puede representar al menos 6 dígitos decimales más significativos correctamente. Undouble
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 - a ≠ b .
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