Почему этот массив символов C ++ может содержать больше, чем его размер? - PullRequest
4 голосов
/ 22 мая 2010
#include <iostream>
using namespace std;

typedef struct
{
    char streetName[5];

} RECORD;

int main()
{
    RECORD r;
    cin >> r.streetName;
    cout << r.streetName << endl;

}

Когда я запускаю эту программу, если я введу более 5 символов, на выходе будет показана вся введенная строка.Он не усекается на 5 символов.Почему это так?

Как мне заставить это работать правильно?

Ответы [ 7 ]

13 голосов
/ 22 мая 2010

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

6 голосов
/ 22 мая 2010

Чтобы ограничить входные данные размером принимающего массива, вам необходимо использовать средства ограничения длины, предоставляемые вашим методом ввода. В вашем случае вы используете cin, что означает, что вы можете указать предел, используя width метод

cin.width(5);    
cin >> r.streetName;
5 голосов
/ 22 мая 2010

Потому что cin видит streetName как символ * и пишет в память, и нет ничего, что могло бы остановить запись в * (streetName + 6) и далее. Это форма переполнения буфера

Лучший код в этом случае - определить streetName как std :: string

т.е.

typedef struct
{
        std::string streetName;
} RECORD;
5 голосов
/ 22 мая 2010

Поскольку вы превышаете конец буфера и в данном конкретном случае вам это сходит с рук. С и С ++ очень просто «выстрелить себе в ногу» , но это не значит, что вы должны.

3 голосов
/ 22 мая 2010

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

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

3 голосов
/ 22 мая 2010

Чтобы сделать это правильно в c ++, используйте std :: string.

#include<iostream>
#include<string>

....
std::string r;
getline(cin, r);
std::cout << r <<std::endl;

Для усеченного ввода (с соответственно определенными и инициализированными значениями).

while(cin.peek() != EOF && i < len)
{
  cin >> arr[i];
  ++i;
}

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

3 голосов
/ 22 мая 2010
...