好吧,我真的不是真的需要这个答案,我只是好奇.
类似*ptr++ = a的表达式是完全有效的,因为我们操作两个对象ptr,*ptr但如果我写*ptr++ = *ptr + a它仍然有效?
例如,请考虑以下代码段:
int main(void){
int a[] = {5,7,8,9,2};
int* p =a;
*p++ = 76; /*altering the first element */
*p++ = *p + 32; /*altering the second element */
p = a;
int i;
for(i = 0;i<5; i++)
printf("%d ",*p++);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我认为表达没有什么可担心的,*p++ = *p + 32;但我不确定所涉及的序列点.
并且f(x)+(g(y))可以确保g(y)先打电话吗?我知道表达式中的顺序在很多情况下是未定义的,但在这种情况下括号是否有效?
我有这个代码来获取表单的字符串bla_2并将其分开:
void separate(char* str, char* word, int* n) {
int i = 0;
while(str[i] != '_') {
word[i] = str[i++];
}
*n = str[++i] - '0';
}
Run Code Online (Sandbox Code Playgroud)
我有:
warning: operation on ‘i’ may be undefined [-Wsequence-point]
Run Code Online (Sandbox Code Playgroud)
但我只是i通过++运营商改变,我没有分配任何东西。
那么,为什么是 UB,如果是的话?如果没有,如何摆脱警告?
请注意,在我看来,这个问题处理了一个不同的问题。
上面的链接讨论的是 C++ 中的序列点和副作用。
一句话,就是在两个序列点之间,如果我们有多个副作用,副作用的顺序是不确定的。
例如,
int x = 1;
int y = 2;
int z = x++ + y++;
Run Code Online (Sandbox Code Playgroud)
我们可以肯定的是,z等于3后z得到3,x并且y会增加---有两个副作用,所以我们不知道第一个哪一个增加。
此外,上面的链接列出了各种序列点。
我的问题是,Java 有完全相同的情况吗?我的意思是相同种类的序列点和相同的未定义行为?
编辑:这个问题不应该被关闭,如果你查看答案,你会发现它们完全不同(旧问题没有提到 C++17)。
我正在阅读一篇 PVS博客文章,他们提到了以下错误。
(减少)
std::map<int,int> m;
m[7]=5;
auto val = 15;
if (!m.contains(val)){
m[val] = m.size(); // bug here
}
Run Code Online (Sandbox Code Playgroud)
根据博客文章,这是错误的。我一直认为 operator [] 对 map 的调用是一个函数调用,所以 .size() 在 [] 之前被排序,因为函数充当序列点。
那么为什么这是一个错误呢?
注意:我知道从 C++11 开始就不存在序列点,但我使用它们是因为新的措辞对我来说更难理解。
注意:这是一个自我问答,并且针对“Let us C”一书宣传的错误信息进行了更直观的提问。另外,请让我们不要讨论C++,这个问题是关于 C 的。
我正在阅读 Yashwant Kanetkar 的书“Let us C”。
书中有如下例子:
#include <stdio.h>
int main(void) {
int a = 1;
printf("%d %d %d", a, ++a, a++);
}
Run Code Online (Sandbox Code Playgroud)
作者声称这段代码应该输出3 3 1:
令人惊讶的是,它输出
3 3 1. 这是因为 C 的调用约定是从右到左。也就是说,首先1通过表达式a++,然后a增加到2。然后结果++a就通过了。即 a 增加到 3 然后通过。最后,传递 a 的最新值,即 3。因此按从右到左的顺序1, 3, 3通过。一旦printf( ) 收集它们,它就会按照我们要求它打印它们的顺序(而不是传递它们的顺序)打印它们。这样3 3 1就打印出来了。
但是,当我编译代码并使用 运行它时clang,结果是1 2 2 …
c undefined-behavior sequence-points language-lawyer order-of-execution
#include <stdio.h>
int main(void)
{
int a = 0, b = 1;
a = (a = 5) && (b = 0);
printf("%d", a);
printf("%d", b);
}
Run Code Online (Sandbox Code Playgroud)
变量的值a被更新两次,这违反了 C 标准。所以我认为这将取决于编译器。我在很多在线 C 编译器中运行了这段代码,所有编译器都给出了相同的输出。
实施例7表达的分组并不完全决定其评估.在以下片段中:
Run Code Online (Sandbox Code Playgroud)#include <stdio.h> int sum; char *p; /* ... */ sum = sum * 10 - '0' + (*p++ = getchar());表达式语句被分组,就好像它被写为
Run Code Online (Sandbox Code Playgroud)sum = (((sum * 10) - '0') + ((*(p++)) = (getchar())));但是p的实际增量可以在前一个序列点和下一个序列点(;)之间的任何时间发生,并且对getchar的调用可以在需要其返回值之前的任何点发生.
所以基本上我把它理解为未指明的行为 - 要么是*p = getchar(); p++;OR p++; *p = getchar().请注意,这;意味着一个序列点,但整个表达式中没有其他序列点.
所以这种语法没用.而且,几乎,++和 - 用于指针分配是没用的.对?
这是一个示例代码段:
int i = 4,b;
b = foo(i++) + foo(i++);
Run Code Online (Sandbox Code Playgroud)
我很确定它不是未定义的,因为在调用之前有一个序列点foo.但是,如果我使用-Wall标志编译代码,则会生成编译器警告warning: operation on 'i' may be undefined.我意识到它说may,但我想仔细检查一下我是否正确.
我理解C使用序列点的概念来识别模糊计算,并且该=运算符不是序列点.但是,我无法看到执行语句时有任何歧义
i = ++i
根据我的理解,这仅仅是评估任何在&i,增加它,并将其存储在同一位置.然而,GCC将其标记为:
[警告]'i'上的操作可能未定义[-Wsequence-point]
我错过了一些关于=功能的方法吗?
编辑:在标记为重复之前,请注意我浏览了有关序列点和未定义行为的其他帖子.他们都没有具体地解决表达式i=++i(注意前增量).提到的表达一般i=i++是a=b++ + ++b,等等.我对它们中的任何一个都毫无疑问.
c increment operator-precedence undefined-behavior sequence-points