Давайте предположим, у меня есть структура и извлечь смещение члена:Как использовать `offsetof` для доступа к полю стандартным образом?
struct A {
int x;
};
size_t xoff = offsetof(A, x);
, как я могу, учитывая указатель на struct A
извлечение элемента в стандартном соответствующем пути? Предположим, конечно, что у нас есть правильный struct A*
и правильное смещение. Одна из попыток было бы сделать что-то вроде:
int getint(struct A* base, size_t off) {
return *(int*)((char*)base + off);
}
Который, вероятно, будет работать, но обратите внимание, например, что указатель арифметика кажется только быть определены в стандарте, если указатели являются указателями одного и того же массива (или один мимо конец), этого не должно быть. Так что технически эта конструкция, похоже, полагается на неопределенное поведение.
Другой подход
int getint(struct A* base, size_t off) {
return *(int*)((uintptr_t)base + off);
}
, который, вероятно, также будет работать, но учтите, что intptr_t
не требуется существовать, и, насколько я знаю, арифметика на intptr_t
не нужно, чтобы получить правильный результат (для Например, я помню, что у некоторых процессоров есть возможность обрабатывать не-байтовые выровненные адреса, которые предполагают, что intptr_t
увеличивается с шагом по 8 для каждого char
в массиве).
Похоже, что в стандарте есть что-то забытое (или что-то, что я пропустил).
Я довольно уверен, ступенчатость к '' * полукокса и указатели, которые ссылаются на один и тот же объект (не обязательно массив) являются действительными. Однако, ожидая авторитетного ответа. – Quentin
'(char *) base' можно использовать для перемещения в любом месте внутри' base' (и один за его конец). Любой объект ведет себя как массив размером 1. –
'return * (int *) ((char *) base + off);' может с легкостью потерпеть неудачу, поскольку доступ 'int' может быть неровным. Например. Доступ 'int' может вызвать ошибку шины на нечетном адресе. OTOH OP действительно сказал: «Предположим ... у нас есть правильная структура A * и правильное смещение» – chux