2016-02-24 3 views
-4

При запуске кода, как это он показывает значение г -> 4 Если раскомментировать COUT < < & он показывает правильное значение -> 1Указатель на следующий адрес

#include<iostream> 
#include<math.h> 
using namespace std; 
int main() 
{ 
    int a=1,b=2,c=3,d=4; 
    /*cout<<&a<<endl; 
    cout<<&b<<endl; 
    cout<<&c<<endl; 
    cout<<&d<<endl;*/ 
    cout<<*(&b - 0x1); 
} 

Может ли кто-нибудь помочь мне понять, почему cout изменяет возвращаемое значение?

+13

Это неопределенное поведение, поэтому все может случиться. – interjay

+2

Поскольку это предположение, я помещаю его здесь: я должен сказать, что переменные оптимизируются, так как вы их не используете, поэтому вы вызываете неопределенное поведение, поскольку 'a' больше не существует. – NathanOliver

+0

Я согласен с NathanOliver. Вы уверены, что '4' происходит от' d'? Вы, скорее всего, просто хватаете какую-то ценность из стека. Попробуйте изменить значение 'd' на что-то еще и посмотреть, останется ли печатное значение 4. В конечном итоге слишком много полагаться на компилятор, помещающий вещи в стек в определенном порядке, является рискованным, если вы не знаете своего компилятора очень и очень хорошо.Особенно для чего-то вроде этого, что не определено, как указывал interjay. –

ответ

3

Без этого заявления

cout<<&a<<endl; 

переменная a не используется в программе. Поэтому компилятору разрешено генерировать объектный код таким образом, чтобы определение a не включалось в программу.

Когда вы раскомментируете эту переменную оператора, a присутствует в объектном коде.

Учитывайте, что поведение программы не определено.

Вы не можете перерисовывать указатель перед переменной, если он не является частью массива.

cout<<*(&b - 0x1); 

Кроме того, порядок, в котором компилятор помещает переменные в память, не указан.

0

Вы вызываете неопределенное поведение.

Недействительно выполнять модификацию такого указателя, если он не является частью какого-либо массива, и ваша арифметика сохраняет значение внутри массива (или один за его концом).

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

Когда вы закомментируете эти строки, оптимизатор, вероятно, замечает, что вы не используете a, c или d и поэтому опускаете их из кода. Когда вы их оставляете, вы получаете ожидаемый результат, потому что вы правильно определили, где ваш компилятор (хотя далеко не все компиляторы) хранят a относительно b (если вообще).

Оптимизатор не требуется и, как правило, не будет пытаться сделать вывод о том, что ваш доступ к &b-0x01 приземляется на a. Это неопределенное поведение и поэтому не имеет значения, какой результат вы получите.

0

По определению C++ выделяет все адреса рядом друг с другом, начиная с последнего, если только память не используется. По моему опыту они находятся рядом друг с другом. Единственная причина, по которой я вижу, - это то, что оптимизация не выделяется, если она не используется. Он всегда показывает значение d, которое является самой странной частью.

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

  • Нет связанных вопросов^_^