很抱歉再次打开这个话题,但是考虑这个话题本身已经开始给我一个未定义的行为.想要进入定义明确的行为区域.
特定
int i = 0;
int v[10];
i = ++i; //Expr1
i = i++; //Expr2
++ ++i; //Expr3
i = v[i++]; //Expr4
Run Code Online (Sandbox Code Playgroud)
我认为上面的表达式(按此顺序)为
operator=(i, operator++(i)) ; //Expr1 equivalent
operator=(i, operator++(i, 0)) ; //Expr2 equivalent
operator++(operator++(i)) ; //Expr3 equivalent
operator=(i, operator[](operator++(i, 0)); //Expr4 equivalent
Run Code Online (Sandbox Code Playgroud)
现在来到这里的行为是来自C++ 0x的重要引用.
$ 1.9/12-"表达式(或子表达式)的评估通常包括值计算(包括确定用于左值评估的对象的身份以及获取先前分配给对象以进行右值评估的值)和启动副作用".
$ 1.9/15-"如果标量对象的副作用相对于同一标量对象的另一个副作用或使用相同标量对象的值计算的值没有排序,则行为未定义."
[注意:与不同参数表达式相关的值计算和副作用未被排序. - 尾注]
$ 3.9/9-"算术类型(3.9.1),枚举类型,指针类型,指向成员类型的指针(3.9.2),std :: nullptr_t和这些类型的cv限定版本(3.9.3)统称为标量类型."
在Expr1中,对表达式i(第一个参数)的评估在对评估operator++(i)(具有副作用)方面没有考虑.
因此,Expr1具有未定义的行为.
在Expr2中,对表达式i(第一个参数)的评估在对评估operator++(i, 0)(具有副作用)的评估方面没有考虑.
因此,Expr2具有未定义的行为.
在Expr3中,在调用operator++(i)外部之前,必须完成对单个参数的评估operator++.
因此,Expr3具有良好定义的行为. …
我已经开始研究C++ 0x了.我偶然发现了以下表达方式:
int l = 1, m=2;
++l *= m;
Run Code Online (Sandbox Code Playgroud)
我不知道第二个表达式是否有明确定义的行为.所以我在这里问.
不是UB吗?我只是渴望知道.
编辑:尚未回答 - 链接的问题是关于普通的r值,初始化列表是一个单独的,如果相关的概念.
这个语句定义得很好,或者在初始化列表中使用前缀增量运算符,对于在列表中出现两次的变量,未定义的行为?
struct T t = { i, ++i };
Run Code Online (Sandbox Code Playgroud)
我对ANSI C最感兴趣,但知道其他版本的C和/或C++是否有所不同也很有用.如果类似以下的类似结构是合法的:
struct T t = { i, i++ };
struct T t = { ++i, ++i };
struct T t = { i++, ++i };
struct T t = { i++, i++ };
Run Code Online (Sandbox Code Playgroud) 在下面的代码中摘录了一段较大的代码
void func(int* usedNum, int wher) {
*usedNum = *usedNum + 1 > wher ? ++(*usedNum) : wher + 1;
}
int main(void) {
int a = 11, b = 2;
func(&a, b);
}
Run Code Online (Sandbox Code Playgroud)
一个警告发出
warning: operation on '* usedNum' may be undefined [-Wsequence-point]
*usedNum = *usedNum + 1 > wher ? ++(*usedNum) : wher + 1;
Run Code Online (Sandbox Code Playgroud)
代码有问题吗?
我怀疑的是这个以及它所说的部分
序列指向逻辑表达式,例如&&和|| 和三元运算符?:和逗号运算符表示在右侧操作数之前计算左侧操作数.这几个操作数是C++中唯一引入序列点的操作数.
对于那些发现折磨阅读评论的人:最初的问题没有恰当地提出,造成误解是不公平的.我对这个主题的看法有两个方面
三元运算符不会(以意想不到的方式)混乱序列点(其中,两个分支在C,C++的每个版本中排序 - 请参阅提供的链接)
是x = ++x问题吗?如coliru链接所示,我们编译为c ++ 14.那里的操作定义很好(对注释的引用),但旧版本的c ++和c将其视为未定义.那为什么会有警告? …
我正在学习在Ubuntu 12.10上第一次使用libusb v1.0.0.这是我用来尝试理解如何使用此API的一些小测试代码:
#include <libusb-1.0/libusb.h>
...
libusb_device **list;
libusb_get_device_list(ctx, &list); // Returns 11 USB devices which is correct.
for (size_t idx = 0; list[idx] != NULL; idx ++)
{
libusb_device *dev = list[idx];
libusb_device_descriptor desc = {0};
int rc = libusb_get_device_descriptor(dev, &desc);
Run Code Online (Sandbox Code Playgroud)
此时,rc == 0,意味着它应该已经成功完成.来源:*libusb_get_device_descriptor()*的文档.
但结构desc总是空的.没有任何字段被设置.如果我将上面的最后两行更改为:
libusb_device_descriptor desc = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int rc = libusb_get_device_descriptor(dev, &desc);
Run Code Online (Sandbox Code Playgroud)
...然后当libusb_get_device_descriptor()返回时,我看到desc保持不变,向我确认我没有得到我对此API的期望.
我还尝试以a.outroot 身份运行,以防万一这需要提升权限.进行谷歌搜索libusb_get_device_descriptor并没有让我到任何地方.
我跑来试试这段代码的相关命令:
sudo …Run Code Online (Sandbox Code Playgroud) 我猜答案是"不",但从编译器的角度来看,我不明白为什么.
我制作了一个非常简单的代码,它使得编译器诊断非常糟糕(clang和gcc),但是我想确认代码在报告错误诊断之前没有格式化.我应该指出,这些不是编译器错误,输出在所有情况下都是正确的,但我对这些警告有疑问.
请考虑以下代码:
#include <iostream>
int main(){
int b,a;
b = 3;
b == 3 ? a = 1 : b = 2;
b == 2 ? a = 2 : b = 1;
a = a;
std::cerr << a << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
赋值a是一个重言式,意思是a将在两个三元语句之后初始化,无论如何b.GCC对此代码非常满意.Clang更聪明,发现了一些愚蠢的东西warning: explicitly assigning a variable of type 'int' to itself [-Wself-assign],但没什么大不了的.
现在是相同的事情(至少在语义上),但语法更短:
#include <iostream>
int main(){
int b,a = (b=3,
b == 3 ? a = 1 …Run Code Online (Sandbox Code Playgroud) 我有以下代码.
int x=80;
int &y=x;
x++;
cout<<x<<" "<<--y;
Run Code Online (Sandbox Code Playgroud)
输出结果是80 80.我不明白怎么做.我认为x的输出是81,尽管我对y一无所知.参数变量如何受减量运算符的影响.有人可以解释一下吗?
考虑以下代码:
std::unordered_map<int, std::string> data;
data[5] = foo();
Run Code Online (Sandbox Code Playgroud)
按照什么顺序data[5]和foo()处理?如果foo()抛出异常,是否创建了5项目data?
如果行为取决于C++的版本,那些版本有何不同?
在表达式中a + b,a保证在之前进行评估b,还是未指定评估的顺序?我认为这是后者,但我很难在标准中找到明确的答案.
由于我不知道C是否处理与C++有所不同,或者如果在C++ 11中简化了评估顺序规则,我将把这个问题标记为三个.
当我遇到这个问题时,我正在阅读我的教科书
起初我认为这是未定义的行为,因为a已被多次修改.
那么我就读了这个问题并说它提到了步骤所以我可能认为这个问题是正确的.
所以我的问题是:
注意:一个解释清楚的答案将得到我的投票
c++ ×10
c ×4
c++11 ×2
expression ×2
clang ×1
gcc ×1
initializer ×1
libusb ×1
libusb-1.0 ×1
side-effects ×1
stdmap ×1