#c #pointers #undefined-behavior #pointer-to-array
Вопрос:
Я изучал указатели и указатели на массивы, когда столкнулся с этой странной вещью.
Кто-нибудь может объяснить, почему это работает?
char str[] = "This is a String";
int *p = str;
while(*p) std::cout<<*p ;
и возвращается :
но это приводит к неприятной ошибке:
int arr[] = {1,2,3,4,5,6,7,8,9};
int *p = arr;
while(*p) std::cout<<*p <<" ";
подобный этому :
Я знаю, что это неопределенное поведение, так есть ли какой-нибудь способ решить эту проблему?
Комментарии:
1. Во втором примере цикл ищет нулевое значение в массиве.
while
Цикл не остановится, пока не увидит 0. В первом примере все строковые литералы имеют завершающийnul
символ, равный 0.2. Измените выражение в
while
цикле для сравнения по размеру, а не по содержанию.3. Первый код даже не компилируется на C . Вы не можете назначить a
char[]
на anint*
. Но даже если бы он компилировался, он печаталint
бы значения, а неchar
значения. Таким образом, единственный способ, которым вы могли бы получитьThis is a String
результат, — это если бы вы использовали achar*
вместоint*
Ответ №1:
char str[] = "This is a String"; int *p = str;
Эта программа плохо сформирована. char[N]
неявно преобразуется в int*
в C , только в char*
.
int arr[] = {1,2,3,4,5,6,7,8,9}; int *p = arr; while(*p) std::cout<<*p <<" ";
Я знаю, что это неопределенное поведение
Вы понимаете, почему это неопределенное поведение? Проблема в том, что условием завершения цикла является достижение элемента со значением 0. Но вы не поместили в свой массив никаких нулей, поэтому цикл никогда не останавливается, и вы получаете доступ за пределы массива.
есть ли какой-нибудь способ решить эту проблему.
Конечно. Просто не выходите за пределы массива.
Хорошим выбором является использование цикла выбора диапазона:
for(int i : arr) {
std::cout << i << ' ';
}