Tag: language lawyer

在确定数组的大小时,括号是否有所作为?

以下程序在gcc 4.8.2上两次打印相同的数字: #include int main() { char a[13]; printf(“sizeof a is %zu\n”, sizeof a ); printf(“sizeof(a) is %zu\n”, sizeof(a)); } 根据这个redditpost ,gcc在这方面不符合标准,因为当数组到指针衰减没有发生时,括号表达式不在exception列表中。 这家伙是对的吗? 这是相关的标准报价: 除非它是sizeof运算符或一元&运算符的操作数,或者是用于初始化字符数组数组的字符串文字,或者是用于初始化元素类型与wchar_t兼容的数组的宽字符串文字,具有“数组类型”类型的左值将转换为具有“指向类型的指针”类型的表达式,该类型指向数组对象的初始成员且不是左值。 为了清楚起见,他认为(a)应该触发数组到指针的衰减,因为上面的列表中没有括号括起来( sizeof运算符,一元&运算符,字符串文字作为初始值)。

是否对空指针未定义行为执行算术运算?

它在我看来像下面的程序计算一个无效的指针,因为除了赋值和比较的平等之外, NULL是没有好处的: #include #include int main() { char *c = NULL; c–; printf(“c: %p\n”, c); return 0; } 然而,似乎GCC或Clang针对未定义行为的警告或工具都没有说这实际上是UB。 这个算术实际上是否有效,而且我太迂腐了,或者这是我们应该报告的检查机制的缺陷吗? 测试: $ clang-3.3 -Weverything -g -O0 -fsanitize=undefined -fsanitize=null -fsanitize=address offsetnull.c -o offsetnull $ ./offsetnull c: 0xffffffffffffffff $ gcc-4.8 -g -O0 -fsanitize=address offsetnull.c -o offsetnull $ ./offsetnull c: 0xffffffffffffffff 似乎很好地记录了Clang和GCC使用的AddressSanitizer更侧重于解除坏指针的引用,所以这很公平。 但其他检查也没有抓住它: – / 编辑 :我问这个问题的部分原因是-fsanitize标志能够动态检查生成的代码中的良好定义。 这是他们应该抓住的东西吗?

是否未定义行为抛弃函数参数的常量?

想象一下,我有这个C函数(以及头文件中的相应原型) void clearstring(const char *data) { char *dst = (char *)data; *dst = 0; } 在上面的代码中是否存在未定义的行为, 将const掉 ,或者它只是一个非常糟糕的编程实践? 假设没有使用const限定对象 char name[] = “pmg”; clearstring(name);

通过结构别名arrays

我正在阅读ISO / IEC 9899:TC2中第6.5段的第7段。 它通过以下方式宽恕对对象的左值访问: 一种聚合或联合类型,包括其成员中的上述类型之一(包括递归地,子聚合或包含联合的成员), 请参阅文档,了解“前面提到的”类型,但它们肯定包含对象的有效类型。 它的部分标注为: 此列表的目的是指定对象可能或可能不具有别名的情况。 我读到这个说(例如)以下是明确定义的: #include #include typedef struct { unsigned int x; } s; int main(void){ unsigned int array[3] = {73,74,75}; s* sp=(s*)&array; sp->x=80; printf(“%d\n”,array[0]); return EXIT_SUCCESS; } 该程序应输出80。 我不是在提倡这是一个好的(或非常有用的)想法,并承认我在某种程度上解释它是因为我无法想到其他意味着什么也不能相信它是一个毫无意义的句子! 也就是说,我看不出有理由禁止它。 我们所知道的是该位置的对齐和内存内容与sp->x兼容,为什么不呢? 它似乎甚至可以说我是否加了(比方说) double y; 在结构的末尾,我仍然可以通过sp->x访问array[0] 。 然而,即使数组大于sizeof(s)任何访问sp->y尝试都是’所有下注’未定义的行为。 可能我礼貌地要求人们说出那句话宽恕而不是进入一个扁平的旋转喊“严格混淆UB严格别名UB”似乎经常是这些事情的方式。

是否可以通过成员地址访问结构的大小,并分配足够的空间?

