В проекте есть следующий код:
#define SIZE 4096U
...
void *t_ptr = (void *) (*(uintptr_t *) test->field & ~(SIZE - 1U));
С помощью него необходимо получить указатель на первый элемент списка, так как память изначально была выделена с выравниваем SIZE
.
Адрес может быть, например, таким - 0x460028
.
Однако результат выполнения этой строки равен NULL
. Странность заключается в том, что при использовании другого указателя код вполне себе успешно функционирует.
test
- это структура, описывающая некую область памяти. field
- указатель на другую вспомогательную структуру.
struct Test {
...
struct Field *field;
};
struct Field {
...
Test *test;
};
Test *test = (Test *) mem;
test->field = (Field *) mem1;
В данном случае, при ptr
равном 0x4a0028
, будет возвращено 0x4a0000
.
ptr
- обычный указатель - void *
#define SIZE 4096U
...
void *t_ptr = (void *) (*(uintptr_t *) ptr & ~(SIZE - 1U));
void *t_ptr = (void *) (*(uintptr_t *) ptr & ~(SIZE - 1U));
Выражение *(uintptr_t *) ptr
означает «привести указатель ptr
к типу ″указатель на uintptr_t
″, а затем разыменовать» т.е. его результатом будет содержимое того участка памяти, на который указывает ptr
, интерпретированное как целое uintptr_t
.
Для того, чтобы получить значение указателя привидённое к uintptr_t
надо сделать просто (uintptr_t) ptr
.
Также если sizeof(uintptr_t) > sizeof(unsigned)
, то выражение ~(SIZE - 1U)
перед выполнением побитового И будет расширено до uintptr_t
по правилам беззнакового расширения т.е. даст число вида 0x_0000_0000_ffff_e000
вместо полностью заполненной битовой маски старших разрядов. Чтобы этого избежать надо привести выражение к uintptr_t
до побитового НЕТ.
В итоге получение адреса страницы на которую указывает указатель должно выглядеть как-то так:
void *t_ptr = (void *) ((uintptr_t) ptr & ~((uintptr_t)SIZE - 1U));
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Я пишу вторую версию вставки в map, где нужно передавать ещё и итератор, помимо вставляемой пары, то есть пишу аналог такой вставки: