Вопрос по массивам

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Ответить
Otsego
Сообщения: 5
Зарегистрирован: 30 авг 2009, 19:45

Код: Выделить всё

int mas[10];
for (int i=0; i<100; i++)
{
	mas[i]=i;
	cout << mas[i] << " ";
}
Код прекрасно работает. Объясните пожалуйста, почему даже варнинг не выдается и почему такое возможно
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

1. Варнинг не может выдаваться. Компилятор не может проверить, что значения индекса не вылазят за пределы границ массива потому, что значение переменной - это runtime информация, которая будет доступна только на этапе запуска. Для того, чтобы реализовать проверку границ следует написать свой класс-массив либо использовать STL контейнер vector и вместо оператора [] использовать метод at, который производит эту самую проверку.

2. Почему прекрасно работает - этот вопрос несколько сложнее. У меня есть подозрение, что тебе очень повезло, что за концом твоего массива было расположена память, не используемая под другие переменные или системные нужды. Не будь ты так счастлив, то мигом бы получил что-нибудь вкусное, типа письма дяде Билли. Кстати, кинь-ка сюда программу целиком, а также укажи каким компилятором компилировал сиё чудо программистской мысли. Тогда я смогу дать более полное описание того, что происходит.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Otsego
Сообщения: 5
Зарегистрирован: 30 авг 2009, 19:45

Спасибо за ответ. Это и есть весь код. Мне товарищ сказал, что так можно сделать, я решил проверить, правда ли. Действительно правда, вот я и захотел выяснить, как же так. У меня студия 2008
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Нет, это не весь код программы. Приведённый код компилироваться не будет, так как в программе должна присутствовать либо функция main (консольный вариант), либо функция WinMain (Win вариант).

Нет, я не придираюсь. В данном случае это важно. Следующие два куска кода имею абсолютно разную семантику:

Код: Выделить всё

int mas[10];
void main()
{
   for (int i=0; i<100; i++)
   {
      mas[i]=i;
      cout << mas[i] << " ";
   }
}

Код: Выделить всё

void main()
{
   int mas[10];
   for (int i=0; i<100; i++)
   {
      mas[i]=i;
      cout << mas[i] << " ";
   }
}
В первом случае тебе может повезти и ты затрёшь участок памяти, в котором ничего полезного не хранится. А всё потому, что массив будет размещён в сегменте данных и ещё потому, что за объявлением массива не следует никаких других объявлений.

Во втором случае ты должен получить гарантированный краш системы (гарантированный по крайней мере для Студии). Дело в том, что твой массив будет расположен в сегменте стека, а следом за ним будет расположена системная информация: старое значение регистра EBP, а также адрес возврата из функции main, иными словами - старые значение регистров ECS и EIP. Затерев их, ты заставишь процессор перейти по системному или принадлежащему не тебе адресу, что даст краш программы.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Otsego
Сообщения: 5
Зарегистрирован: 30 авг 2009, 19:45

Сплошное везение
Изображение
Ответить