Tag: undefined behavior

表达式的定义行为

C99标准以6.5.2美元计价。 在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算修改一次。 此外, 先前的值应该是只读的,以确定要存储的值 。 (我强调) 它继续指出,以下示例是有效的(一开始看似很明显) a[i] = i; 虽然它没有明确说明我和i是什么。 虽然我相信它没有,但我想知道这个例子是否涵盖以下情况: int i = 0, *a = &i; a[i] = i; 这不会更改i的值,而是访问i的值以确定放置值的地址。 或者我们为i分配一个已经存储在i的值是无关紧要的? 请说清楚。 奖金问题; 那a[i]++或a[i] = 1怎么样?

为什么strlen()的实现有效?

(免责声明:我已经看到了这个问题 ,我并没有重新询问它 – 我对代码的工作原理感兴趣,而不是它的工作方式。) 所以这是Apple的(好吧,FreeBSD的) strlen() 。 它使用一个众所周知的优化技巧,即它一次检查4或8个字节,而不是与0进行逐字节比较: size_t strlen(const char *str) { const char *p; const unsigned long *lp; /* Skip the first few bytes until we have an aligned p */ for (p = str; (uintptr_t)p & LONGPTR_MASK; p++) if (*p == ‘\0’) return (p – str); /* Scan the rest of the […]

未指定,未定义和实现定义的行为WIKI for C

虽然SO上有很多关于这个主题的链接,但我认为有些东西缺失:用简单的语言明确解释未指定行为 (UsB), 未定义行为 (UB)和实现定义行为 (IDB)之间的区别)详细但容易解释任何用例和示例。 注意:为了在WIKI中实现紧凑性,我将UsB缩写为up,但是不要指望在其他地方使用它。 我知道这可能看起来与其他post(它更接近的是这个 ) 的重复 ,但在任何人将此标记为重复之前 ,请考虑我已经找到的所有材料的问题(我将要制作这个post中的社区WIKI): 太多分散的例子。 当然,例子并不坏,但有时人们无法找到一个很好地适应他手头问题的例子,因此它们可能会令人困惑(特别是对于新手)。 示例通常只是代码,但解释很少。 在这些微妙的问题上,特别是(相对)新手,更自上而下的方法可能更好:首先是一个清晰,简单的解释与抽象(但不是法律)的描述, 然后是一些简单的例子,解释为什么他们触发一些行为 。 有些post经常混合使用C和C ++示例。 C和C ++有时与他们认为的UsB,UB和IDB不一致,所以一个例子可能会误导那些不熟悉这两种语言的人。 当给出UsB,UB和IDB的定义时,通常它是标准的简单引用,有时可能不清楚或难以为新手消化。 有时引用标准是不完整的。 许多post只引用了对手头问题有用的部分标准,这很好,但缺乏一般性。 此外,标准的引用通常没有任何解释(对初学者不利)。 由于我自己不是这个主题的超级专家,我将建立一个社区WIKI,以便任何有兴趣的人都可以贡献并改进答案。 为了不破坏我创建一个结构良好的初学友好的WIKI的目的,我希望海报在编辑WIKI时遵循一些简单的指导原则: 对您的用例进行分类。 尝试将您的示例/代码放在已存在的类别下(如果适用),否则创建一个新类别。 首先是简单的单词描述。 首先用简单的词语描述(当然,不要过于简单化 – 质量第一!)你想要做的例子或要点。 然后输入代码示例或引用。 引用标准参考。 不要发布各种标准的片段,但要提供明确的参考资料(例如C99 WG14 / N ……第1.4.7节,第……段), 并在可能的情况下发布相关资源的链接。 喜欢免费的在线资源。 如果你想引用书籍或非免费可用的资源(可能会提高WIKI的质量),但也尝试添加一些免费资源的链接。 这对ISO标准尤为重要。 欢迎您添加官方标准的链接,但也尝试添加等效链接以免费提供草稿。 请不要将参考链接替换为参考官方标准, 添加到它们 。 甚至某些大学的某些计算机科学系也没有ISO标准的副本,更不用说大多数程序员了! 除非确实需要,否则不要发布代码。 仅在仅使用普通英语的解释尴尬或不清楚时才发布代码。 尝试将代码示例限制为单行。 发布指向其他SO Q&A的链接。 不要发布C […]

访问超出C和C ++限制的数组

int data[8]; data[9] = 1; c ++标准对此有何评论? 这是未定义的行为吗? 至少C编译器(gcc -std = c99 -pedantic -W -Wall)对此没有任何说明。 谢谢。

C中的序列点和副作用

在这个C-FAQ中给出了序列点 ; 标准规定: 在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算修改一次。 此外,只能访问先前值以确定要存储的值。 在例子中 i = i++; a[i] = i++; 从声明的第一句可以清楚地看出,这些例子是未定义行为的结果。 在解释声明的第二句时,据说; 第二句话说: 如果一个对象被写入一个完整的表达式,那么在同一个表达式中对它的任何和所有访问都必须直接参与计算要写入的值。 此规则有效地将法律表达式约束为在修改之前明显存在访问的表达式。 例如,旧备用 i = i + 1 是允许的,因为i的访问用于确定i的最终值。 这个例子 a[i] = i++ 是不允许的,因为i的一个访问(a [i]中的一个)与最终存储在i中的值无关(在i ++中发生),因此没有好的方法来定义。 我的问题是; 1.它是什么意思, 如果一个对象被写入一个完整的表达式,那么在同一个表达式中对它的任何和所有访问必须直接参与计算要写入的值。 ? 2.它是什么意思,例子a[i] = i++ 是不被允许的,因为i的一个访问(a [i]中的一个)与最终存储在i中的值无关(其中发生在i ++) 有人可以用一些简单的方法解释它吗?

为什么char *会导致未定义的行为而char 不会?

尝试修改字符串文字会导致未定义的行为: char * p = “wikipedia”; p[0] = ‘W’; // undefined behaviour 防止这种情况的一种方法是将其定义为数组而不是指针: char p[] = “wikipedia”; p[0] = ‘W’; // ok 为什么char*会导致未定义的行为,而char[]却没有?

在调用toupper(),tolower()等之前,是否需要转换为unsigned char?

不久之前,StackOverflow上有名望的人在评论中写道,在调用std::toupper (和类似的函数)之前,有必要将char -argument转换为unsigned char 。 另一方面,Bjarne Stroustrup没有提到在C ++ – Programming Language中这样做的必要性。 他只是喜欢使用toupper string name = “Niels Stroustrup”; void m3() { string s = name.substr(6,10); // s = “Stroustr up” name.replace(0,5,”nicholas”); // name becomes “nicholas Stroustrup” name[0] = toupper(name[0]); // name becomes “Nicholas Stroustrup” } (引自上述书,第4版。) 该引用表明输入需要表示为unsigned char 。 对我来说,这听起来像每个char都有,因为char和unsigned char具有相同的大小。 那么这个演员是不必要的还是Stroustrup不小心? 编辑: libstdc ++手册提到输入字符必须来自基本源字符集 ,但不会强制转换。 […]

我们可以通过指针改变用const定义的对象的值吗?

#include int main() { const int a = 12; int *p; p = &a; *p = 70; } 它会起作用吗?

为什么这些构造使用前后增量未定义的行为?

#include int main(void) { int i = 0; i = i++ + ++i; printf(“%d\n”, i); // 3 i = 1; i = (i++); printf(“%d\n”, i); // 2 Should be 1, no ? volatile int u = 0; u = u++ + ++u; printf(“%d\n”, u); // 1 u = 1; u = (u++); printf(“%d\n”, u); // […]

关于C – union中的union作为一种类型并且作为另一种类型读取的问题 – 是否已实现定义?

我正在阅读K&R中关于C的联合,据我所知,联合中的单个变量可以包含几种类型中的任何一种,如果某些东西存储为一种类型并且提取为另一种类型,则结果纯粹是实现定义的。 现在请检查以下代码段: #include int main(void) { union a { int i; char ch[2]; }; union au; u.ch[0] = 3; u.ch[1] = 2; printf(“%d %d %d\n”, u.ch[0], u.ch[1], ui); return 0; } 输出: 3 2 515 在这里,我在u.ch分配值,但是从u.ch和ui检索。 它是实现定义的吗? 或者我做的事情真的很傻? 我知道这对其他大多数人来说似乎很初学,但我无法弄清楚输出背后的原因。 谢谢。