标签: sequence-points

关于循环缓冲区中简洁索引处理的建议

我已经实现了一个循环缓冲区,我想要一个简洁的方法来更新缓冲区指针,同时正确处理环绕.

假设一个大小为10的数组,我的第一个响应是:

size_t ptr = 0;  
// do some work...
p = ++p % 10;
Run Code Online (Sandbox Code Playgroud)

静态分析,以及gcc -Wall -Wextra,由于序列点违规而正确地拍了我的手腕以查找未指定的行为.明显的修复方法如下:

p++;
p %= 10;
Run Code Online (Sandbox Code Playgroud)

然而,我正在寻找更简洁的东西(即一个单行)来"封装​​"这个操作.建议?除了p ++之外; p%= 10; :-)

c c99 sequence-points

2
推荐指数
1
解决办法
265
查看次数

序列点警告说明

我是 C 初学者。当我尝试运行以下代码时:

#include <stdio.h>

    int main(void) {

    int a = 3, b;

    b = printf("%d %d", a, a++);
    a = printf(" %d", b);
    printf(" %d", a);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它向我展示:

error: operation on 'a' may be undefined [-Werror=sequence-point]
b = printf("%d %d", a, a++);
                        ^
Run Code Online (Sandbox Code Playgroud)

但在这里我只改变了一次的值。那为什么会出现序列点错误呢?

我正在使用 -Wall -Werror 标志。

c sequence-points

2
推荐指数
1
解决办法
4191
查看次数

序列点和副作用

根据序列点定义,序列点是" 执行序列中称为序列点的指定点,以前的评估的所有副作用都保证完整 "

因此,在下面的程序中,++操作符的所有副作用必须在进入&&操作符的第二部分之前执行,即,i应该像&&序列点一样递增到1 .

#include<stdio.h>

int main()
{
    int i=0,a;
    a=i++&&1;
    printf("%d",a);
    getchar();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

预期产量:

1(1&&1=1)

实际产量:

0

为什么i第二部分之前不增加?

使用三元运算符也可以提供相同的输出:

#include<stdio.h>

int main()
{
    int i=0,a;
    a=(i++)?1:0;

    printf("%d",a);
    getchar();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

三元运算符也是序列点.那么这不应该给出输出1而不是0吗?

c sequence-points post-increment

2
推荐指数
1
解决办法
120
查看次数

在条件运算符中使用对象两次是否会产生UB?

正如我所了解的那样,条件运算符(三元运算符“?”)保证了其操作数的求值顺序,我想知道是否向变量分配了?在两个表达式之一中使用该变量的返回值。是否成为UB。这是我所拥有的:

我编写了这个程序,尝试根据字符串是否str包含有效的数字字符将字符串转换为整数,例如:+-.0123456789,因此我在一个表达式中使用了std::stoiwith std::string::find_first_of和conditional运算符:

std::string str = "a^%^&fggh67%$hf#$";
std::size_t pos = 0;
auto val = (((pos = str.find_first_of("0123456789.+-")) != std::string::npos) ?
    std::stoi(str.substr(pos)) : -1);

std::cout << val << std::endl; // 67

str = "a^%^&fggh__#$!%$hf#$";
pos = 0;
val = (((pos = str.find_first_of("0123456789.+-")) != std::string::npos) ?
    std::stoi(str.substr(pos)) : -1);

std::cout << val << std::endl; // -1
Run Code Online (Sandbox Code Playgroud)

正如你所看到的一段代码看起来做工精细,我知道,如果值-1是在无意中发现str,我们不知道是否val拥有-1成功运作或失败(?运营商)的。但是我只想知道我编写的这段代码是否具有UB?

  • 感谢在上一个主题UB中指导我的成员,我已经将其更正。

c++ conditional-operator sequence-points

2
推荐指数
1
解决办法
68
查看次数

在 C++17 中,这段代码应该产生警告吗?

正如在这个godbolt链接上看到的

c++14 模式下的 clang(但不是 c++17)和 c++17 模式下的 GCC 会产生关于排序的警告。我假设在 C++17 中,= 的 rhs 上的所有内容都在 lhs 之前进行评估,所以我不确定 gcc 警告是否正确。

Code is:
static int index =0; 
void f(int* pindex){
        pindex[index] = 5;
        pindex[index] = index++;

}
int main(){

}
Run Code Online (Sandbox Code Playgroud)

gcc警告是:

:在函数“void f(int*)”中:
:4:30: 警告:对“索引”的操作可能未定义 [-Wsequence-point]
4 |         pindex[index] = index++;

  |                         ~~~~~^~
Run Code Online (Sandbox Code Playgroud) :4:30: 警告:对“索引”的操作可能未定义 [-Wsequence-point]

编译器返回:0

注意:我知道标准没有指定警告,指定问题wrt警告比谈论序列点/排序保证要容易得多。

c++ sequence-points c++17

2
推荐指数
1
解决办法
99
查看次数

这个程序有任何序列点问题吗?

#include<stdio.h>
 int main()
 {  
       int i=7,j;
       j=(i++,++i,j*i); 
       return 0;
}
Run Code Online (Sandbox Code Playgroud)

j =(i ++,++ i,j*i);这个定义得很好吗?让我清楚我的怀疑.

c operator-precedence sequence-points

1
推荐指数
1
解决办法
207
查看次数

c/c++ 中的未定义行为:i++ + ++i vs ++i + i++

想象一下,我们有以下代码:

int i = 1;
int j = i++ + ++i;
Run Code Online (Sandbox Code Playgroud)

我知道这是一个未定义的行为,因为在分号之前,它是一个序列点,的值i已经改变了不止一次。这意味着即使运算符 plus 的优先级是从左到右,编译器也可能有两种可能性:

情况1)

  1. 取值i++--- 的值为i1
  2. 取值++i--- 的值为i2
  3. 执行运算符加号并将结果分配为 ​​3j并执行副作用i++(此步骤的顺序也未定义,但我们不在乎,因为它不会改变结果)

情况 2)

  1. 取值i++--- 的值为i1
  2. i++---的副作用i是 2
  3. 取值++i---当前值为i3
  4. 做运算符加号并将结果分配给 4 j

如果这里没有问题,我有一个问题:

int j = ++i + i++;

上面的代码仍然是未定义的行为吗?

在我看来,只有一种可能:

  1. ++i---的副作用i是 2
  2. 取值i++--- 的值为i2
  3. 执行运算符加号并将结果分配为 ​​4j并执行副作用 …

c++ side-effects undefined-behavior sequence-points

1
推荐指数
1
解决办法
1962
查看次数

每个转换是否与输入/输出格式说明符相关联C中的序列点?

关于C中序列点的维基百科条目具有以下序列点:

与输入/输出格式说明符关联的每次转换后.例如,在表达式printf("foo%n%d",&a,42)中,在评估%n之后和打印之前有一个序列点42

但C标准也说:

函数指示符的评估顺序,实际参数和实际参数中的子表达式是未指定的,但在实际调用之前有一个序列点.

对于像这样的代码,这两点似乎是矛盾的

int i=1;
printf("%d, %d and %d\n", i++, i++, i--); 
Run Code Online (Sandbox Code Playgroud)

根据每个格式说明符后的维基百科条目,有一个序列点,所以它将打印如下: 1,2,3

但根据C标准中未指明的beaviour条目,它可以打印任何东西.

c stdio operator-precedence undefined-behavior sequence-points

1
推荐指数
1
解决办法
94
查看次数

为什么逗号运算符似乎不在我的代码中的"if"语句和"else"语句之间工作?

我知道如下的语句(逗号代替分号)看起来很奇怪:

 if(a<b)printf("Hello\n"),a+=5,b/=5,printf("%d,%d",a,b);
Run Code Online (Sandbox Code Playgroud)

但它完全正常,我读过它是因为comma这里作为一个序列点.我可以理解这一点.但我只是不明白为什么以下失败然后我也使用了一个else:

  if(a<b)printf("Hi\n"),else printf("Bye\n"),a+=5,b/=5,printf("%d,%d",a,b);
Run Code Online (Sandbox Code Playgroud)

它给出了错误expected expression before 'else'.

为什么第二个语句会出错?在第一个语句中,我们看到它comma作为一个序列点.那么为什么它之前没有这样做else?第二个导致错误的情况有什么特别之处?这是我的完整程序:

#include<stdio.h>

int main(void)
{
    int a=30,b=45;

    //if(a<b)printf("Hello\n"),a+=5,b/=5,printf("%d,%d",a,b); //Works well
    if(a<b)printf("Hi\n"),else printf("Bye\n"),a+=5,b/=5,printf("%d,%d",a,b); 

}
Run Code Online (Sandbox Code Playgroud)

c if-statement comma sequence-points

0
推荐指数
1
解决办法
270
查看次数

无限循环的原因

signed char ch=5;
while(ch = ch--)
    printf("%d",ch);
Run Code Online (Sandbox Code Playgroud)

我看了这个.清楚地说明了声明和声明(;)的结尾是序列点.

所以我不明白为什么上面的那个运行无限时间并打印相同的值[5].

c sequence-points

0
推荐指数
1
解决办法
86
查看次数