Намиране на правилния размер на структура от указател без създаване на обект?

Съжалявам, ако заглавието е объркващо. Ето моята структура:

struct l_list{
   int number;
   char *name;
   double value;
   struct l_list *next;
};

typedef struct l_list *PhoneBook;

Главна функция:

int main(void){

   printf("%u\n", sizeof(struct l_list));

   PhoneBook person1;

   printf("%u\n", sizeof(*person1));
   printf("%u\n", sizeof(PhoneBook));

   return 0;
}

Резултатът е:

20
20
4

Разбирам, че PhoneBook показва 4 байта, защото това е само размерът на указателя, но как можете да намерите размера на действителната структура от typedef PhoneBook?


person tgun926    schedule 30.10.2013    source източник


Отговори (3)


Можете да направите:

printf("%u\n", sizeof(*(PhoneBook) NULL) );
person Community    schedule 30.10.2013
comment
sizeof *(PhoneBook)NULL ще е достатъчно, по-малко скоби :) - person congusbongus; 30.10.2013
comment
Бихте ли обяснили как/какво правят скобите около PhoneBook? Дефинирате NULL обект, след което го дереферирате...? - person tgun926; 30.10.2013
comment
@tgun926 кастира към PhoneBook. - person ; 30.10.2013

Можете да използвате следното:

printf("%zu\n", sizeof( *(PhoneBook)NULL ) );

важният въпрос е защо горното е валидно, не извършвате ли индиректност върху NULL указател, който би бил недефинирано поведение? Не, не сте от sizeof с изключение на масивите с променлива дължина не се оценяват на всичко. Ако разгледаме проекта на стандарт C99 раздел 6.5.3.4 Операторът sizeof параграф 2 казва (акцентът е мой):

Операторът sizeof дава размера (в байтове) на своя операнд, който може да бъде израз или името в скоби на тип. Размерът се определя от типа на операнда. Резултатът е цяло число. Ако типът на операнда е тип масив с променлива дължина, операндът се оценява; в противен случай операндът не се оценяваи резултатът е целочислена константа.

освен това виждаме следния пример в параграф 5, който потвърждава това четене:

double *dp = alloc(sizeof *dp);

По време на компилиране типът на израза се определя, за да се изчисли резултатът. Можем допълнително да демонстрираме това със следния пример:

int x = 0 ;
printf("%zu\n", sizeof( x++ ));

което няма да увеличи x.

Забележка: %zu е независим от платформа спецификатор на формат за резултата от sizeof.

person Shafik Yaghmour    schedule 30.10.2013

Бих го направил така:

typedef struct l_list{
    int number;
    char *name;
    double value;
   struct l_list *next;
} PhoneBook, *PPhoneBook;

Тогава вашият телефонен указател е typedef за struct l_list, а не показалеца. Това има повече смисъл. PPhoneBook (или всяко друго име по ваш избор) е typedef за Phonebook *.

След това можете да направите:

sizeof(PhoneBook)

и ще ви даде правилния размер на обект PhoneBook.

Или можете да направите:

sizeof(PPhoneBook)

и ще върне 4 байта, размера на указателя. Имайте предвид, че скриването на факта, че използвате указател зад typedef, който не изглежда като указател (като PPhoneBook), не винаги е препоръчително. Това може да направи кода ви объркващ. Въпреки това, ако това е, което искате, ето как да го направите!

person Baldrick    schedule 30.10.2013
comment
Но след това всеки път, когато дефинирам обект, ще трябва да направя PhoneBook *person3;, т.е. да посоча, че това е указател, нали? - person tgun926; 30.10.2013
comment
Можете да създадете множество дефиниции на типа в един оператор, ако искате да дефинирате и указателя - вижте редакцията по-горе. - person Baldrick; 30.10.2013
comment
Скриването на индиректност в typedef е лоша идея. Не можете да погледнете името на типа и да разберете дали е указател, или двоен указател, или какво. Допълнителното * в декларацията е само един знак повече и прави много ясно, че променливата е указател, а не структура. - person Charlie Burns; 30.10.2013
comment
@Charlie Burns: Като цяло бих се съгласил. Въпреки това, OP изглежда има конкретно желание за typedef със скрита индиректност. Оттук и предложението по-горе. Все пак ще актуализирам отговора си с вашата точка. - person Baldrick; 30.10.2013
comment
@Baldrick, коментарът ми беше насочен към OP, а не към вашия отговор. Трябваше да изясня това. съжалявам - person Charlie Burns; 30.10.2013
comment
@Charlie Burns - Без притеснения :) - person Baldrick; 30.10.2013