2016-01-13 2 views
4

Я пишу код, зависящий от выравнивания, и совершенно удивлен тем, что нет стандартного тестирования функции, если данный указатель правильно выровнен.Является `reinterpret_cast <char*> (reinterpret_cast <uintptr_t> (& ch) + 1) == & ch + 1` гарантировано?

Похоже, что большинство кода в Интернете используют (long)ptr или reinterpret_cast<uintptr_t>(ptr), чтобы проверить выравнивание, и я также использовал их, но мне интересно, является ли использование литого указателя интегральным типом стандартным.

Есть ли какая-либо система, которая вызывает это утверждение здесь?

char ch[2]; 
assert(reinterpret_cast<char*>(reinterpret_cast<uintptr_t>(&ch[0]) + 1) 
     == &ch[1]); 
+2

Как это выражение проверяет выравнивание? – MikeMB

+0

Могут быть некоторые системы, в которых код не компилируется, так как опционально определяется 'uintptr_t'. * «Беззнаковый целочисленный тип, способный удерживать указатель» *, не требуется. –

+0

@MikeMB Это выражение не используется для проверки выравнивания, но выравнивание проверяется с помощью LSB указателя переинтерпретации, поэтому я считаю, что выражение является необходимым условием проверки выравнивания. – kukyakya

ответ

4

Чтобы ответить на этот вопрос в названии: Нет

контрпример: На старом Pr1me мини-компьютер, нормальный указатель было два 16-битных слов. Первым словом был 12-битный сегментный номер, 2 бита кольца и бит флага (не помню 16-й бит). Второе слово - это 16-битное смещение слова внутри сегмента. А char * (и, следовательно, void *) потребовалось третье слово. Если бит флага был установлен, третье слово было либо 0, либо 8 (являющееся смещением бита в адресованном слове). A uintptr_t для такой машины должно быть uint48_t или uint64_t. В любом случае добавление 1 к такому целому числу не будет продвигаться к следующему символу в памяти.

У устройства с адресованной способностью также могут быть указатели, которые намного больше адресного пространства, и нет особой причины, по которой наименее значимая часть соответствующего целого должна быть частью «адреса», а не части дополнительная информация.

На практике, конечно, никто не пишет C++ для Pr1me, и машины с поддержкой функций, похоже, тоже не появились. Он будет работать на всех реальных системах, но стандарт не гарантирует его.

+0

Более реалистично/недавно классические 8086 20-битные адреса в формате 16:16 могут потерпеть неудачу, когда 'ch [2]' пересекает границу сегмента. '0000: FFFF + 1'' 1000: 0000' не '0001: 0000'. – MSalters

+0

Ох! Отличный пример. –

Смежные вопросы