Хотелось бы знать, что здесь означает "безопасность" (я видел твой комментарий, что ты получил это из интервью, и что интервьюер не объяснил, что он имел в виду).
ТамЕсть только 4 причины, по которым функция должна получать указатель в качестве параметра:
- Функция предназначена для обновления параметра;
- Параметр является выражением массива, которое автоматически преобразуетсяк выражению указателя при передаче в качестве аргумента функции;
- Параметр имеет очень большой
struct
или аналогичный агрегатный тип, и создание локальной копии считается слишком дорогим; - Параметр былсозданный с помощью
malloc
, calloc
или realloc
.
Ни один из них не должен применяться к опубликованным фрагментам.«Самый безопасный» вариант для них - вообще не использовать указатель.
Один «небезопасный» аспект использования указателя заключается в том, что вы можете использовать вход только для чтения, но посколькубыл передан указатель, вы можете изменить ввод.В этих случаях вы хотите const
-квалифицировать этот параметр:
void foo ( const char *str ) // we cannot modify what str points to
{
...
}
Другим «небезопасным» аспектом использования указателя является случайное (или умышленное) обновление самого значения указателя для доступа к памяти, которую вы не должны 't:
while ( *ptr )
do_something_with( ptr++ );
Вы можете уменьшить это, объявив указатель как const
:
void bar( int * const ptr ) // we cannot update the value in ptr
Это не мешает вам использовать []
оператор подписки, хотя:
while( ptr[i] )
do_something_with( ptr[i++] );
Теперь, если ваш интервьюер думал о нескольких потоках или какой-то проблеме на уровне машины в отношении прерываний или волатильности, тогда, возможно, у него есть точка - если есть что-то, чтоэто может изменить то, на что указывает ptr
за пределами текущего потока управления выполнением, тогда да, второй метод в этом отношении «безопаснее» (указанное значение не изменится в середине вычисления).
Однако, если код многопоточный и ptr
может быть изменен в разных потоках, доступ к нему должен быть синхронизирован через мьютекс или что-то еще.Если ptr
может быть обновлено вне контроля вашей программы, должно быть объявлено volatile
:
int power1( volatile int *ptr ) { ... }
int power2( volatile int *ptr ) { ... }