#c #memory #pointer-arithmetic
#c #память #указатель-арифметика
Вопрос:
У меня есть эта структура вместе с методом, который ее инициализирует:
struct Person
{
char name[32];
char lastn[32];
size_t year;
};
void init_pers(struct Person* p, const char* n, const char* ln, size_t y)
{
strcpy(p->name, n);
strcpy(p->lastn, ln);
p->year = y;
}
И именно так они вызываются в основном:
struct Person f;
init_pers(amp;f, "Alan", "Wake", 1995);
С помощью простой арифметики указателей я смог распечатать два первых атрибута:
printf("First field: %sn", (const char*)amp;f); // prints 'Alan'
printf("Second field: %sn", (const char*)amp;f 32); // prints 'Wake'
Однако, когда я пытаюсь то же самое для печати третьего атрибута, который является size_t , я получаю число, отличное от года:
printf("Third field: %lun", (size_t)amp;f 64); // prints '6422317'
Как правильно распечатать пространство памяти, содержащее год, используя арифметику указателей?
Комментарии:
1. Пожалуйста, обратите внимание, что
size_t
иunsigned long
не обязательно являются совместимыми типами. Таким образом, вы должны использовать спецификатор формата%zu
для печати типаsize_t
. Но,size_t
который обычно используется для размеров и / или индексов, so кажется неправильным типом для вызываемого поляyear
.2. Вы не должны этого делать. Используйте обычный доступ к элементам структуры, как с
p->year
. Доступ к элементам структуры через символьные указатели должен выполняться только для специальных целей, а не для обычного доступа к элементам.3. Спасибо, я приму во внимание оба замечания. Я знаю, что не рекомендуется обращаться к элементам структуры, как я, это был просто небольшой эксперимент, чтобы доказать мои знания о том, как распределяется структурная память.
Ответ №1:
Стандарт C на самом деле не определяет, как размещаются элементы структуры; могут быть дополнения.
Вместо предположения, что year
это 64 байта в структуре, вы должны использовать offsetof(struct Person, year)
.
Если вам нужно больше контроля над тем, как структура размещается в памяти, загляните в упакованные структуры. Это не стандартно, но почти все компиляторы поддерживают их, хотя синтаксис отличается.
Тем не менее, этот третий printf делает не то, что вы думаете. Попробуйте что-то вроде
*((size_t*) (((char*) amp;f) 64))
С помощью вашего исходного кода вы пытаетесь напечатать адрес year
как a size_t
, а не значение.