Адресная математика: на что влияет тип указателя?

170
03 февраля 2020, 06:10

Я всегда думал, что для адресной математики не важно, какого типа указатель - все равно вычисления будет производить в байтах. Но, кажется, я упустил что-то:

int main()
{
    int a=5;
    void *pa = &a;
    cout << pa << endl;
    void *ppa = pa + 12;
    cout << ppa << endl;
    void *sza = (size_t*)pa + 12;
    cout << sza << endl;
}

Результаты разные в gcc:

22ff00
22ff0c
22ff30

Я не понимаю, почему адрес указателя sza отличается от адреса ppa. Ведь в обоих случаях я прибавил к pa 12 байт. Почему так?

Answer 1

Вообще, арифметика на типах void* запрещена в стандарте. Так что надо приводить к какому-то конкретному типу указателя, а не обобщённому void*. В gcc используется своё расширение (послабление), позволяющее интерпретировать void* как char*, т.е. выполнять единичный сдвиг (sizeof(char) == 1).

А когда будет уже этот конкретный тип, то арифметика будет на него и опираться, т.е. смещать адрес на указанное кол-во элементов соответствующего типа. Т.е. 12 - это не 12 байт, а 12 раз по sizeof(*тип указателя), для которого производится арифметическая операция. В последнем случае sizeof(size_t), что будет 4 или 8 в зависимости от разрядности системы (32 или 64 бит соответственно).

READ ALSO
Qt предупреждения

Qt предупреждения

Вроде после первичного использования setRootIndex на директорию у QAbstractItemView для модели QFileSystemModel в терминал сыпятся ошибки:

145
Как нарисовать простую карту в OpenGL

Как нарисовать простую карту в OpenGL

С помощью libosmium я загрузил карту, и достал из неё водоёмыУ меня есть массив вида

143
Компиляция C++ в .wasm файл

Компиляция C++ в .wasm файл

У меня есть следующий C++ код:

167
include в C++ для MemoryStatus

include в C++ для MemoryStatus

Как понять какой #include нужно написать для MemoryStatusПотому что MemoryStatus выделяется в коде красным и говорит что идентификатор не определен

171