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

Вот мой код:

#include <iostream>
using namespace std;
int countX(char*, char);

int main() {
char msg[] = "there are four a's in this sentence a a";
//char *ptr = msg; // <----- question 2!
cout << countX(msg, 'a');
cin.get();
}

int countX(char* ptr, char x) {
int c = 0;
for (; *ptr; ptr++) {
if (*ptr == x) c++;
}
/*
while(*ptr) {
if(*ptr==x) c++;
ptr++;
}
*/
return c;
}

Мне было интересно несколько вещей, касающихся безопасности и указателей:

  1. Мое условное утверждение в цикле for ; *ptr ;это безопасная практика? Будет ли это каждый разрыв, если что-то будет храниться в адресе памяти рядом с последним элементом в массиве? Это вообще возможно? Как он знает, когда прекратить? Когда *ptr считается неприемлемым?
  2. (относительно закомментированного char *ptr = msg; в основном): я понимаю, что указатель и массив очень похожи, однако есть ли разница между передачей фактического массива в countX против передачи указателя (который указывает на начало массива?).
  3. В countX Я предоставил два разных способа решения простой проблемы. Один считается превосходящим другого?

0

Решение

Q Мое условное утверждение в цикле for; * ptr;, это безопасная практика?

Да, большую часть времени. Подробности смотрите ниже.

Q Будет ли он каждый (я знаю, вы имели в виду когда-либо) сломаться, если что-то будет храниться в адресе памяти рядом с последним элементом в массиве?

Да.

Q Это вообще возможно?

Да. Вы можете легко получить доступ к памяти за последним символом массива и сделать его чем-то отличным от нулевого символа.

Q Как он знает, когда прекратить?

Он завершится, когда вы встретите завершающий нулевой символ строки. Если нулевой символ был заменен чем-то другим, поведение будет непредсказуемым.

Q Когда * ptr считается неприемлемым?

Если длина строки len, это нормально, чтобы установить ptr В диапазоне msg а также msg+len, Если ptr указывает на что-либо за пределами этого диапазона, поведение не определено. Следовательно, их следует считать неприемлемыми в программе.

Q (относительно закомментированного char * ptr = msg; в основном): я понимаю, что указатель и массив очень похожи, однако есть ли разница между передачей фактического массива countX и передачей указателя (который указывает на начало массива?).

Нет, они идентичны

Q В countX я предоставил два разных способа решения простой проблемы. Один считается превосходящим другого?

Нет, они не. Все сводится к личному вкусу. Мне нравится использовать for петли, пока я знаю людей, которые любят использовать while петли.

1

Другие решения

Q1: Мое условное утверждение в цикле for; * ptr;, это безопасная практика? Будет ли это каждый разрыв, если что-то будет храниться в адресе памяти рядом с последним элементом в массиве? Это вообще возможно? Как он знает, когда прекратить? Когда * ptr считается неприемлемым?

Ответ: При использовании со строками в стиле c, да, это безопасная практика. Любая строка в стиле c обязательно заканчивается на «\ 0», что в основном равно 0. Поведение не определено, когда «\ 0» отсутствует. Таким образом, цикл будет прерываться в конце строки. * ptr никогда не завершится, если это будет что-то кроме строки в стиле c. Например, «hello» в стиле c на самом деле представляет собой массив, содержащий «h», «e», «l», «l», «o», «\ 0». Таким образом, цикл существует в ‘\ 0’, никогда не обращаясь к памяти после него.
возможно получить доступ к памяти после последнего элемента массива. Например,

int a[5] = {0,1,2,3,4,5};
int *p = a+5;

p обращается к элементу после последнего элемента массива a.

Q2:(относительно закомментированного char * ptr = msg; в основном): я понимаю, что указатель и массив очень похожи, однако есть ли разница между передачей фактического массива countX и передачей указателя (который указывает на начало массива?).

Ответ: Массивы и указатели не совсем похожи. Просто имя массива — это не что иное, как постоянный указатель, указывающий на первый элемент массива. Рассмотрим предыдущий пример, который я написал. При этом a [3], 3 [a], * (a + 3) и * (p + 3), все относятся к одному и тому же элементу. Поскольку вы передаете по значению, значение постоянного указателя msg будет просто скопировано в ptr. Так что нет, это не имеет значения.

Q3: В countX я предоставил два разных способа решения простой проблемы. Один считается превосходящим другого?

Ответ: Я не эксперт, но я бы сказал нет.

Кроме того, вам, вероятно, не нужен cin.get ().

0

Это очень плохая практика.

Что вы делаете в for состояние в основном if (*ptr)иными словами, память, на которую указывает ptr содержать ненулевое значение?

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

-2
По вопросам рекламы [email protected]