Как справиться с неопределенным поведением указателя на массив в cpp?

#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[] на an int* . Но даже если бы он компилировался, он печатал int бы значения, а не char значения. Таким образом, единственный способ, которым вы могли бы получить This is a String результат, — это если бы вы использовали a char* вместо 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 << ' ';
}