标签: sequence-points

表达式中有序列点a ^ = b ^ = a ^ = b,还是未定义?

据称"巧妙"(但实际上效率低下)交换两个整数变量而不是使用临时存储的方式通常涉及这一行:

int a = 10;
int b = 42;

a ^= b ^= a ^= b; /*Here*/

printf("a=%d, b=%d\n", a, b); 
Run Code Online (Sandbox Code Playgroud)

但我想知道,复合赋值运算符^=不是序列点,是吗?这是否意味着它实际上是未定义的行为?

c undefined-behavior sequence-points compound-assignment

13
推荐指数
4
解决办法
617
查看次数

当p和q指向同一个对象时,"*p = ++(*q)"是否未定义?

在阅读序列点后,我了解到这i = ++i是未定义的.

那么这段代码怎么样:

int i;
int *p = &i;
int *q = &i;
 *p = ++(*q);           // that should also be undefined right?
Run Code Online (Sandbox Code Playgroud)

假设p和q的初始化取决于某些(复杂)条件.他们可能像上面的情况一样指向同一个对象.会发生什么?如果未定义,我们可以使用哪些工具进行检测?

编辑:如果两个指针不应该指向同一个对象,我们可以使用C99限制吗?这是"严格"的意思吗?

c c99 operator-precedence sequence-points

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

序列点和方法链

以下表达式通常用于演示未定义的未指定行为:

f() + g()
Run Code Online (Sandbox Code Playgroud)

如果f()g()都有一些共享对象的副作用,则行为是不确定的不确定,因为执行的顺序是未知的.f()可以在之前评估,g()反之亦然.

现在我想知道当你在一个对象上链接成员函数时会发生什么.比方说,我有一个类,叫做实例的实例obj,它有两个成员函数,foo()bar()这两个修改的对象.这些函数的执行顺序不是可交换的.在一个接一个之前调用一个的效果与用另一个方式调用它们的效果不同.这两个方法都返回一个引用,*this以便它们可以像这样链接:

obj.foo().bar()
Run Code Online (Sandbox Code Playgroud)

但这是不明确的行为吗?我在标准中找不到任何东西(不可否认只是扫描),区分了这个表达式和我在帖子顶部给出的表达.两个函数调用都是full-expression的子表达式,因此它们的执行顺序是未指定的.但肯定foo() 必须先评估,以便bar()知道要修改哪个对象.

也许我错过了一些明显的东西,但我无法看到序列点的创建位置.

c++ method-chaining sequence-points

12
推荐指数
2
解决办法
915
查看次数

placement-new是否会引入序列点?

考虑以下代码行:

new (p++) T();
Run Code Online (Sandbox Code Playgroud)

如果构造函数T()抛出异常,p保证已经增加了吗?

c++ constructor exception side-effects sequence-points

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

printf中的序列点

在这里读到有一个序列点:

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

但是,当我运行此代码时:

int your_function(int a, int b) {
    return a - b;
}

int main(void) {
    int i = 10;

    printf("%d - %d - %d\n", i, your_function(++i, ++i), i);
}
Run Code Online (Sandbox Code Playgroud)

而不是我期望得到的:

12 - 0 - 12

这意味着没有为转换格式说明符创建序列点.http://en.wikipedia.org是错误的,还是我只是误解了某些内容,或者在这种情况下gcc是否不合规(顺便提一下Visual Studio 2015会产生相同的意外结果)?

编辑:

我理解,参数your_function的评估顺序和分配给参数的顺序是未定义的.我不是在问我为什么我的中期是0.我在问为什么其他两个术语都是12.

c c++ printf undefined-behavior sequence-points

11
推荐指数
2
解决办法
696
查看次数

我会在C17中新定义i = i ++吗?

在遇到问题" 为什么这些构造使用前后增量未定义的行为? "之后,我决定抓住最新的草案,为我能找到的下一个C标准,并阅读更多相关内容.
在我在C17草案中发现以下段落后不久:

表达式是操作符和操作数的序列,其指定值的计算,或指定对象或函数,或者生成副作用,或执行其组合.在运算符结果的值计算之前对运算符的操作数的值计算进行排序
来源:ISO/IEC 9899:2017,第6.5.1节"表达式"

现在我有点困惑.这i = i++是不是意味着定义了行为?我这次看了另一个草案,C99:

表达式是操作符和操作数的序列,其指定值的计算,或指定对象或函数,或者生成副作用,或执行其组合.
资料来源:ISO/IEC 9899:1999,第6.5.1节"表达式"

