Я написал код, который использует арифметику указателей на GodBolt , используя G CC 9.2. Позже я попытался скомпилировать этот же код на моей Windows машине, используя MinGW.
Это минимальный c пример кода, который я запустил на GodBolt:
#include <iostream>
#include <memory>
struct release {
void operator()(void* data) const noexcept {
free(data);
}
};
int main() {
auto x = std::unique_ptr<float[], release>{ static_cast<float*>(aligned_alloc(100U * sizeof(float), 32U)) };
if(!x.get() || reinterpret_cast<uintptr_t>(x.get()) % 32U != 0U)
std::cout << "Failed to allocate or align memory\n";
for(auto i = 0U; i < 100U; ++i)
*reinterpret_cast<float*>(reinterpret_cast<intptr_t*>(x.get()) + i * sizeof(float)) = i;
for(auto i = 0U; i < 100U; ++i)
std::cout << *reinterpret_cast<float*>(reinterpret_cast<intptr_t*>(x.get()) + i * sizeof(float)) << std::endl;
}
Он прекрасно работает, без каких-либо ошибок вывода. Когда я попытался запустить этот код на Windows, у меня возникла ошибка. Я заметил, что ошибка произошла из-за умножения текущего индекса элемента ( i ) в циклах for на sizeof (float) . После удаления sizeof (float) у меня был тот же результат, что и у GodBolt.
Я также знаю, что это связано с reinterpret_cast для intptr_t *. Но я ожидал, что, если я приведу указатель к intptr_t *, прежде чем выполнять арифметику, я смогу уйти без умножения на sizeof (float) . Узнав, что на GodBolt этого не происходит, я попытался привести указатели к char * вместо intptr_t *. Но это тоже не сработало.
Может кто-нибудь объяснить мне, что именно вызывает эту разницу? Есть ли способ, которым я могу проверить, нужно ли мне получить доступ к следующему элементу в массиве, просто используя индексацию или умножая на размер элемента?