Почему вы не можете выполнять побитовые операции с указателем в C, и есть ли способ обойти это?

Я читал, что вы не можете делать битмаски по указателям, почему вы не можете сделать побитовые операции над указателями?

Есть ли способ добиться такого же эффекта?

То же самое относится к С++?

Ответы

Ответ 1

Причина, по которой вы не можете выполнять операции побитового указателя, заключается в том, что стандарт говорит, что вы не можете. Я полагаю, причина, по которой стандарт говорит так, состоит в том, что побитовые операции указателя почти повсеместно приводят к undefined или (в лучшем случае) поведению, определяемому реализацией. Таким образом, вы ничего не сможете сделать, это полезно и переносимо, в отличие от простых операций, таких как добавление.

Но вы можете обойти его с помощью кастинга:

#include <stdint.h>

void *ptr1;
// Find page start
void *ptr2 = (void *) ((uintptr_t) ptr1 & ~(uintptr_t) 0xfff)

Как и для С++, просто используйте reinterpret_cast вместо C-style cast.

Ответ 2

Это запрещено, потому что семантика не очень хорошо определена. Конечно, вы можете это сделать. Просто введите uintptr_t, выполните операции, а затем верните их в тип указателя. Это тоже будет работать на С++.

Ответ 3

Вы не можете использовать побитовые операторы для указателей, потому что стандарты накладывают очень мало требований о том, как представлен указатель и какой диапазон значений может указывать какой-либо конкретный указатель. Таким образом, нет определения того, что это означало бы использовать эти операторы на указателе.

Тем не менее, большинство компиляторов на большинстве машин используют очевидное отображение адреса памяти в качестве значения указателя. И большинство из них позволит вам указать указатель на интегральный тип. Затем вы можете выполнять побитовые операции над значением и даже возвращать его указателю. Но это не будет строго переносимым или четко определенным в целом.