Арифметика указателей для структур

Учитывая определение структуры, которое содержит одну двойную и три переменные типа int (всего 4 переменные), если p является указателем на эту структуру со значением 0x1000, какое значение имеет p++?

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

Это в C. Да, я хочу значение p после его увеличения. Это 32-битная машина


person user950891    schedule 01.10.2011    source источник
comment
Результатом p = 0x1000, p++ является 0x1000, так как постинкремент приводит к старому значению. Это вопрос с подвохом или вы хотели спросить значение p после p++ = результат ++p = результат p + 1?   -  person    schedule 02.10.2011
comment
Помимо всего этого, и если предположить, что вам действительно нужно новое значение p, и что это C или C++ (поскольку очень немногие другие языки имеют все указатели, struct и int), ответ зависит от размера члены структуры, которая определяется реализацией. Ничто не говорит, что int должен быть 4 байта; иногда 2, иногда 8, иногда вообще какой-то другой размер.   -  person cHao    schedule 02.10.2011
comment
Я сразу предположил, что он увеличивается на 4 байта в 32-битных системах и на 8 байтов в 64-битных.   -  person Radu    schedule 02.10.2011
comment
@Radu: ваше предположение было бы неверным - если p равно mystruct *, то при его увеличении к адресу добавляется sizeof(mystruct).   -  person cHao    schedule 02.10.2011
comment
@Radu - Правда? В моей 32-битной системе int составляет 4 байта, а double — 8, поэтому 4 байта недостаточно, чтобы поместить ее после первой переменной.   -  person Chris Lutz    schedule 02.10.2011
comment
Извините, я думал о массиве указателей на структуру.   -  person Radu    schedule 02.10.2011


Ответы (5)


struct foobar *p;
p = 0x1000; 
p++;

такой же как

struct foobar *p;
p = 0x1000 + sizeof(struct foobar);
person tangrs    schedule 02.10.2011

p = p + sizeof(YourStruct)

Компилятор может решить, какой sizeof будет возвращен, если вы не отключите заполнение.

person James    schedule 02.10.2011
comment
Вы должны добавить приведение к char *, чтобы было понятнее, что вы выполняете арифметику указателя на уровне байта, а не арифметику указателя на уровне C. - person Chris Lutz; 02.10.2011

Арифметика указателя выполняется в единицах размера типа указателя.

Поэтому, если вы сделаете p++ для указателя на вашу структуру, p переместится на sizeof *p байта. то есть просто спросите у своего компилятора, насколько велика ваша структура с оператором sizeof.

person nos    schedule 02.10.2011

Ответ таков: минимум

sizeof(double) + (3*sizeof(int))

Причина, по которой это «по крайней мере», заключается в том, что компилятор более или менее свободен добавлять отступы по мере необходимости для базовой архитектуры, чтобы она соответствовала ограничениям выравнивания.

Предположим, например, что у вас есть машина с 64-битным словом, как старая машина CDC. (Черт, у некоторых из них были 60-битные слова, так что это было бы еще более странно.) Далее предположим, что на этой машине sizeof(double) — это 64 бита, а sizeof(int) — 16 бит. Затем компилятор может представить вашу структуру как

| double     | int | int | int | 16 bits padding |

так что вся структура может быть передана через машину за 2 ссылки на память, без каких-либо сдвигов или возни с необходимостью. В этом случае sizeof(yourstruct_s) будет равен 16, где sizeof(double)+ (3*sizeof(int)) всего лишь 48 14.

Обновить

Обратите внимание, что это может быть верно и для 32-битной машины: тогда вам может понадобиться дополнение, чтобы уместить его в три слова. Я не знаю современной машины, которая бы не адресовала до байта, поэтому сейчас может быть трудно найти пример, но это может понадобиться для множества старых архитектур.

person Charlie Martin    schedule 02.10.2011
comment
Обратите внимание, что компиляторы обычно добавляют заполнение, чтобы члены структуры были выровнены, когда вы создаете массив своей структуры. если первый элемент здесь является двойным, он будет выровнен таким образом, что все элементы в массиве этой структуры начинаются с адреса, подходящего для двойных значений. (и для других элементов также могут быть добавлены отступы, чтобы они красиво заканчивались на адресе в соответствии с их типом) - person nos; 02.10.2011
comment
@ChrisLutz Я математик, а не бухгалтер. Вы правы, конечно. - person Charlie Martin; 02.10.2011

Приращение базового адреса типа данных равно базовому адресу + sizeof(тип данных)

person Saurabh Yadav    schedule 05.02.2019