2013-01-05 15 views
23

Próbowałem wykonawczych operatora sizeof .. Zrobiłem w ten sposób ..implementacja operatora sizeof

#define my_sizeof(x) ((&x + 1) - &x) 

Ale to zawsze kończyło się podając wynik jako „1” dla jednej z typem danych ..

mam wtedy google go za to .. i znalazłem kod typecasted

#define my_size(x) ((char *)(&x + 1) - (char *)&x) 

i kod działa, jeśli jest typecasted .. i d ONT zrozumieć dlaczego .. Kod ten jest również wyściółka STRUKTURY doskonale ..

Jest również pracuje dla

#define my_sizeof(x) (unsigned int)(&x + 1) - (unsigned int)(&x) 

Może ktoś proszę wyjaśnić, jak to działa, jeśli typecasted a jeśli nie typecasted?

góry dzięki ..

+3

Przesyłanie do 'unsigned int' jest złym pomysłem. "uintptr_t" jest lepsze, ale nadal wymaga denerwującej, ale nieuniknionej, niejawnej konwersji. –

Odpowiedz

26

Wynik odejmowania wskaźnika jest w elementach, a nie w bajtach. Zatem pierwsze wyrażenie z definicji przyjmuje wartość 1.

to na bok, tak naprawdę powinno się używać nawiasów w makrach:

#define my_sizeof(x) ((&x + 1) - &x) 
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x) 

przeciwnym razie próbuje użyć my_sizeof() w wyrażeniu może prowadzić do błędów.

+0

Położyłem nawias .. Ale działało też, gdybym ... .. –

+12

Makra są beznadziejne, jako sposób na zastąpienie 'sizeof'. Oceniają argument (również dwa razy) ... Pomyśl o 'my_sizeof (x ++)'. – Mat

+0

@Mat: tak .. Mam to .. :) –

5

Ale to zawsze kończyło się podając wynik jako „1” dla jednej z typem danych

Tak, to jak działa wskaźnik arytmetyczne. Działa w jednostkach wskazanego typu. Tak więc odlewanie do char * działa jednostek char, co jest tym, czego potrzebujesz.

5

Operator jest częścią specyfikacji języka C (i C++) i jest implementowany wewnątrz kompilatora (front-end). Nie ma sposobu, aby zaimplementować go z innymi konstrukcjami C (chyba że używasz rozszerzeń GCC, takich jak typeof), ponieważ może akceptować typy lub wyrażenia jako operand, bez żadnych efektów ubocznych (np. sizeof((i>1)?i:(1/i)) nie ulegnie awarii, gdy i==0, ale twoje makro my_sizeof ulegnie awarii z podziałem o zero). Zobacz także C coding guidelines i wikipedia.

Powinieneś zrozumieć C pointer arithmetic. Zobacz np. this question. Różnica wskaźnika wyrażona jest w elementach, a nie w bajtach.

-2

#define my_sizeof (x) ((& x + 1) - & x)

& x daje adres zmiennej i zwiększając go z jednym (& x + 1), poda adres, gdzie można zapisać inną zmienną typu x. Teraz jeśli robimy arytmetyki nad tymi adresami jak ((& x + 1) - & x), to powie, że w ciągu ((& x + 1) - & x) Zakres adresów 1 zmienna typu X mogą być przechowywane.

Teraz, jeśli typograficznie wielkość pamięci zostanie zapisana w (char *) [ponieważ rozmiar znaku wynosi 1 bajt, a inkrementowanie znaku * zostanie przesunięte tylko o jeden bajt], wówczas otrzymamy liczbę bajtów typu x spożywanie

5
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x) 

Ten my_sizeof() makro nie działa w następujących przypadkach:

  1. sizeof 1 - 4 bajty (na platformie 4-bajtowe int) my_sizeof(1) - nie skompiluje się wcale.

  2. sizeof (int) - 4 bajtów (dla platformy z 4-bajtowy int)
    my_sizeof(int) - nie będzie skompilować kod w ogóle.

Będzie działać tylko dla zmiennych. To nie będzie działać dla typów danych, jak intfloat, char itp, dla literałów jak 2, 3.4, 'A' itp, ani do wyrażenia rvalue jak a+b lub foo().

+1

Byłoby to świetny komentarz, ponieważ nie odpowiada na zadane pytanie, ale jest to ["konstruktywna krytyka, która prowadzi autora w poprawie postu"] (http: // stackoverflow.com/help/privileges/comment) ... – Sebivor

+0

Jak go rozwiązać? –

5
#define my_sizeof(x) ((&x + 1) - &x) 

&x daje adres zmiennej (powiedzmy double x) zdefiniowana w programie i zwiększając go z 1 podaje adres gdzie obok zmienna typu X może być przechowywany (tutaj addr_of(x) + 8, dla wielkości podwójne wynosi 8Byte).

Różnica daje wynik, który ilu zmienne typu x mogą być przechowywane w takiej ilości pamięci, która oczywiście będzie wynosić 1 dla typu X (dla zwiększając go z 1 i biorąc różnicę to, co zrobiliśmy).

#define my_size(x) ((char *)(&x + 1) - (char *)&x) 

rzutowania go do char* i biorąc różnicę powie nam, jak wiele zmiennych typu char mogą być przechowywane w pamięci danej przestrzeni (różnica). Ponieważ każdy kod char wymaga tylko 1 bajtu pamięci, dlatego (ilość pamięci)/1 poda liczbę bajtów między dwiema kolejnymi lokalizacjami pamięci typu przekazywanej zmiennej do makra, a tym samym ilość pamięci zmienną typu x wymaga.

Ale nie będzie można przekazać żadnych literałów do tego makra i znać ich wielkości.