c - 函数原型(prototype)中的顶级 volatile 或 restrict 是否重要?

标签 c language-lawyer qualifiers restrict-qualifier

以下原型(prototype)之间有什么实际区别吗?

void f(const int *p);

void f(const int *restrict p);

void f(const int *volatile p);

C11 6.7.6.3/15 部分(最后一句)表示,为了确定类型兼容性,不考虑顶级限定符,即允许函数定义在其参数上具有不同的顶级限定符比原型(prototype)声明有。

但是(与 C++ 不同)它并没有说它们会被完全忽略。在 const 的情况下,这显然没有实际意义;但是在 volatilerestrict 的情况下可能会有不同。

示例:

void f(const int *restrict p);

int main()
{
     int a = 42;
     const int *p = &a;
     f(p);
     return a;
}

原型(prototype)中存在 restrict 是否允许编译器针对 return a; 优化 a 的读取?

( Related question )

最佳答案

如果标准中没有任何内容,则由编译器决定,但似乎至少对于 gcc 4.9(对于 x86)它们被忽略了。检查我用来取笑编译器的这个小片段:

static int b;

void f(const int *p) {
  b = *p + 1;
}

int main()
{
     int a = 42;
     const int *p = &a;
     f(p);
     return a;
}

如果我按原样编译它,我会得到

f(int const*):
    pushq   %rbp
    movq    %rsp, %rbp
    movq    %rdi, -8(%rbp)
    movq    -8(%rbp), %rax
    movl    (%rax), %eax
    addl    $1, %eax
    movl    %eax, b(%rip)
    popq    %rbp
    ret
main:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $16, %rsp
    movl    $42, -12(%rbp)
    leaq    -12(%rbp), %rax
    movq    %rax, -8(%rbp)
    movq    -8(%rbp), %rax
    movq    %rax, %rdi
    call    f(int const*)
    movl    -12(%rbp), %eax
    leave
    ret

如果我使用void f(const int *__restrict__ p)编译它

f(int const*):
    pushq   %rbp
    movq    %rsp, %rbp
    movq    %rdi, -8(%rbp)
    movq    -8(%rbp), %rax
    movl    (%rax), %eax
    addl    $1, %eax
    movl    %eax, b(%rip)
    popq    %rbp
    ret
main:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $16, %rsp
    movl    $42, -12(%rbp)
    leaq    -12(%rbp), %rax
    movq    %rax, -8(%rbp)
    movq    -8(%rbp), %rax
    movq    %rax, %rdi
    call    f(int const*)
    movl    -12(%rbp), %eax
    leave
    ret

Anf 最后,如果我使用 void f(const int *__volatile__ p) 编译它,我会得到

f(int const*):
    pushq   %rbp
    movq    %rsp, %rbp
    movq    %rdi, -8(%rbp)
    movq    -8(%rbp), %rax
    movl    (%rax), %eax
    addl    $1, %eax
    movl    %eax, b(%rip)
    popq    %rbp
    ret
main:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $16, %rsp
    movl    $42, -12(%rbp)
    leaq    -12(%rbp), %rax
    movq    %rax, -8(%rbp)
    movq    -8(%rbp), %rax
    movq    %rax, %rdi
    call    f(int const*)
    movl    -12(%rbp), %eax
    leave
    ret

所以在实践中它们似乎在 C 中也被忽略了。

关于c - 函数原型(prototype)中的顶级 volatile 或 restrict 是否重要?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28819855/

相关文章:

c - C MIPS 环境中延迟 1 微秒

c - bool 是原生 C 类型吗?

c++ - 在复制初始化中,对复制构造函数的调用是显式的还是隐式的?

c++ - 两个内容相同的unordered_set-s的迭代顺序是否保证相同

java - org.jboss.weld.exceptions.DeploymentException WELD-001409 : Ambiguous dependencies for type X with qualifiers @Default

android - 如何获得给定资源的限定符(使用时)?

c - 当我在 MATLAB 中单击 UI 按钮时,我需要交替使用 X 和 O

c++ - 函数模板重载解析,依赖和非依赖参数

c - 这 5 种无数种声明/初始化常量限定指针的方法有什么问题?(摘自一本可疑但受欢迎的书)

c - 这是什么把戏?