2012-05-17 12 views
6

Miałem nadzieję, że ktoś może wyjaśnić dlaczegoJeśli bool jest makrem dla int, dlaczego ma inny rozmiar?

#include <stdbool.h> 

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

wyjścia do

size of bool 1 
size of int 4 

Szukałem na http://pubs.opengroup.org/onlinepubs/009695399/basedefs/stdbool.h.html co wydaje się wskazywać, że bool jest zasadniczo dla _Bool makro, które po ustawieniu wartości true lub false, tak naprawdę jest tylko makrem dla stałej liczb całkowitych. Jeśli jest liczbą całkowitą, dlaczego nie ma tego samego rozmiaru?

Pytam, ponieważ zajęło nam zbyt dużo czasu, aby debugować program, dla którego nie przydzieliliśmy wystarczającej ilości pamięci.

+1

Po prostu ciekawy - jeśli "bool" jest * mniejszy * niż się spodziewałeś, w jaki sposób nie przydzieliłeś wystarczającej ilości pamięci? – detly

+0

@detly Cóż, szczerze mówiąc nie jesteśmy pewni. Mieliśmy tablicę 'bool', która zawsze powodowała błąd segmentacji aż do pomnożenia' malloc (x * sizeof (bool)) 'malloc (4 * x * sizeof (bool))' To mogło być coś całkowicie inny, ale to rozwiązało problem i doprowadziło mnie do tego pytania. – NickO

+0

Czy zadeklarowałeś 'bool *'? Nie mamy wiele do zrobienia bez kodu, chociaż to prawdopodobnie byłoby oddzielne pytanie (i brzmi to tak, jakbyś przydzielił dla 'bool', ale pisanie większych obiektów do przydzielonego magazynu. – birryree

Odpowiedz

11

typu _Bool w C99 (typedef „wyd do bool w stdbool.h) nie ma standardowego określonej wielkości, ale według części 6.2.5 standardu C99:

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

do C, najmniejszym adresowalnym obiektem (oprócz bitfieldów) jest char, który ma co najmniej 8-bitową szerokość, a sizeof(char) jest zawsze 1.

_Bool i bool zatem mieć sizeof przynajmniej 1, aw większości implementacji, które widziałem, sizeof(bool)/sizeof(_Bool) jest 1.

Jeśli przyjrzeć GCC stdbool.h, dostaniesz to:

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

#define false 0 
#define true 1 

Więc jeśli używasz starszej wersji GCC i starą wersję standardu C podczas kompilacji, to użyje int jako typ _Bool.

Oczywiście, jak ciekawa rzecz, to sprawdzić:

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

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

} 

wyjściowa:

λ > ./a.out 
1 
4 
4 

GCC 4.2.4, Clang 3.0, GCC 4.7.0 i wszystkie wyjścia takie same. Jak wskazują trynita, sizeof(true) i sizeof(false) wytwarzają większe rozmiary, ponieważ przyjmują rozmiar literału int, co najmniej sizeof(int).

+0

Dziękuję za odpowiedź.Wciąż zaczynam od C i nauczyłem się dużo więcej z twojej odpowiedzi niż tylko odpowiedzi na pytanie. – NickO

+0

Wielkość ma sens, ponieważ są # definicje dla literałów. Rozmiar int literału jest sizeof int. true i false są int literałami w tym przypadku. –

+0

@trinithis - tak, chciałem zwrócić uwagę na różne rozmiary, które uzyskałbyś, gdybyś spróbował przeciwko typowi w porównaniu do innych makr dostarczonych przez nagłówek. – birryree

1

Jestem prawie pewny, że jest zależny od twojego kompilatora, może twój używa bajta zamiast int dla bool? Tak czy inaczej nie powinieneś mieć problemów z przydzielaniem pamięci, jeśli używasz sizeof(), aby wiedzieć, ile pamięci chcesz przydzielić, na przykład, jeśli chcesz przydzielić 10 wartości pamięci, nie przydzielaj 10 * 4, czy 10 * sizeof (bool), więc nie możesz się pomylić.

2

Standard C99 wprowadził typ _Bool. _Bool gwarantuje, że jest wystarczająco duży, aby utrzymać stałe w liczbach całkowitych 0 lub 1, nie oznacza to, że jest to int. Rzeczywisty rozmiar zależy od kompilatora.

0

_Bool jest natywny dla kompilatora, jest zdefiniowany w C99 i może być aktywowany jak gcc -std=c99; stdbool.h #define bool to _Bool, i true i false, aby po prostu int literały, które całkiem dobrze pasują do tego _Boola.

1

Jest to liczba całkowita, ale nie jest to int. char, short, int, long, long long itp., Są to liczby całkowite. char ma gwarantowaną wielkość 1. Reszta jest co najmniej tak duża, jak char (i trudno sobie wyobrazić, jak byś działał poprawnie, gdyby int był nie większy niż char). Istnieje również wymagane zamówienie od char do long long (w tej samej kolejności wymieniono je powyżej), gdzie każdy typ musi mieć co najmniej tyle samo zasięgu, co jego poprzedniki.

Poza tym, nie masz gwarancji co do rozmiarów typów całkowitych. W szczególności, char jest jedynym z typów "podstawowych", który ma gwarantowany rozmiar (chociaż istnieją typy takie jak int8_t i int32_t, które mają gwarantowane rozmiary).

1

Jak wiem od przeniesienia kodu z systemu Windows do systemu Unix, nigdy nie można mieć pewności co do wielkości typu danych. Zależy to od systemu operacyjnego, a czasami nawet od używanego kompilatora.

Specyfikacja stdbool.h mówi tylko, że PRAWDA i FAŁSZ są odwzorowane na liczbę całkowitą (1 i 0). Nie oznacza to, że typ bool jest typu int. Z mojego doświadczenia bool jest najmniejszym dostępnym typem danych (tj char lub bajt):

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

w Eclipse CDT i Visual Studio można śledzić definicje makr, aby zobaczyć, co naprawdę kryje się za swoimi typów danych.

Więc proponuję zawsze poprosić kompilator o miejsca pamięci potrzebnej w celu przydzielenia wystarczającej ilości pamięci (To jest także to, co widziałem w wielu bibliotekach):

malloc(4*sizeof(bool)); 

Mam nadzieję, że to pomaga.

+0

Interesujące. Nie wiedziałem, że można śledzić definicje makr w czasie zaćmienia. Zawsze jest miło nauczyć się czegoś więcej niż tylko odpowiedzi na oryginalne pytanie! – NickO

Powiązane problemy