c - 有没有办法在例如得到警告。GCC 或 Clang 关于这种严格的别名违规?
问题描述
这是一个严格的别名违规的基本原理是缓冲区已声明类型 char 数组并被一个指向 struct 的指针所别名
#include<string.h>
#include<stdalign.h>
#include<stdio.h>
struct thing {
int a;
char x;
};
int main() {
char alignas(struct thing) buffer[128];
struct thing s = {10,'a'};
struct thing *ptr = memcpy(buffer,&s,sizeof(struct thing));
// violation at ptr->a
printf("%d\n",ptr->a);
return 0;
}
解决方案
警告所有违反 N1570 6.5p7 中所写约束的构造的编译器会生成许多关于所有质量实现都将毫无困难地支持的构造的警告。标准的这些部分有意义的唯一方法是,如果作者期望质量实现能够扩展语言的语义以支持用例,即使标准没有强制要求,他们也没有理由不这样做支持。呈现的代码中说明的用例就是一个例子。
尽管标准不会禁止实现使用 N1570 6.5p7 作为借口,即使在对象仅用作单一类型的存储的情况下也可以进行无意义的行为,但规则的既定目的是描述实现将或将要实现的情况不需要考虑指针别名的可能性。即使在存储仅作为单一类型使用的情况下,禁止有争议的特定构造也无助于实现这一目标。如果代码要在 上使用下标运算符buffer
,除了通过 a 访问存储struct thing*
,编译器可能合法地无法识别使用后一个左值的访问可能与使用前一个左值的访问进行交互的可能性。然而,在呈现的代码中,存储仅用作 typestruct thing
或 via memcpy
,没有理由禁止的用例。以仅禁止使用 achar[]
来保存某些其他类型的数据的方式编写规则,在它也被下标的情况下肯定会增加复杂性,但不会期望编译器支持他们不会有的任何构造反正支持。
如果该标准旨在将程序描述为正确或不正确的程序,那么编写更详细的规则是值得的。但是,由于它没有尝试区分错误的构造和正确但“不可移植”的构造(从某种意义上说,可能存在一些没有有意义地处理它们的实现),因此没有必要尝试明确识别并提供编译器没有理由不进行有意义处理的所有构造。
推荐阅读
- android - 是否可以有两个单独的帐户来获取单个应用程序的 firebase crashlytics
- c# - 如何从消息中正确创建类
- dafny - Dafny 中 multiset(a[..a.Length]) 和 multiset(a[..]) 之间的区别
- erlang - 将 Map 作为参数传递给函数并获取 Erlang 中的值的键
- ios - iOS系统标签在明暗模式下的颜色代码是什么?
- facebook - Blazor WebAssembly 使用后端身份 Api 和社交提供程序进行身份验证
- reactjs - 我在开玩笑中使用 toHaveBeenCalled() 时遇到错误?
- java - 异常运行应用程序 application.TipCalculator
- java - 使用 Test Kit 测试自定义 Gradle 插件
- intellij-idea - 我想知道 IntelliJ IDEA 的默认字体