具体来说,是下面的代码,标记下方的行,好吗? struct S{ int a; }; #include int main(){ struct S *p; p = malloc(sizeof(struct S) + 1000); // This line: *(&(p->a) + 1) = 0; } 人们在这里争论,但没有人给出令人信服的解释或参考。 他们的论点略有不同,但基本相同 typedef struct _pack{ int64_t c; } pack; int main(){ pack *p; char str[9] = “aaaaaaaa”; // Input size_t len = offsetof(pack, c) + (strlen(str) + 1); […]

通过易失性引用/指针访问声明的非易失性对象是否会在所述访问时赋予易失性规则?

这将是一个漫长的过程,关于它的上下文并提供尽可能多的信息,我必须蜿蜒通过各种链接和引用 – 这通常是我们进入C / C ++标准兔子洞后的唯一方法。 如果您对此帖有更好的引用或任何其他改进,请告诉我。 但是要事先总结一下, 你可以责怪@ zwol发布这个;-)并且目的是从两个命题中找到真相: 执行C和(通过导入;请参阅注释)C ++标准要求通过volatile *或volatile &访问必须引用最初声明为volatile的对象才能具有volatile语义? 或者是通过volatile指针/引用访问非易失volatile限定对象/应该使所述访问行为就像对象被声明为volatile ? 无论哪种方式,如果(看起来)措辞与意图相比有些含糊不清 – 我们可以在标准本身中明确说明吗? 这些相互排斥的解释中的第一个更常见,而且并非完全没有依据。 但是,我希望表明有大量的“合理怀疑”支持第二个 – 特别是当我们回到基本原理和WG论文中的一些先前的段落时。 接受的智慧:被引用的对象本身必须被声明为volatile 昨天流行的问题是“挥发性”这个波动的定义,还是GCC有一些标准的合规性问题? 通过假设一个volatile引用会给volatile volatile指示物带来volatile行为 – 但发现它没有,或者在不同程度上以不可预测的方式做出来。 接受的答案最初得出结论,只有宣称的指称类型才重要。 这个和大多数注释似乎都同意等效原则在我们对const很熟悉的情况下起作用:如果引用具有与引用对象相同的cv -qualification,则行为将只是volatile (或根本定义): 该段落中的关键词是对象。 volatile sig_atomic_t flag; 是一个易变的对象。 *(volatile char *)foo仅仅是通过volatile限定左值的访问,标准不要求具有任何特殊效果 。 – zwol 这种解释似乎被广泛持有,正如对这个相似但希望不重复的问题的回答所示: 指向易失性指向非易失性对象的行为要求但即使存在不确定性:紧接着答案是’不’,然后说’也许’! 无论如何……让我们检查一下标准,看看’没有’是什么。 标准所说的……或者不是 C11, N1548,§6.7.3 :很明显,通过不共享所述限定符的指针访问用 volatile或const类型定义的对象是UB … 6如果尝试通过使用具有非const qualifiedified类型的左值来修改使用const限定类型定义的对象,则行为未定义。 […]

C – 是不确定的不确定值吗?

根据这篇文章 ,不确定的价值是: 3.17.2 1 indeterminate value either an unspecified value or a trap representation 根据谷歌的说法,不确定性的定义是: 不确定,已知或已建立 遗憾; 模糊。 根据字典,可确定的是: 能够被确定 根据merriam-webster,确定(在特定的上下文中)是: 通过调查,推理或计算找出或做出决定 因此,常识规定尽管在编译期间不确定值是未知的,但它在运行时是完全可确定的,例如,您总是可以读取占用该内存位置的任何事件。 或者我错了? 如果是这样,为什么? 编辑:为了澄清,我发布了与用户试图说服不确定值不确定的用户的激烈争论,我非常怀疑。 编辑2:澄清,通过“可确定”我并不意味着稳定或可用的值,即使它是未初始化的内存的垃圾值,仍然可以确定该垃圾的价值。 我的意思是试图确定这个价值仍然会产生一些价值,而不是……没有行动。 所以这个值必须来自一些内存,分配为仍然不确定的值的存储,我高度怀疑编译器实际上会使用一个随机数生成器只是为了提出一些任意值。

通过C转换访问结构的第一个字段是否违反了严格的别名?

此代码是否违反严格别名? struct {int x;} a; *(int*)&a = 3 更抽象的是,只要原始读/写操作类型正确,在不同类型之间进行转换是否合法?