Безопасно ли указывать на доступ к массиву из указателя, который выходит за пределы массива? - PullRequest
1 голос
/ 27 июня 2019

Извиняюсь за зацикленную формулировку вопроса, но это сводится к этому. Я поддерживаю код C, который делает что-то вроде этого:

char *foo = "hello"
int i;
char *bar;

i = strlen(foo);
bar = &foo[i];

Это безопасно? Может ли быть случай, когда foo[i] приводит к ошибке сегментации, прежде чем он получит указатель и не будет покрыт компилятором?

Ответы [ 2 ]

5 голосов
/ 27 июня 2019

Да, вам разрешено устанавливать указатель один за концом массива (хотя вы на самом деле этого не делаете в своем коде - вы указываете на терминатор NUL).

Обратите внимание, чтоповедение при разыменовании указатель, установленный на один конец конца массива, будет неопределенным.

(Обратите внимание, что для оценки стандарта C требуется &foo[i] без разыменования указателя: т. Е. &foo[i + 1] допустимо, но foo[i + 1] само по себе нет.)

1 голос
/ 27 июня 2019

Я поддерживаю код C, который делает что-то вроде этого:

char *foo = "hello"
int i;
char *bar;

i = strlen(foo);
bar = &foo[i];

Это безопасно?

Представленный код соответствует текущему и всему прошломуСтандарты языка C, и имеет то же четко определенное поведение в соответствии с каждым.В частности, имейте в виду, что строковые литералы C представляют символьные массивы с нулевым символом в конце, как и все остальные строки C, как в примере кода.foo[i] относится к терминатору, а &foo[i] указывает на массив (до его последнего элемента), а не за его пределами.

Кроме того, C также позволяет получить указатель на только что прошедшиеконец массива, поэтому даже 1 + &foo[i] является действительным и соответствующим.Разрешается разыменовывать такой указатель, но вы можете выполнять арифметику указателей и сравнивать их (при условии соблюдения обычных ограничений).

Может ли быть случай, когда foo [i] приводит кошибка сегментации, до того, как она получит указатель и не будет покрыта компилятором?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...