Является ли что-то несогласованным или нет, зависит от типа данных и его размера. Как объясняет Грегг.
Хорошо написанная программа, как правило, не имеет равномерного доступа к памяти, за исключением случаев, когда компилятор представляет ее. (Да, это происходит во время векторизации, но давайте пропустим это).
Но вы можете написать программу на C++, чтобы принудительно использовать неравномерный доступ к памяти. Код ниже делает именно это.
#include <iostream>
using namespace std;
int main() {
int a[3] {1, 2, 3};
cout << *((long long *)(&a[0])) << endl;
cout << *((long long *)(&a[1])) << endl;
cout << (long long) (&a[0]) << endl;
cout << (long long) (&a[1]) << endl;
return 0;
}
Выход кода это
8589934593
12884901890
70367819479584
70367819479588
Что делает эта программа? Я объявляю целочисленный массив размера 3. Этот массив будет выровнен по 4 байт, потому что int - это 4-байтовый тип данных (по крайней мере, на моей платформе). Таким образом, адрес [0] делится на 4. Теперь адрес обоих [0] и [1] делится на 4, но только адрес одного из них делится на 8.
Так что если я введите адрес [0] и [1] в указатель на длинный (который является 8-байтным типом данных на моей платформе), а затем почуйте эти два указателя, один из них будет негласным доступом к памяти. Это не неопределенное поведение AFAIK, но оно будет медленнее, чем выровненный доступ к памяти.
Как вы видите, этот код содержит стили стиля C, что не является хорошей практикой. Но я думаю, что для обеспечения какого-то странного поведения это нормально.
дайте мне знать, если у вас есть вопрос о выходе кода. Вы должны знать о конкретизации и представлении целых чисел для понимания первых двух строк. Третья и четвертая строки являются адресами первых двух элементов целочисленного массива. Это должно быть легче понять.
Из ответа, на который вы ссылаетесь: «на C++ невозможно написать код, который будет выполнять неприсоединенный доступ, не вызывая неопределенного поведения». – molbdnilo