2010-08-11 3 views
3

Почему массив не переполнен (например, предупреждение об ошибке), когда массив объявлен глобально, в другом случае я могу заполнить его неограниченным количеством элементов (через), даже если он ограничен размером в и он предупреждает, когда я объявляю массив локально внутри основного?Глобальные массивы в C++

char name[9]; 


int main(){ 


    int i; 


    for(int i=0; i<18; ++i){ 
    cin>>name[i]; 


    } 

    cout<<"Inside the array: "; 
    for(i=0; i<20; i++) 
    cout<<name[i]; 

    return 0; 

} 

ответ

2

C++ не имеет проверки границ массива, поэтому язык никогда не проверяет, превысил ли вы конец вашего массива, но, как можно было ожидать, что другие могут сказать о плохих вещах.

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

6

C++ не проверяет ошибки границ для массивов любого типа. Чтение или запись за пределами границ массива вызывает то, что известно как «неопределенное поведение», что означает, что все может произойти. В вашем случае кажется, что происходит то, что он работает, но программа все равно будет находиться в недопустимом состоянии.

Если вы хотите проверки границ, используйте зЬй :: вектор и его в() функцию-член:

vector <int> a(3); // vector of 3 ints 
int n = a.at(0);  // ok 
n = a.at(42);  // throws an exception 
+0

Почему это предупреждает, когда я объявляю его локально? – user377622

+0

@persistent, why * what *, когда вы объявляете его локально? –

+0

@persistent вы объявляете их локально, если вам нужна переменная локального массива. то, что говорит Нил, справедливо для всех массивов в c/C++. Рассмотрите возможность использования 'std :: vector' – Andrey

1

его неопределенное поведение. Все может случиться.

+0

Остерегайтесь носовых демонов http://www.catb.org/jargon/html/N/nasal-demons.html – EvilTeach

0

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

+0

Расслабьтесь, я просто тренируюсь и учась :) – user377622

0

Я бы сделал еще один шаг и сказал, что у C/C++ нет массивов. То, что у них есть, это синтаксический сахар, подобный массиву, который сразу же переводится в арифметику указателя, которая не может быть проверена, поскольку указатели могут использоваться для доступа потенциально всех памяти. Любая проверка того, что компилятор может выполнить на основе статических размеров и постоянных границ индекса, - это счастливая случайность, но вы не можете полагаться на нее.

Вот странность, что меня поразило, когда я впервые увидел его:

int a[10], i; 
i = 5; 
a[i] = 42; // Looks normal. 
5[a] = 37; // But what's this??? 
std::cout << "Array element = " << a[i] << std::endl; 

Но странный линия совершенно законно C++. В этом примере подчеркивается, что массивы на C/C++ являются вымыслом.

Нейл Баттерворт уже прокомментировал преимущества использования std :: vector и метода доступа at() для него, и я не могу выполнить его рекомендацию достаточно сильно. (К сожалению, дизайнеры STL взорвали прекрасную возможность сделать проверочный доступ к операторам [], при этом методы at() непроверенные. Это, вероятно, стоило сообществу разработчиков на C++ миллионов часов и миллионов долларов и будет продолжать сделайте это.)

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