Как я могу получить доступ к атрибуту структуры, используя простую арифметику указателей?

#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 , а не значение.