#c #pointers #struct #pointer-arithmetic
#c #указатели #структура #указатель-арифметика
Вопрос:
Учитывая определение структуры, которое содержит одну переменную double и три переменные int (всего 4 переменные), если p является указателем на эту структуру со значением 0x1000, какое значение имеет p ?
Это не проблема домашнего задания, так что не волнуйтесь. Я просто пытаюсь подготовиться к тестированию и не могу решить эту практическую проблему. Спасибо
Это на C. Да, я хочу значение p после его увеличения. Это 32-разрядная машина
Комментарии:
1.Результатом
p = 0x1000, p
является0x1000
то, что результат после увеличения приводит к старому значению. Это вопрос с подвохом или вы хотели спросить значениеp
afterp
= результатp
= результатp 1
?2. Помимо всего этого, и предполагая, что вы действительно хотели получить новое значение
p
, и что это C или C (поскольку очень немногие другие языки имеют все указатели,struct
, иint
), ответ зависит от размера членов структуры, который определяется реализацией. Ничто не говорит, что значение int должно быть 4 байта; иногда это 2, иногда 8, иногда какой-то другой размер.3. Мое непосредственное предположение заключается в том, что оно увеличивается на 4 байта в системах 32b и на 8 байтов в 64b.
4. @Radu: ваше предположение было бы неверным — если
p
равно amystruct *
, то его увеличение добавляетsizeof(mystruct)
к адресу.5. @Radu — Серьезно? В моей 32-разрядной системе значение an
int
равно 4 байтам, а значение adouble
равно 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(тип данных)