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

Извините, если название сбивает с толку. Вот моя структура:

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 байта, потому что это всего лишь размер указателя, но как узнать размер фактического struct из 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 section 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 для телефонной книги *.

Тогда вы сможете:

sizeof(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
@ Чарли Бернс: В общем, я согласен. Однако OP, похоже, имеет особое желание typedef со скрытой косвенной адресацией. Отсюда высказанное выше предложение. Однако я дополню свой ответ вашей точкой зрения. - person Baldrick; 30.10.2013
comment
@Baldrick, мой комментарий был адресован OP, а не вашему ответу. Я должен был прояснить это. Прости. - person Charlie Burns; 30.10.2013
comment
@Charlie Burns - Не беспокойтесь :) - person Baldrick; 30.10.2013