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

#c #pointers #struct #pointer-arithmetic

#c #указатели #структура #указатель-арифметика

Вопрос:

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

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

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

Комментарии:

1.Результатом p = 0x1000, p является 0x1000 то, что результат после увеличения приводит к старому значению. Это вопрос с подвохом или вы хотели спросить значение p after p = результат p = результат p 1 ?

2. Помимо всего этого, и предполагая, что вы действительно хотели получить новое значение p , и что это C или C (поскольку очень немногие другие языки имеют все указатели, struct , и int ), ответ зависит от размера членов структуры, который определяется реализацией. Ничто не говорит, что значение int должно быть 4 байта; иногда это 2, иногда 8, иногда какой-то другой размер.

3. Мое непосредственное предположение заключается в том, что оно увеличивается на 4 байта в системах 32b и на 8 байтов в 64b.

4. @Radu: ваше предположение было бы неверным — если p равно a mystruct * , то его увеличение добавляет sizeof(mystruct) к адресу.

5. @Radu — Серьезно? В моей 32-разрядной системе значение an int равно 4 байтам, а значение a double равно 8, поэтому 4 байтов недостаточно, чтобы поместить его за первую переменную.

Ответ №1:

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

совпадает с

 struct foobar *p;
p = 0x1000   sizeof(struct foobar);
  

Ответ №2:

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

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

Ответ №3:

Ответ заключается в том, что это по крайней мере

 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-разрядной машине: тогда вам может понадобиться дополнение, чтобы уместить его в три слова. Я не знаю современной машины, которая не адресуется вплоть до байта, поэтому сейчас может быть трудно найти пример, но куча старых архитектур нуждается в этом.

Комментарии:

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

2. @ChrisLutz Я математик, а не бухгалтер. Вы, конечно, правы.

Ответ №4:

 p = p   sizeof(YourStruct)
  

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

Комментарии:

1. Вы должны добавить приведение к char * , чтобы было понятнее, что вы выполняете арифметику указателей на уровне байтов, а не арифметику указателей на уровне C.

Ответ №5:

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