它错过了那句话!

问题

  1. 我误解了什么吗?
  2. 答案是否过时了?
  3. 我看错了选秀吗?

c operator-precedence sequence-points language-lawyer c17

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

Chained compound assignments with C++17 sequencing are still undefined behaviour?

Originally, I presented a more complicated example, this one was proposed by @n. 'pronouns' m. in a now-deleted answer. But the question became too long, see edit history if you are interested.

Has the following program well-defined behaviour in C++17?

int main()
{
    int a=5;
    (a += 1) += a;
    return a;
}
Run Code Online (Sandbox Code Playgroud)

I believe this expression is well-defined and evaluated like this:

  1. The right side a is evaluated to 5.
  2. There are no side-effects of the right side.
  3. The …

c++ sequence-points language-lawyer c++17

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

带有strcmp的Segfault

我在以下方面使用strcmp

  1. 传递char []数组名称
  2. 将指针传递给字符串文字,但第二个结果是seg错误.即使我已经确认指针指向正确的字符串文字,我很困惑为什么我得到seg错误..这是代码: -

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int argc, char const *args[])
    {
      char firstName[strlen(*++args)];
      strcpy(firstName, *args);
      char lastName[strlen(*++args)];
      strcpy(lastName, *args);
      printf("%s\t%s\n", firstName, lastName);
    
      printf("%d\n", strcmp(firstName, lastName));// this works
    
      printf("%d\n", strcmp(*(--args),*(++args)));//this gives me a seg fault
    
      return EXIT_SUCCESS;
    }
    
    Run Code Online (Sandbox Code Playgroud)

我将它保存为str.c,当我编译它时,首先我得到以下警告:

[Neutron@Discovery examples]$ gcc -Wall str.c -o str

str.c: In function ‘main’:
str.c:15: warning: operation on ‘args’ may be undefined
Run Code Online (Sandbox Code Playgroud)

最后运行它,给出一个seg错误,如下所示

[Neutron@Discovery examples]$ ./str Jimmy Neutron


Jimmy   Neutron

-4

Segmentation fault (core dumped)
Run Code Online (Sandbox Code Playgroud)

c evaluation args strcmp sequence-points

10
推荐指数
2
解决办法
2033
查看次数

C++ cout副作用测序

假设以下代码:

#include <iostream>
using namespace std;

char one()
{
    cout << "one\n";
    return '1';
}

char two()
{
    cout << "two\n";
    return '2';
}

int main(int,char**)
{
    // 1:
    cout << one()
         << '\n'
         << two()
         << '\n';

    // 2:
    operator<<(
        operator<<(
            operator<<(
                operator<<(
                    cout, 
                    one()),
                '\n'),
            two()),
        '\n');
}
Run Code Online (Sandbox Code Playgroud)

执行标记为1和的行,并2使用ideone编译时执行相同的操作,它打印如下:

two
one
1
2
Run Code Online (Sandbox Code Playgroud)

从我的观点来看,我们在这里观察到的是未指定的行为,因为未指定解析函数参数的顺序.

这是一个在采访中的问题,打印上面给出的序列(没有任何替代方案)应该是正确答案,但它是否真的正确?

c++ sequence-points unspecified-behavior

10
推荐指数
2
解决办法
739
查看次数

序列点"在库函数返回之前"的结果是什么?

最近的这个问题中,一些代码显示有未定义的行为:

a[++i] = foo(a[i-1], a[i]);
Run Code Online (Sandbox Code Playgroud)

因为即使实际调用foo()是一个序列点,该分配未测序,所以你不知道该功能是否被调用后的副作用不++i发生或之前.

进一步思考这一点,函数调用的序列点只保证在输入函数后执行评估函数参数的副作用,例如

int y = 1;
int func1(int x) { return x + y; }
int main(void)
{
    int result = func1( y++ ); // guaranteed to be 3
}
Run Code Online (Sandbox Code Playgroud)

但是看看标准,还有§7.1.4p3(关于标准库的章节):

库函数返回之前有一个序列点.

我的问题是:这一段的结果是什么?为什么它只涉及库函数以及实际依赖的代码类型?

像(无意义的代码)这样​​的简单想法

errno = 0;
long result = ftell(file) * errno;
Run Code Online (Sandbox Code Playgroud)

这个时候仍然是未定义的,乘法是不确定的.我正在寻找一个利用这个特殊保证的例子§7.1.4p3使库函数成为可能.


关于建议的重复, …

c sequence-points language-lawyer

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