【问题标题】:Understanding restrict keyword了解限制关键字
【发布时间】:2018-01-16 20:50:23
【问题描述】:

为了理解严格别名和限制关键字的用法,我正在尝试下面显示的程序。在这种情况下,相同的内存位置被两个指针引用。因此,如果没有用户明确告知,编译器无法进行任何优化(即不使用限制关键字)。因此我的理解是,如果没有限制关键字,程序的输出将为 40,而使用“限制”的输出将为 30(因为“*b += *a”之后不需要从内存中读取“a”)。然而,即使有限制,输出也是 40。为什么优化没有发生?

我关注“What is the strict aliasing rule?”以便理解。

#include <stdio.h>

void merge_two_ints(int * restrict a, int * restrict b) {
  *b += *a;
  *a += *b;
}

int
main(void)
{
    int x = 10;
    int *a = &x;
    int *b = &x;
    merge_two_ints(a, b);
    printf("%d\n", x);
    return 0;
}

bash-3.2$ gcc -Wall -O3 -fstrict-aliasing -std=c99 strict_alias2.c

bash-3.2$ ./a.out 40

【问题讨论】:

  • 因此我的理解是,如果没有限制关键字,程序的输出将是 40,而“限制”输出将是 30 - 不。使用restrict 它将是未定义。
  • @EugeneSh.通过使用限制,我们不是告诉编译器 a 和 b 没有指向同一个内存吗?这样就可以无忧优化了?
  • 可以优化但不是必须的。你向编译器承诺了一些东西,但是你违背了你的承诺。这些东西都不好用。
  • 你欺骗了你的编译器,结果就是你所期望的。如果语言滥用,这是一个完美的例子,C 语言与其他语言相比允许很多。但不要太担心。所有初学者都会经历。
  • 顺便说一句,它与严格别名几乎没有关系(几乎没有)。

标签: c strict-aliasing restrict


【解决方案1】:

你观察:

在这种情况下,相同的内存位置被两个指针引用。 [...] 我的 理解是没有限制关键字,程序的输出 将是 40 并且 'restrict' 输出将是 30(因为 'a' 不需要 在“*b += *a”之后从内存中读取)。

但您的期望与 C 标准直接相反,该标准规定:

restrict 限定符 [...] 的预期用途是促进 优化,以及从所有实例中删除限定符的所有实例 预处理组成符合程序的翻译单元 不改变其含义(即,可观察的行为)。

C2011 6.7.3/8;强调)

此外,6.7.3/8 还说,

通过限制限定指针访问的对象具有 与该指针的特殊关联。这种关联,定义在 下面的 6.7.3.1 要求对该对象的所有访问都直接或间接地使用该特定指针的值。

并且没有详细说明,6.7.3.1 明确规定当给定程序不满足其规定时,行为未定义。您的程序会触发此规定,并且您正在预期所产生的未定义行为的特定表现。 C 语言中没有任何东西可以证明这一点。

然而,即使有限制, 输出为 40。为什么没有进行优化?

C 语言从不要求进行一般优化或任何特定优化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-27
    相关资源
    最近更新 更多