Могу ли я использовать квалификатор ограничения в этой функции?

Я прочитал стандарт, но все еще не уверен:

#include <stdio.h>
#include <string.h>

void repl(char *restrict ap){
    char *cp=strchr(ap,(int)'m');
    *cp='M';
}

int main(){
    char arr[] = "example";
    repl(arr);
    puts(arr);
    return 0;
}

В функции repl я использовал strchr, чтобы получить еще один указатель для изменения объекта. Я ожидаю, что результатом будет строка, в которой первый m заменен на M.

Но может ли это быть неопределенным поведением?

Если да, то как насчет использования ap[cp-ap]='M'; вместо *cp='M';?


person cshu    schedule 27.12.2014    source источник
comment
Да, но в данном контексте это ни на что не указывает. AFAICT, вам нужны две переменные указателя в списке аргументов, чтобы это имело значение. Я не вижу ничего, что могло бы нарушить ограничение в коде, который вы показываете.   -  person Jonathan Leffler    schedule 27.12.2014
comment
Такие литералы, как 'm', уже имеют тип int. Так что не нужно их приводить, и в любом случае, даже если бы типы были разными, приведение в любом случае не очень хорошая идея.   -  person Jens Gustedt    schedule 27.12.2014


Ответы (3)


Правила псевдонимов позволяют обращаться к любой переменной через ее собственный тип или по символьному типу (включая его знаковый/беззнаковый вариант). Это означает, что *cp='M'; является заданным поведением без каких-либо особых мер предосторожности, поскольку *cp имеет символьный тип.

В другой теме вам не нужно приводить 'm' к (int)'m', поскольку 'm' уже имеет тип int в C.

person ouah    schedule 27.12.2014
comment
Вы правы, я только что понял, что литерал имеет тип int. Спасибо. На самом деле я задал этот вопрос, потому что беспокоился о том, что, возможно, компилятор не знает отношения между cp и ap и просто считает, что "example" никогда не модифицируется. - person cshu; 27.12.2014
comment
@ouah Вы говорите, что указатель char / unsigned char может использовать псевдоним указателя ограничения? (Если да, то какой смысл ограничивать аргументы strcpy()?) - person nos; 27.12.2014
comment
@nos restrict используется в strcpy как подсказка (в целях оптимизации), чтобы сообщить компилятору, что два указателя не являются псевдонимами . C позволяет char * использовать псевдоним любого другого указателя. - person ouah; 27.12.2014
comment
@ouah 6.7.3-7 из c99, кажется, говорит, что это больше, чем намек ... хотя я не могу расшифровать фактическое определение в 6.7.3.1 - person nos; 27.12.2014

У меня сложилось впечатление, что вы неправильно понимаете назначение модификатора restrict. Это гарантия, которую должен предоставить вызывающий объект функции, а именно, что объект недоступен через какой-либо другой указатель и не будет неожиданно изменен при использовании такого другого указателя. Таким образом, использование restrict квалифицированных указателей не приводит к UB.

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

Чтобы дать вам пример, это не функция memcpy, которая имеет UB. Но это будет ваш вызов memcpy, который не определил поведение, если два указателя указывают на перекрывающиеся объекты.

person Jens Gustedt    schedule 27.12.2014

Это не неопределенное поведение, поскольку указатель cp является производным от переменной указателя ap.

Как компилятор узнает, что cp является производным от ap? Это не обязательно знать. Во-первых, то, знает компилятор или нет, не меняет того, что поведение определено или не определено. Правило не "если компилятор знает...", а правило "если cp получено из ap".

Пока компилятор не может доказать, что cp не был производным от ap, он должен обеспечить точно такую ​​же семантику, как если бы вы не использовали ключевое слово limited.

person gnasher729    schedule 27.12.2014
comment
Могу ли я немного поинтересоваться, как компилятор узнает, что cp получено из ap (а не из нерелевантного источника)? :) - person cshu; 27.12.2014