2013-04-29 3 views
1

Я видел 3 различных способа SIZEOF структуре в С.Что наиболее подходящий способ SIZEOF на структуру

typedef struct A { 
    int a, b; 
} A; 


sizeof(A); // method 1 

sizeof(struct A); // method 2 

A *p; 
sizeof(*p); // method 3 

Какой из них наиболее подходящий способ сделать это? Рассмотрим эффективность и удобочитаемость.

+1

Способ 2 намного медленнее, чем метод 1, но метод 3 занимает намного больше памяти. Я думаю, что метод 1 есть O (N^2). –

+4

Все они вычисляются во время компиляции. Что вы подразумеваете под «эффективностью»? –

+0

sizeof - это время компиляции, так что он оптимизирован во всех 3 случаях. –

ответ

8

За исключением случаев использования массивов переменной длины, sizeof - это 100% время компиляции. Таким образом, нет «эффективности», за исключением косвенно в отношении удобочитаемости, понятности, безопасности и т. Д.

Я предпочитаю версию с наименьшим повторением, а также с наименьшей типизацией. Таким образом, если имеется указатель, я всегда использую третью форму, но без скобок, так как они не нужны.

Например:

float *a = malloc(1000 * sizeof *a); 

Следует отметить, что код, как это «блокирует» sizeof к указателю используется, что, по крайней мере slighly лучше (я бы утверждать, что это намного лучше, так как типичные функции имеют меньше указателей в области, чем у них есть имена типов), чем повторение типа, так как соответственно уменьшается риск неправильного сопоставления.

Скобки в коде, такие как sizeof(float) или ваш sizeof(A), нужны только тогда, когда аргумент является именем типа. Так как он выглядит, как вызов функции, которой нет, когда я должен использовать эту форму, я всегда форматировать его с пространством:

void *p = malloc(1000 * sizeof (float)); 

Помните, что sizeof не является функцией.

+0

Это не совсем правильно, скобки являются частью 'sizeof'. C11 6.5.3.4/2 'Оператор sizeof дает размер (в байтах) своего операнда, который может быть выражением или заключенным в скобки именем типа. '. См. Также синтаксис в 6.5.3: 'sizeof unary-expression',' sizeof (type-name) '. – Lundin

+1

См. Http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf для определения 'sizeof (T)' в разделе 6.5.3. 'sizeof (T)' не является литой (T), а «нормальным» скобкой. Кроме того, я бы предпочел 'sizeof (* a)', так как изменение типа '' 'автоматически отражается этим выражением. – wirrbel

+0

@ Lundin Спасибо, я на самом деле не читал этого, я получил свое понимание 'sizeof' в другом месте. Я отредактировал, чтобы удалить ссылку на трансляцию. – unwind

0

Здесь typedef бессмысленна и запутывает тот факт, что вы пропустили важное использование sizeof. Я буду притворяться, что вы не использовали typedef и вместо этого задаете вопрос о выборе размера переменной. Например, у вас есть переменная с именем A типа struct A.

С точки зрения читаемости все зависит от контекста (и личных предпочтений). При выделении памяти, более читаемым использовать 3:

p = malloc(sizeof *p); 

При попытке определить размер структуры, то лучше использовать 2 (хотя это очень надуманный пример, так как метод 2 почти никогда желательно):

char *ptr; /* eventually points to an array of struct A */ 
ptr += sizeof(struct A); 

Если вы хотите узнать размер переменной, используйте метод 1:

void *ptr = malloc(COUNT * sizeof A); 

на практике метод 3 почти всегда предпочтительнее. (Это заявление личного мнения.)

Я не знаю, почему вы вычисляете размер. Это будет определять определение «читаемый».

1

sizeof оценивается во время компиляции (*), поэтому все они одинаково эффективны.

Остальная часть вашего вопроса касается стиля кодирования.

Существует два лагеря, в которых обсуждается, следует ли использовать typedef для структур. Один лагерь (в первую очередь, ядро ​​Linux) считает, что struct A понятнее, чем typedef. Другой лагерь (почти все, кроме людей из Linux) считает, что typedef понятнее. Это субъективные мнения, и нет никакого консенсуса, нет правильного или неправильного. Любая форма в порядке.

И вот еще одна дискуссия о стиле кодирования о том, является ли sizeof(type_of_ptr) или sizeof(*ptr) понятнее. Опять же, нет консенсуса, это субъективный стиль кодирования.

Таким образом, ответ на ваш вопрос: это зависит от вашего стандарта стиля кодирования. Тот, который когда-либо формирует то, что ваш стандарт кодирования диктует для вашего текущего проекта.


(*) За исключением SizeOf Власа

+2

Разница между 'sizeof object' и' sizeof (type) 'не просто субъективна. Рассмотрим утверждения 'p = malloc (sizeof * p);' и 'p = malloc (sizeof (type));'.В отсутствие какого-либо ужасного макроса препроцессора для 'p', первое может быть объективно определено для размещения правильного размера для' * p', но последнее требует дополнительной информации, прежде чем можно будет сделать определение. Следовательно, существует объективная, а не субъективная разница между этими двумя формами. –

+0

@EricPostpischil У меня нет предпочтения, и я не хочу обсуждать это. Но так же «объективный» контр-аргумент заключается в том, что если «p» является указателем на указатель, например, параметр, переданный функции для получения malloc: ed, тогда очень легко проскальзывать и написать неправильный уровень Косвенная. Потому что неясно, использовать ли '** p' или' * p' или 'p'. Хотя '** p' будет правильным для моего примера malloc-inside-function, было бы неправильно, если malloc был вызван из main(). И это также может сбивать с толку при работе со статическими многомерными массивами. – Lundin

+1

Как это уместно? Ни 'p = malloc (sizeof * p);' ни 'p = malloc (sizeof (type));' помогает с обнаружением того, был ли правильный уровень косвенности применен к 'p'. Например, если '* p = malloc (sizeof ** p);' или '* p = malloc (sizeof (type));' должно быть использовано, ни одна форма не является более полезной при определении этого. –

0

Когда приходит использование SizeOf оператора, чтобы оценить размер статически объявленных массивов, вы можете сделать это в один причудливый способ - sizeof(some_type[some_size]).

Итак, предположим, что у вас есть некоторые пользовательские определенный тип:

struct some_struct { 
     int some_int; 
}; 

Тогда, в меньшей мере, простой компилируемый грунтовки можно использовать что-то вроде этого:

#define PREFERABLE_SIZE 1000 

int main(const int argc, const char *argv[static const 1]) 
{ 
     return sizeof(struct some_struct[PREFERABLE_SIZE]); 
     /* Or you may do this with some base type (i.e, float) */ 
     /* return sizeof(float[PREFERABLE_SIZE]); */ 
} 

sizeof(some_type[some_size]) эквивалентно some_size * sizeof(some_type). Что касается меня, то первое гораздо предпочтительнее и «красивее», чем последнее.

Смежные вопросы