2012-06-10 4 views
3

В этом коде, почему sizeof(x) размер указателя, а не размер x?Почему sizeof (type) размер указателя, а не размер самого типа?

typedef struct { 
    ... 
} x; 

void foo() { 
    x *x = malloc(sizeof(x)); 
} 
+2

Ваш вопрос не имеет отношения к 'malloc'. С немного здравым рассудком ваш вопрос: «Что такое' x'? –

+0

@JensGustedt: Ну, да - однако, не 'sizeof' * в основном * используется вместе с' malloc'? – thejh

+0

Это не имеет никакого отношения к 'sizeof'. Как я уже сказал, ваш вопрос: «Что такое' x'? или даже более понятным ", какой из двух« х »я получу здесь, тип или переменная указателя?» –

ответ

6

Поскольку C говорит:

(C99, 6.2.1p7) "Any other identifier has scope that begins just after the completion of its declarator."

Таким образом, в вашем примере, область объекта x начать сразу после x *x:

x *x = /* scope of object x starts here */ 
     malloc(sizeof(x)); 

Чтобы убедить себя, поставить еще один объект декларации типа x сразу после объявления объекта x: вы получите сообщение об ошибке:

void foo(void) 
{ 
    x *x = malloc(sizeof(x)); // OK 
    x *a; // Error, x is now the name of an object 
} 

В противном случае, как отмечает Шахбаз в комментариях к другому ответу, это по-прежнему неправильное использование malloc. Вы должны позвонить malloc так:

T *a = malloc(sizeof *a); 

и не

T *a = malloc(sizeof a); 
5

Это потому, что sizeof(x) использует сокровенное определение x, который является указателем. Чтобы избежать этой проблемы, не используйте одно и то же имя для типа и переменной.

+5

Кроме того, с помощью malloc используйте его следующим образом: 'type * var = malloc (sizeof (* var));' вместо 'malloc (sizeof (type))' – Shahbaz

+0

Причиной рекомендации Shahbaz является то, что это означает, что тип из 'var' может измениться, и ваш код по-прежнему будет правильным. Если вы используете 'type' вместо' var * ', тогда вы должны помнить об изменении' type' в декларации и в 'sizeof'. –

0

Это плохая идея, чтобы не дать разные вещи разные имена (не только в программировании):

Академическое причина обозреватель поведения уже упомянул мои дорогие коллеги-аннотаторы.

Чтобы дать ясно советует имя diffenet вещи Differnet (здесь: типы переменных и переменных экземпляров):

typedef struct { 
    ... 
} X; 

void foo() { 
    X *x = malloc(sizeof(X)); 
} 

Еще более гибкий способ закодировать этот пример будет (как и уже упомянутый комментарий Shahbaz в):

typedef struct { 
    ... 
} X; 

void foo() { 
    X *x = malloc(sizeof(*x)); 
} 

последний пример позволяет изменить тип x без изменения кода делает распределение.

Недостатком этого подхода является то, что вы можете переключиться с использования ссылок на массивы и стихи vica (как тип для x), не будучи уведомленным компилятором и нарушающим ваш код.