Это код, который я написал:
#include <iostream>
using namespace std;
int main() {
int x[3] = {30,31,32}, y[3] = {40,41,42}, z[3] = {50,51,52};
for (int i=0; i < 3; i++) {
cout << *(x+i) << endl;
cout << *(x-(3-i)) << endl;
cout << *(x-(6-i)) << endl;
}
cout << endl;
for (int i=0; i < 3; i++) {
cout << (long int)&x[i] << endl; // address of x
}
cout << endl;
for (int i=0; i < 3; i++) {
cout << (long int)&y[i] << endl; // address of y
}
cout << endl;
for (int i=0; i < 3; i++) {
cout << (long int)&z[i] << endl; // address of z
}
}
Вот результат:
30
40
50
31
41
51
32
42
52
140701886846268
140701886846272
140701886846276
140701886846256
140701886846260
140701886846264
140701886846244
140701886846248
140701886846252
Здесь вы можете видеть, что массив, который был объявлен последним, занимает первый адрес памяти, а предпоследний занимает адрес памяти после последнего и так далее.
В вашей программе есть неопределенное поведение, потому что вы выходите за границы массива.
Не думайте, что x[3]
, y[3]
и z[3]
связаны вместе. Если вы не объявите их как один массив или std::vector
так это не всегда так? может тоже случайно?
Я бы не сказал, что это случайно. У каждого компилятора есть (нетривиальная) реализация, которая это определит. Он может меняться в зависимости от компилируемого кода, флагов компилятора, версии компилятора, операционной системы и т. д.
Кадры стека обычно добавляются вниз, поэтому локальные переменные сначала будут занимать самый высокий адрес стека,
Не каждая переменная оказывается в стеке, и выравнивание может создавать дыры в кадре стека при добавлении переменных в кадр стека. Приличный компилятор поместит более поздние переменные в дыры, оставленные более ранними переменными. Компиляторы также нередко добавляют переменные в обратном порядке.
Попробуйте запустить код на godbolt.org/z/5oseKbzGs
Here you can see the array which was declared at last takes the foremost memory address and second last takes memory address after the last one and so on.
Нет, это не то, что происходит. Программа имеет неопределенное поведение, потому что вы выходите за границы массива для выражений *(x-(3-i))
и *(x-(6-i))
для разных значений i
.
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior. The program may just crash.
Таким образом, результат, который вы видите (возможно, видите), является результатом неопределенного поведения. И, как я уже сказал, не полагайтесь на вывод программы с UB. Программа может просто вылететь.
Таким образом, первым шагом для корректной работы программы будет удаление УБ. Тогда и только тогда можно начинать рассуждать о выводе программы. В вашем случае это означает, что вы должны убедиться, что не выходите за пределы массива.
1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.
Это зависит от компилятора. Почему тебе не все равно? Какую реальную проблему вы пытаетесь решить?