2012-05-17 9 views
6

alguien que estaba esperando podría explicar por quéSi bool es una macro para int, ¿por qué es un tamaño diferente?

#include <stdbool.h> 

printf("size of bool %d\n", sizeof(bool)); 
printf("size of int %d\n", sizeof(int)); 

salidas a

size of bool 1 
size of int 4 

He mirado en http://pubs.opengroup.org/onlinepubs/009695399/basedefs/stdbool.h.html lo que parece indicar que bool es esencialmente una macro para _Bool que, cuando se define como true o falso, es realmente solo una macro para una constante entera. Si es un número entero, ¿por qué no tiene el mismo tamaño?

Lo estoy preguntando porque nos llevó demasiado tiempo depurar un programa para el que no asignamos suficiente memoria.

+1

Simplemente curioso: si un 'bool' es * más pequeño * de lo que esperaba, ¿cómo no asignó suficiente memoria? – detly

+0

@detly Bueno, para ser sincero, no estamos seguros. Teníamos una matriz de 'bool' que siempre producía una falla de segmentación hasta que multiplicamos el' malloc (x * sizeof (bool)) 'por' malloc (4 * x * sizeof (bool)) 'Podría haber sido algo completamente diferente, pero eso resolvió el problema y me llevó a esta pregunta. – NickO

+0

¿Declaraste un 'bool *'? No tenemos mucho que seguir sin el código, aunque probablemente sea una pregunta aparte (y parece que usted ha estado asignando para 'bool' pero escribiendo objetos más grandes en el almacenamiento asignado. – birryree

Respuesta

11

El tipo _Bool en C99 (typedef 'ed a bool en stdbool.h) no tiene un tamaño estándar definido, pero de acuerdo con la sección 6.2.5 de la Norma C99:

2 An object declared as type _Bool is large enough to store the values 0 and 1. 

En C, la el objeto direccionable más pequeño (aparte de los campos de bits) es el char, que tiene al menos 8 bits de ancho, y sizeof(char) siempre es 1.

_Bool y por lo tanto tienen una boolsizeof de al menos 1, y en la mayoría de las implementaciones que he visto, sizeof(bool)/sizeof(_Bool) es 1.

Si se echa un vistazo a GCC de stdbool.h, obtendrá esto:

#define bool _Bool 
#if __STDC_VERSION__ < 199901L && __GNUC__ < 3 
typedef int _Bool; 
#endif 

#define false 0 
#define true 1 

Así que si se utiliza una versión antigua de GCC y una versión antigua de la norma C al compilar, que va a utilizar int como un tipo _Bool.

Por supuesto, como una cosa interesante, mira esto:

#include <stdio.h> 
#include <stdbool.h> 

int main() { 
    printf("%zu\n", sizeof(_Bool)); 
    printf("%zu\n", sizeof(true)); 
    printf("%zu\n", sizeof(false)); 

} 

Salida:

λ > ./a.out 
1 
4 
4 

GCC 4.2.4, 3.0 Sonido metálico, y GCC 4.7.0 toda la salida de la misma. Como señala Trinithis, sizeof(true) y sizeof(false) producen tamaños más grandes porque toman el tamaño de un int literal, que es al menos sizeof(int).

+0

Gracias por la respuesta.Todavía estoy empezando con C y he aprendido mucho más de su respuesta que simplemente la respuesta a la pregunta. – NickO

+0

El tamaño de tiene sentido porque son #defines para int literales. El tamaño de un int literal es sizeof int. verdadero y falso son int literales en este caso. –

+0

@trinithis - Sí, solo quería llamar la atención sobre los diferentes 'tamaños' que obtendría si lo intentara contra el tipo frente a las otras macros proporcionadas por el encabezado. – birryree

1

Estoy bastante seguro de que depende de tu compilador, ¿quizás el tuyo está utilizando byte en lugar de int para bool? De cualquier forma, no deberías tener problemas de asignación de memoria si usas sizeof() para saber cuánta memoria asignar, por ejemplo, si quieres asignar 10 bools de memoria, no asignes 10 * 4, haz 10 * sizeof (bool) por lo que no puedes equivocarte.

2

C99 estándar introdujo el tipo _Bool. _Bool se garantiza que es lo suficientemente grande como para contener constantes enteras 0 o 1, esto no necesariamente significa que es un int. El tamaño real depende del compilador.

0

El _Bool es nativo del compilador, se define en C99 y se puede activar como gcc -std=c99; stdbool.h #define bool para ser _Bool, y verdadero y falso simplemente int literales que encajan muy bien en ese _Bool.

1

Se es un número entero, pero no un int. char, short, int, long, long long, etc., son todos los números enteros. char se garantiza que tiene un tamaño de 1. El resto es al menos tan grande como char (y es difícil imaginar cómo haría que el sistema de E/S funcione correctamente si int no era más grande que char). También hay un pedido obligatorio de char a long long (el mismo orden en que los enumeré arriba) donde cada tipo debe tener al menos el mismo rango que sus predecesores.

Aparte de eso, sin embargo, usted no está garantizada tanto de tamaños de los tipos enteros. Específicamente, char es el único de los tipos "base" que tiene un tamaño garantizado (aunque hay tipos como int8_t y int32_t que tienen tamaños garantizados).

1

como sé por portar código de Windows a Unix que nunca puede estar seguro sobre el tamaño de un tipo de datos. Depende del sistema operativo y, a veces, incluso del compilador que utilice.

Las especificaciones de stdbool.h solamente dicen que VERDADERO y FALSO se asignan a un número entero (1 y 0). Esto no significa que el tipo de datos bool sea de tipo int. Desde mi experiencia bool es del tipo de datos más pequeño disponible (es decir, carbón o byte):

bool flag = TRUE; -> byte flag = 0x01; 

en Eclipse CDT y Visual Studio puede seguir las definiciones de macros con el fin de ver lo que realmente hay detrás de sus tipos de datos.

así que yo sugeriría que siempre pregunte a su compilador sobre el espacio de memoria necesaria con el fin de asignar suficiente memoria (Esto es también lo que vi en una gran cantidad de bibliotecas):

malloc(4*sizeof(bool)); 

espero que esto ayude.

+0

Interesante. No sabía que podía seguir las definiciones de macro en eclipse. ¡Siempre es bueno aprender mucho más que la respuesta a la pregunta original! – NickO

Cuestiones relacionadas