问题标签 [sequence-points]
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++ - 为什么表达式 a = a + b - ( b = a ) 在 c++ 中给出序列点警告?
以下是测试代码:
编译它会给出以下警告:
为什么操作可以是未定义的?
根据我的理解,首先(b = a)
应该评估子表达式,因为()的优先级更高,因此设置b = a。然后,由于 '+' 和 '-' 具有相同的优先级,表达式将被左关联评估。因此,a + b
接下来应该评估,最后(b = a)
应该从 中减去的结果a + b
。我看不到这里违反了任何序列点规则。
c - 分配和序列点:这怎么模棱两可?
考虑 C 代码a = a = a
。没有用于赋值的序列点,因此此代码在编译有关a
.
这里可能有什么价值a
?似乎a
不可能改变价值观。这里实际上是否存在未定义的行为,或者编译器只是懒惰?
c++ - 在返回对象的函数调用和对该对象的方法调用之间是否存在序列点?
如果我写,我可以在评估之前f(x)->g(args, ...)
依赖一个序列点吗?我可以看到两种方式的论点:f(x)
args, ...
- §1.9.17 “在调用函数时(无论该函数是否内联),在函数体中的任何表达式或语句执行之前发生的所有函数参数(如果有)的评估之后都有一个序列点。在复制返回值之后和函数外的任何表达式执行之前还有一个序列点。 ”
- 另一方面,对象指针隐含地是一个隐藏的参数
this
,就好像我写g(f(x), args, ...)
的那样,这表明它就像一个参数,因此未指定。
该->
运算符不是普通的二元运算符,因为显然g(...)
无法f(x)
像我写的那样进行评估f(x) + g(...)
。我很惊讶我找不到一些关于它的具体陈述。
c - return 语句后的序列点?
在我对一个问题的回答中,我解释了在与return
语句在同一行的全局变量上使用后缀 ++ 时发生的情况。
C11 的资料性附录 C 指出在 a 之后有一个序列点,return
并参考规范性章节 6.8.6.4,其中没有关于序列点的文本。
在 C 标准中,我可以在哪里找到说明语句后有序列点的规范性文本return
?
(作为特例,我只在 7.1.4/3 找到了说明库函数的规范文本。)
c++ - 为什么对原始类型的操作是未排序的,而不是不确定排序的?
If i
is an int
, 像这样的表达式++i + ++i
是未定义的行为,因为有 2 个未排序的修改i
. 但是, ifi
是一些int
类似的类,++i + ++i
而是具有不确定的顺序修改,因此是定义的行为(在这种情况下具有确定性的结果)。有没有一种情况,对原语的操作最好是无序列的而不是不确定的序列?如果是这样,为什么这种情况不适用于用户创建的类型?如果不是,为什么原始操作根本没有排序?
c++ - 是索引一个新的地图元素并将读取它的东西分配给它未定义的行为,还是只是未指定?
在回答了这个问题之后,关于有问题的代码是否是未定义的行为进行了长时间的讨论。这是代码:
首先,这是公认的,这至少是未指定的。结果根据首先评估作业的哪一侧而有所不同。在我的回答中,我跟踪了四个结果案例中的每一个,其中首先评估了哪一方的因素以及该元素在此之前是否存在。
还出现了一个简短的表格:
我声称它更像这样:
最终,我找到了一个似乎对我有用的例子:
回到原来的,我把它分解成相关的函数调用,以便更容易理解:
如果word_count["a"]
不存在,则有人认为它将被分配两次,而两者之间没有排序。如果我认为是真的两件事实际上是:
When a side is picked to be evaluated, the whole side has to be evaluated before the other side can start.
诸如 word_count["a"] = 1 之类的结构表现出明确定义的行为,即使在插入元素然后分配给它的情况下也是如此。
这两个说法是真的吗?最终,这实际上是未定义的行为吗?如果是,为什么第二个语句起作用(假设它起作用)?如果第二个是假的,我相信myMap[i]++;
世界上所有的 s 都是不正确的。
有用的链接:未定义的行为和序列点
c - int a=1, b=a++; 调用未定义的行为?
是否int a=1, b=a++;
调用未定义的行为?a
的初始化及其在初始化程序中的访问和修改之间没有序列点干预b
,但据我所知,初始化不是对象的“修改”;指定一个初始化器来给出对象的“初始值”。根据 6.7.8 初始化,第 8 段:
初始化器指定存储在对象中的初始值。
并且在对对象的任何访问之前将“初始”作为排序似乎是合理的。以前是否考虑过这个问题,是否有公认的解释?
c - 像“int a=4,*ptr=&a;”这样的语句是否存在“序列点”问题 还是“x+=4,y=x*2;”?
我对整个序列点的理解是基本的。我所拥有的只是一些粗略的直观想法,即“一旦遇到序列点,我们可以确定之前评估的所有副作用都是完整的”。我还读到,在printf("%d",a++,++a,a++)
行为未定义之类的语句中,逗号不表示序列点,而分号表示。因此,与其凭直觉进行猜测和猜测,我觉得一个非常严谨和确凿的答案会对我有很大帮助。
以下类型的语句在 C 中是安全且确定的:
如果是,如何?特别是在第二种情况下,如果逗号不是序列点,我们如何确定在赋值中使用它之前x
已经递增了?对于第一条语句,我如何确定在分配地址之前已经初始化并分配了内存?我应该安全地使用以下内容:4
y=x*2
a
ptr
和
编辑我对逗号运算符的理解告诉我这些语句是安全的。但是在阅读了关于序列点以及类似的东西printf("%d",a++,++a,a++)
是如何未定义的之后,我有了第二个想法。
c - 另一个序列点查询:*p++ = getchar() 是如何工作的?
示例 7 表达式的分组并不能完全确定它的求值。在以下片段中:
表达式语句被分组,就好像它被写成
但是 p 的实际增量可以发生在前一个序列点和下一个序列点( ; )之间的任何时间,并且对 getchar 的调用可以在需要其返回值之前的任何时间发生。
所以基本上我将其理解为未指定的行为-要么*p = getchar(); p++;
OR p++; *p = getchar()
。请注意,这;
意味着一个序列点,但整个表达式中没有其他序列点。
所以这个语法是没用的。而且,对于指针赋值,++ 和 -- 几乎是没用的。正确的?
c - 像 "for(i=1;i<=10;printf("%d\n";i),i++) 这样的东西在 C 中是否有效且无 UB?
以下两个代码块是否完全相同并实现相同的东西?当我运行程序时它显示相同的东西,但我希望能得到一些严格的解释。
和
循环需要有效的for
C 语句作为参数,不是吗?但是,即使我已经在 StackOverflow 上验证了类似语句x+=4,y=x*2;
是安全的,因为这里的逗号充当序列点,但在上面的循环printf("%d\n",i),i++)
中作为参数传递的语句是否相同?for
如果是,请费心回答由此产生的小问题:
是否
comma
充当涉及许多逗号分隔的语句中的序列点函数调用如下:
printf("Enter number\n"),scanf("%d",&number),printf("You entered %d",number);