问题标签 [restrict-qualifier]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c - 可以通过将变量标记为 volatile 来修复不安全的类型双关语吗?
在zwol的回答中,通过在一个结构之间转换指针来实现继承是否合法,该结构是另一个结构的子集而不是第一个成员?他举了一个例子,说明为什么相似结构之间的简单类型转换不安全,并且在评论中有一个示例环境,它的行为异常:在 -O2 上使用 gcc 编译以下内容会导致它打印“x=1.000000 some= 2.000000"
我在乱搞代码以更好地了解它的行为方式,因为我需要做类似的事情,并注意到标记a
为volatile
足以防止它打印不同的值。这符合我对出了什么问题的预期——gcc 假设它a->some
不受写入的影响b->some
。但是,我原以为 gcc 只能假设a
或b
标记为restrict。
我是否误解了这里发生的事情和/或限制限定符的含义?如果不是,gcc 是否可以自由地做出这个假设,因为 a
并且b
属于不同类型?最后,是否同时标记和a
标记使此代码符合标准,或者至少防止未定义的行为允许 gcc 做出上述假设?b
volatile
c - 这是否违反了 `restrict` 的语义?
注意- 这与限制限定符和指针算术非常相似,但不是重复的。那篇文章的作者将指针的操作结果分配restrict
给同一个指针,而我将指针的操作结果restrict
作为参数分配给restrict
函数参数。
我在很大程度上理解了 的含义restrict
,并且我开始养成restrict
在适用时声明函数参数的习惯。但我不确定我是否在这里滥用它。
具体来说,我(char*)dst->data + elemSize*oldElemCount
在调用中指的是memcpy
. 如果我传递了dst
self 而不是上面的参数,我知道它是有效的,因为我会将它分配给一个函数的参数本身restrict
。在这种情况下,论点是操作的结果dst
而不是dst
其本身是否会改变事情?我的理由是,参数不会被别名的保证包含在不会被别名的保证中dst
。
c++ - 结合 __restrict__ 和 __attribute__((aligned(32)))
我想确保 gcc 知道:
- 指针指向不重叠的内存块
- 指针有 32 字节对齐
以下是正确的吗?
谢谢。
更新:
我尝试使用一次读取和大量写入来使 CPU 端口饱和以进行写入。我希望这将使对齐动作的性能提升更加显着。
但是该程序集仍然使用未对齐的移动而不是对齐的移动。
代码(也在godbolt.org 上)
使用 gcc 8.2 和“-march=haswell -O3”编译的程序集充满了 vmovups,它们是未对齐的移动。
即使对于 sandybridge 也有相同的行为:
使用加法而不是乘法(Godbolt)。仍然不结盟的动作。
c - 指针表达式何时“基于”另一个指针?
在C 语言标准的第 6.7.3.1 节中restrict
,它说:
令 D 是一个普通标识符的声明,它提供了一种将对象 P 指定为指向类型 T 的限制限定指针的方法。
...
在下文中,如果(在对 E 求值之前执行 B 的某个序列点)修改 P 以指向它以前指向的数组对象的副本,则称指针表达式 E 基于对象 P会改变 E 的值。
我不明白这是在说什么 - 从字面上看:
- 谁说 P 指向“数组对象的副本”?
- 为什么P“以前”指向任何东西?也就是说,谁说我们改变了它的价值?
- 假设 E 是本地范围的指针。为什么修改E 指针本身以外的任何指针表达式会“改变 E 的值”?它可能会改变 E 指向的值。正确的?
有人可以帮我解释那段文字以便更有意义吗?
(受此答案启发)
c - 为什么`printf`的原型有`restrict`?
printf
根据我的说法,原型stdio.h
是
在解释Restrict的页面上,它说它是一个关键字,用于指示指针是唯一的。但是,我不明白为什么有人需要它printf
。
为什么printf
有一个“限制”关键字?
如果有必要进一步解释“限制”是什么意思,请做。
c++ - C++ 标准中“restrict”关键字/属性的情况
简而言之,restrict
应该告诉编译器指针不能指向相同的内存位置。这对于函数参数和进一步的编译器优化非常有用。在科学计算中,restrict
应用非常广泛。
目前,restrict
关键字只是 C99 的一部分,而不是 C++ 的一部分。我们知道很多 C++ 编译器都支持__restrict__
作为扩展。这个问题还详细讨论了做什么restrict
和__restrict__
做什么。
现在,上述问题中的讨论发生在很久以前,没有谈论 C++17、C++20,也没有计划未来的标准。我发现n3988 提案讨论了 C++ 中的类似restrict
别名、C++ 中具有更丰富语法的复杂性以及潜在的补救措施。
根据 IBM 博客 (2014),鼓励 n3988 用于未来的工作。
这个问题讨论了restrict
和 C++ 的历史,没有任何关于实际实现的结论,并提到了我已经列出的论文或评论中提到的论文 (p1296)。
除了即将推出的 C++的支持计划之外,我找不到任何其他内容restrict
(据我所知,它不是 C++17 的一部分)。这似乎是一个非常有用的功能,所以我想知道
- 如果我在提案/讨论方面遗漏了什么?
- 还有其他关于
restrict
C++ 用法的信息吗? __restrict__
是否有其他方法可以通过仅使用“标准”功能使编译器优化(允许)成为可能?
c - Clang 是否误解了“const”指针说明符?
restrict
在下面的代码中,我看到没有隐式指针说明符,clang 无法执行更好的优化:
我用 clang 版本11.0.0 (clang-1100.0.32.5)编译了这段代码
在反汇编文件中我看到生成的代码重新读取内存:
将restrict
关键字添加到指针后,这些不需要的重新读取就消失了:
我知道在clang中,默认情况下严格别名是禁用的。但是在这种情况下,event_ptr
指针被定义为const
它的对象的内容不能被这个指针修改,因此它不能影响指向的内容queue_ptr
(假设对象在内存中重叠的情况),对吧?
那么这是一个编译器优化错误还是确实存在一些奇怪的情况,即假设此声明queue_ptr
可以影响指向的对象:event_ptr
顺便说一句,我尝试为 x86 目标编译相同的代码并检查了类似的优化问题。
生成的带有关键字的程序集restrict
不包含重新读取:
添加:
在对 Lundin 的回答的评论中与 Lundin 进行了一些讨论后,我得到的印象是可能会导致重新读取,因为编译器会假设这queue_ptr->queue
可能指向*queue_ptr
自身。所以我将queue_t
结构更改为包含数组而不是指针:
然而,重读仍然如前所述。我仍然不明白是什么让编译器认为queue_t
字段可能被修改,因此需要重新读取......以下声明消除了重新读取:
但是为什么queue_ptr
必须将其声明为restrict
指针以防止我不理解的重新读取(除非它是编译器优化“错误”)。
附言
我也找不到任何指向文件/报告不会导致编译器崩溃的问题的链接...
c - 相等或不重叠
假设一个添加两个向量的函数
现在,如果我知道r
与和p
是否在同一个数组中,是否可以帮助使用并行添加指令优化代码?p
q
restrict
我问这个问题是因为在 GCC 上,
可以使用精确假设的条件和我想要的 asm 进行优化,但是在不同的情况下分离会使代码变得一团糟,而 asm 分离的情况做同样的事情
c - 为什么 printf_s(附件 K)中的格式标记为限制?
我完全清楚这个问题的存在。
但是,printf_s
将存在说明符%n
视为错误,因此不会期望从printf_s
. 这里有什么意义restrict
?
c - 对受限指针的子指针的限制?
文章提到:
受限制的指针可以从一个复制到另一个以创建指针层次结构。但是,C99 标准中定义了一个限制。子指针不得与父指针位于同一块级范围内。在同一块级范围内复制受限指针的结果是未定义的。
然后它提供了一个例子:
稍后,它还有另一个例子:
我想现在受限制的父指针position
与其子指针在同一范围内 position_x
,不是吗?根据我在本文开头引用的段落是不允许的吗?