2014-12-27 4 views
1

Я читал стандарт, но все еще не может быть уверен:Могу ли я использовать ограничитель в этой функции?

#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';?

+0

Да, но в этом контексте ничего особого не сказано. AFAICT, вам нужны две переменные-указатели в списке аргументов, чтобы она имела значение. Я не вижу ничего, что могло бы нарушить ограничение в коде, который вы показываете. –

+0

Литералы, такие как '' m'', уже имеют тип 'int'. Так что не нужно бросать их, и в любом случае, даже если типы были разными, приведение не является хорошей идеей. –

ответ

0

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

Как компилятор знает, что cp происходит от ap? Он не должен знать. Во-первых, знает ли компилятор или нет, что это поведение определено или неопределено. Правило не «если компилятор знает ...», правило «если cp происходит из ap».

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

+1

Могу ли я быть немного любопытным, как компилятор знает 'cp' происходит от' ap' (а не нерелевантного источника)? :) – cshu

2

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

На другой теме, вам не нужно, чтобы бросить 'm' в (int)'m', как 'm' уже типа int в С.

+0

Вы правы, я просто понял, что буква имеет тип 'int'. Благодарю. На самом деле я задал вопрос, потому что я беспокоился о том, что, может быть, complier не знает отношения между 'cp' и' ap' и просто считает, что пример '' никогда не модифицируется. – cshu

+0

@ouah Вы говорите, что указатель char/unsigned char разрешен псевдоним указателя ограничения? (Если да, то в чем смысл ограничения аргументов strcpy()?) – nos

+3

@nos 'restrict' используется в' strcpy' в качестве подсказки (для целей оптимизации), чтобы сообщить компилятору, что два указателя не являются псевдонимами. C позволяет символу 'char *' использовать любой другой указатель. – ouah

0

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

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

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