2015-12-22 1 views
0

Я изучаю указатели. Я видел этот образец кода в учебнике. Я попробовал, но это дало другой результат из учебника.Тот же исходный код, но другой результат в разных операционных системах

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    int i = 5; 
    int myInt = 7; 
    int *pointer = &i; 
    printf("%i\n", *(pointer + 1)); 

    return 0; 

} 
  • на машине окна, выход 2686740

  • на Linux машине, выход 7.

Что является причиной этого?

+3

Поиск 'неопределенное поведение'. Нет ничего особо гарантированного существования в '* (указатель + 1)', поскольку код никогда не выделяет и не резервирует для него ничего. Кроме того, пожалуйста, укажите «учебник», чтобы другие знали, чтобы избежать его. – dxiv

+0

Доступ к недопустимой памяти - это неопределенное поведение. Подробнее: [Действительно ли «Неопределенное поведение» действительно разрешает * что-либо?] (Https://stackoverflow.com/questions/32132574/does-undefined-behavior-really-permit-anything-to-happen) и [Не определено , неопределенное и определенное по реализации поведение] (https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior). – kaylum

+0

@dxiv Я не знаю, является ли это плохим учебником или нет. На самом деле я абсолютный новичок. [link] https://youtu.be/5jQ2ZiXzJjE?t=3m57s –

ответ

0

памяти (стек в данном случае), как это

[ i ][ something else .... 
^ ^
^ pointer+1 
pointer 

Ведение

int *pointer = &i; 
printf("%i\n", *(pointer + 1)); 

вы отображать Int, то есть пространство памяти с pointer+1 в sizeof(int) читается как int, то, что компилятор не ожидал от вас, и это пространство «неизвестно». Так что Windows может отображать X, Linux также может это сделать, отобразить что-то еще или даже сбой ...

Это неопределенное поведение.

0

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

Фактическая причина заключается в том, что на Linux, переменная моя ИНТ находится по адресу & я + 1, в то время как на окнах ... это где-то еще

0

Я думаю, что код делает предположения о макете памяти, который может быть или не содержать. Предположения: стек является линейным, а переменные хранятся точно так же, как указано в источнике. Это подразумевает, что вы предполагаете, что компилятор не делает никаких оптимизаций.

Попробуйте следующее на окнах: (i) отключите всю оптимизацию компилятора, (ii) или запустите в режиме отладки. Поведение может или не может переключиться на «ожидаемый» на окна. Урок: не пишите такой код;)

1

Чтобы подробнее рассказать о существующих ответах, я хотел бы добавить объяснение.

В вашем коде i является переменной int. Вы назначаете адрес i на номер pointer. Хорошо. Затем, что вы делаете, увеличивайте указатель (адрес), а затем пытайтесь разыменовать его.

Теперь, по сравнению с утверждением в вашем коде,

printf("%i\n", *(pointer + 1));  

со ссылкой на стандарт C11, глава §6.5.6, Аддитивные операторы

[....] Если оба указателя и результат указывают на элементы одного и того же объекта массива или один последний элемент объекта массива, оценка не должна приводить к переполнению; в противном случае поведение не определено. Если результат указывает один за последний элемент объекта массива, он не должен использоваться в качестве операнда унарного оператора *, который оценивается.

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

Выход UB, есть, ну, undefined.

+0

Благодарим вас за объяснение и разделите эту ссылку, о которой я раньше не знал. –

+0

@HakanAs приветствуются. :) –

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