printf("%ld %ld\n",sizeof(me),sizeof(*me));//output is 8 80 how??
На самом деле это должно быть:
printf("%zu %zu\n",sizeof(me),sizeof(*me));//output is 8 80 how??
"%zu"
правильная строка формата для значения size_t
, такие как значение, которое вы получаете от sizeof
."%ld"
может случиться с некоторыми системами (и, по-видимому, это делается на вас), но вы не должны рассчитывать на это.
Если ваш компилятор не поддерживает "%zu"
, вы можете использовать "%lu"
(который ожидает unsigned long
аргумента) и явно преобразовать аргументы:
printf("%lu %lu\n", (unsigned long)sizeof(me), (unsigned long)sizeof(*me));
Вы получаете 8
для sizeof(me)
потому, что случается размер указателя на компиляторе, который вы используете (8 байт, 64 бит). Если вы скомпилировали и запустили свою программу в другой системе, вы можете получить 4
, потому что многие системы имеют 32-разрядные указатели. (И это предполагает, что байт имеет 8 бит, что справедливо для большинства систем, но не гарантируется языком.)
Большинство компиляторов делают все указатели одинаковыми, но это не гарантируется также и языком. Например, на машине, адресованной слову, указатель int*
может быть просто адресом машинного уровня, но указателю char*
может понадобиться дополнительная информация, чтобы указать, какой байт находится в указанном слове. Вы вряд ли столкнетесь с системой с различными размерами указателей, но до сих пор нет смысла предполагать, что все указатели имеют одинаковый размер.
Что касается размера структуры, которая также может варьироваться от одного компилятора к другому. Вот ваша структура снова:
struct krishna {
int i,j,k,l,m;
char c;
double d;
char g[48];
};
char
всегда точно 1 байт, и char[48]
всегда ровно 48 байт.
Число байтов в int
может варьироваться от одной системы к другой; В наши дни наиболее распространено 4 байта.
Размер double
обычно занимает 8 байт, но это также может меняться (хотя я не думаю, что я когда-либо видел систему, где sizeof (double)
не является 8 байт.)
члены Структура прокладываются в том порядке, в котором они объявлены, поэтому ваш i
будет в самом начале структуры, а затем j
, k
и т. д.
Наконец, компилятор часто вставлять байты заполнения между членами, или после последнего элемента, так что каждый член правильно выровнены. Например, во многих системах 4-байтовый int
необходимо выровнять со смещением, кратным 4 байтам; если он смещен, доступ к нему может быть медленным и/или очень сложным.
Дело в том, что sizeof (struct krishna)
составляет 80 байт в вашей системе не так уж и важно. Более важно понять (а) общие компиляторы правил, чтобы определить, как структурируются структуры, и (б) тот факт, что эти правила могут приводить к разным макетам для разных систем.
Определение языка и ваш компилятор гарантируют, что у вас могут быть объекты типа struct krishna
и что вы можете получить доступ к этим объектам и их членам, возвращая все значения, которые вы сохранили в них. Если вам нужно знать, насколько велика struct krishna
, ответ будет просто sizeof (struct krishna)
.Если по какой-то причине вам нужно знать более подробную информацию (например, если вам нужно сопоставить какой-то внешний шаблон), вы можете сделать некоторые эксперименты и/или проконсультироваться с документацией вашего компилятора, но имейте в виду, что будут применяться специфические особенности только для компилятора, который вы используете в системе, в которой вы его используете. (Часто ABI для вашей системы будет ограничивать выбор компилятора.)
Вы также можете использовать sizeof
и offsetof
(посмотреть его), чтобы выяснить, где выделяется каждый член.
Ответ # 1: Нет. Размер указателя ** по определенной цели ** одинаковый для каждого типа. –
cant get you mr @ RichardJ.RossIII –
Размер указателя в соответствии со стандартами определяется реализацией. На практике размер указателя при компиляции для конкретной цели (в вашем случае, вероятно, x86_64) одинаковый, независимо от типа. Для другой цели (например, x86) вы можете получить другой размер указателя, например 4 (32 бита). –