【问题标题】:Can I use restrict qualifier in this function?我可以在这个函数中使用限制限定符吗?
【发布时间】:2014-12-27 02:16:05
【问题描述】:

我阅读了标准,但仍不能确定:

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

【问题讨论】:

  • 是的,但在这种情况下它并不能说明什么。 AFAICT,您需要参数列表中的两个指针变量才能有所作为。我看不到任何会破坏您显示的代码中的限制的内容。
  • 'm' 等文字已经具有 int 类型。所以不需要强制转换它们,无论如何,即使类型不同,强制转换也不是一个好主意。

标签: c c99 undefined-behavior c11 restrict-qualifier


【解决方案1】:

别名规则允许通过其自己的类型或字符类型(包括其有符号/无符号变体)访问任何变量。这意味着*cp='M'; 是指定的行为,不需要任何特殊的预防措施,因为*cp 是字符类型。

在不同的主题上,您不需要在(int)'m' 中转换'm',因为'm' 已经是C 中的int 类型。

【讨论】:

  • 你说得对,我刚刚意识到字面量是int 类型。谢谢。其实我问这个问题是因为我担心编译器可能不知道cpap之间的关系,只是认为"example"永远不会被修改。
  • @ouah 你是说 char/unsigned char 指针被允许别名为限制指针吗? (如果是这样,限制 strcpy() 的参数有什么意义?)
  • @nos restrictstrcpy 中用作提示(出于优化目的),以通知编译器这两个指针没有别名。 C 允许 char * 为任何其他指针起别名。
  • @ouah 6.7.3-7 of c99 似乎说这不仅仅是一个提示......虽然我无法破译 6.7.3.1 中的实际定义
【解决方案2】:

我的印象是您理解了restrict 修饰符的用途错误。这是函数调用者必须提供的保证,即该对象不能通过任何其他指针访问,也不会被使用这样的另一个指针意外修改。所以restrict 限定指针的用法不会导致UB。

此外,在您的情况下,您正在将这样的指针传递给函数。之后,编译器不能再假设指针没有别名,例如全局变量或函数返回的指针。 (它实际上是这样做的)

举个例子,不是函数memcpy有UB。但是,如果两个指针指向重叠的对象,那将是您对 memcpy 的调用未定义行为。

【讨论】:

    【解决方案3】:

    这不是未定义的行为,因为指针 cp 是从指针变量 ap 派生的。

    编译器怎么知道cp是从ap派生的?它不必知道。首先,无论编译器是否知道,都不会改变行为已定义或未定义。规则不是“如果编译器知道......”,规则是“如果 cp 派生自 ap”。

    只要编译器不能证明 cp 不是从 ap 派生的,它就必须提供与您没有使用 restrict 关键字完全相同的语义。

    【讨论】:

    • 我可以对编译器如何知道cp 派生自ap(而不是无关的来源)有点好奇吗? :)
    猜你喜欢
    • 2012-02-27
    • 2018-07-08
    • 1970-01-01
    • 2017-07-10
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    • 1970-01-01
    • 2022-06-10
    相关资源
    最近更新 更多