2012-06-12 4 views
1

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

#include <iostream> 
using namespace std; 
int main() 
{ 
    char data[1]; 
    cout<<"Enter data: "; 
    cin>>data; 
    cout<<data[2]<<endl; 
} 

Ввод строки с длиной больше, чем 1 (например, «Привет»), будет производить выход, как если массив был достаточно большим, чтобы удерживать его (например, «л»). Должно ли это не возникать ошибка при попытке сохранить значение, которое было больше, чем массив, или когда оно пыталось получить значение с индексом, большим длины массива?

+0

Не гарантируется работа, так что вы не должны полагаться на это поведение. – weidi

+0

Связанный вопрос: http://stackoverflow.com/questions/1239938/c-accesses-an-array-out-of-bounds-gives-no -error-why – nurettin

ответ

3

Следующий код, похоже, работает , когда он не должен.

Это не о "должен" или "не должны". Это примерно «может» или «не может».

Т.е. ваша программа может работать, а может и нет.

Это потому, что ваша программа вызывает undefined behavior. Доступ к элементу массива за пределами длины массива вызывает неопределенное поведение, которое означает что-либо может случиться.

Правильный способ, чтобы написать свой код, чтобы использовать std::string как:

#include <iostream> 
#include <string> 

//using namespace std; DONT WRITE THIS HERE 

int main() 
{ 
    std::string data; 
    std::cout<<"Enter data: "; 

    std::cin>>data; //read the entire input string, no matter how long it is! 

    std::cout<<data<<std::endl; //print the entire string 

    if (data.size() > 2) //check if data has atleast 3 characters 
    { 
     std::cout << data[2] << std::endl; //print 3rd character 
    } 
} 
+1

Звучит неплохо, спасибо кучу. Я предположил, что определенное поведение состояло в том, чтобы отключить строку или выбросить исключение. Спасибо за разъяснение – mattsbox

1

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

1

Небезопасно это делать. То, что он делает, это писать над памятью, которая, как оказалось, лежит после буфера. Затем он читает это вам.

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

Чтобы это исправить, вы можете заменить это:

std::string data; 

C++ позволит вам делать большие ошибки памяти.

Некоторые 'правила', которые будут вам сэкономить большую часть времени:

1: Не использование char[]. Вместо этого используйте string.

2: Не используйте указатели для передачи аргументов. Перейдите по ссылке, вернитесь по значению.

3: Не использовать массивы (например, int[]). Используйте vectors. Вы все еще должны проверить свои границы.

С этими тремя вы будете писать какой-то «безопасный» код и код, не похожий на C.

+0

У меня сильно искушение дать -1 для «выделения большого массива» «решение» для переполнения буфера. – Hurkyl

+0

Хотите, чтобы я удалил его? – Rhexis

+0

Я думаю, что было бы неплохо либо удалить его, либо, по крайней мере, представить механизмы iostream, чтобы вы не читали больше символов, чем может хранить ваш буфер. Я думаю, что 'std :: setw' будет работать в этой ситуации? Я не использовал манипуляторы для ввода очень часто. – Hurkyl

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