2016-08-03 11 views
-4
void first(){ 
    int x; 
    int *p; 
    p= &x; 
    scanf("%d",p); 
    printf("The value in x or *p is: %d\n",x); 
} 


void second(){ 
    int x; 
    int *ptr; 
    scanf("%d",&x); 
    printf("The value in *ptr is: %d\n",*ptr); 
} 


int main(){ 
    first(); 
    second(); 
} 

В приведенном выше коде функция second() мисс behaving.What когда-либо значение я даю для x переменной, значение становится присвоенного *ptr, а также х. Зачем?Указатель дает неожиданное значение

+4

Выявление неинициализированного указателя является неопределенным поведением. Он может печатать любую ценность. –

+1

В ответ на вопрос «Почему?» print '* p' показывает значение, введенное в' x': это неопределенное поведение, поэтому компилятор может что-либо сделать, и вы не можете положиться на него ... но в этом конкретном случае с этим выравниванием планет, вероятно, компилятор просто сохраняет адрес '& x' в регистре и читает обратно, вместо недействительного' p'.Честно: любая попытка прочитать из неинициализированной переменной UB и может что-то сделать или ничего, или что-то хорошее, или что-то плохое ... и т. Д. –

+0

Я знаю, что p в первой и второй функции p другой. Мой вопрос в том, почему * p во второй функции получает значение x? –

ответ

6

Вы не присвоили p значение, поэтому оно остается неинициализированным. Попытка разыменовать этот указатель вызывает undefined behavior.

Дайте p значение, и вы получите результат, который вы ожидаете:

int *p = &x; 

Тот факт, что ваш код по-прежнему печати правильное значение является частью этого неопределенного поведения. Один из способов неопределенного поведения может проявиться в том, что код работает правильно, но тогда, казалось бы, несвязанное изменение приведет к его разрыву.

В этой конкретной ситуации функции first и second определяют две локальные переменные того же типа и в том же порядке. По завершении вызова first память, содержащая значения x и p от этой функции, все еще содержит эти значения, но еще не было никаких других вызовов функций, чтобы их перезаписать.

После этого звоните second сразу после first. Переменные x и ptr в second в конечном итоге используют ту же память, что и x, и p в first. И поскольку ptr неинициализирован, он по-прежнему содержит старое значение, которое является адресом x в первую очередь, которое, как оказалось, совпадает с адресом x в second.

Опять же, это неопределенное поведение, поэтому вы не можете постоянно зависеть от этого. Если вы добавили другую переменную в first или вызвали другую функцию между first и second, которая изменит память стека, ранее использовавшуюся first. Затем память будет содержать другое значение, и вы, вероятно, либо распечатаете значение мусора, либо дамп ядра.

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

+0

Я знаю это, но почему содержание p получает значение of x во втором вопросе –

+1

@Muralikrishna См. мое редактирование. – dbush

+0

Вы можете прочесть это фундаментальное рассуждение, создав буфер с большим объемом памяти без его инициализации и используя GDB для просмотра содержимого памяти. буфера каждое исполнение. –

0

int *p=&x;

Адрес х сохраняется в р.

printf("%d",*p);

Поскольку р имеет адрес х, * р в основном означает, что вы собираетесь в месте, указанном на р и собирание элемент, который является значением х.

+0

ОП задается вопросом о результате *** *** ***. – alk

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

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