编辑:这个问题不应该被关闭,如果你查看答案,你会发现它们完全不同(旧问题没有提到 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 开始就不存在序列点,但我使用它们是因为新的措辞对我来说更难理解。
根据 ISO/IEC 9899:2017:
严格遵守的程序应仅使用本文档中指定的语言和库的那些功能。它不应产生依赖于任何未指定、未定义或实现定义的行为的输出,并且不应超过任何最小实现限制。
然而,几页后,它说:
活动位置是显示设备上该
fputc函数输出的下一个字符将出现的位置。将打印字符(由函数定义)写入显示设备的目的isprint是在活动位置显示该字符的图形表示,然后将活动位置前进到当前行的下一个位置。书写方向是特定于语言环境的。如果活动位置位于一行的最终位置(如果有),则显示设备的行为未指定。
由于似乎没有任何方法可以判断活动位置是否位于一行的最终位置,因此无法在不冒调用未指定行为的风险的情况下输出到显示设备,因此不可能编写严格遵守程序。这是一个错误还是我遗漏了什么?
c standards standards-compliance unspecified-behavior output
#include <iostream>
int foo() {
std::cout<<"foo() is called\n";
return 9;
}
int bar() {
std::cout<<"bar() is called\n";
return 18;
}
int main() {
std::cout<<foo()<<' '<<bar()<<' '<<'\n';
}
// Above program's behaviour is unspecified
// clang++ evaluates function arguments from left to right: http://melpon.org/wandbox/permlink/STnvMm1YVrrSRSsB
// g++ & MSVC++ evaluates function arguments from right to left
// so either foo() or bar() can be called first depending upon compiler.
Run Code Online (Sandbox Code Playgroud)
上述程序的输出取决于编译器.未指定评估函数参数的顺序.我读到这个的原因是它可以导致高度优化的代码.如何不指定函数参数的精确评估顺序有助于编译器生成优化代码?
AFAIK,评估顺序严格按Java,C#,D等语言规定.
c++ optimization operator-precedence compiler-optimization unspecified-behavior
对于使用不同编译器的相同代码,我得到了不同的结果。这是一个未定义的行为吗?
#include <stdio.h>
int a;
int b=10;
int puan_ekle(int puan, int bonus){
puan=puan+bonus;
a=puan-5;
bonus--;
return bonus;
}
int main(){
a=23;
printf("Result1 %d \n", a);
a=a+puan_ekle(a,b);
printf("Result2 %d \n", a);
a=a+puan_ekle(a,b);
printf("Result3 %d \n", a);
}
Run Code Online (Sandbox Code Playgroud) 我正在编写一些C++代码,用于娱乐和练习,以了解有关语言功能的更多信息.我想更多地了解静态变量及其在递归函数中的行为.在g ++编译器中尝试此代码,我得到了预期的结果:
#include <iostream>
using namespace std;
int f(const int& value)
{
static int result = 0;
return result += value;
}
int main()
{
cout << f(10) << ", " << f(f(10)) << ", " << f(f(f(10)));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但我的朋友在Microsoft Visual C++ 6中测试了相同的代码.输出是50, 80, 90我用其他C++编译器(g ++,Borland,Code :: blocks和MingW在Linux,Win和Mac下)输出测试的110, 100, 40.我无法理解输出如何50, 80, 90......
为什么MSVC的输出不同?
的逗号序列操作者引入了一个顺序点的表达式中.我想知道这是否意味着下面的程序避免了未定义的行为.
int x, y;
int main()
{
return (x++, y) + (y++, x);
}
Run Code Online (Sandbox Code Playgroud)
如果它确实避免了未定义的行为,它仍然可能未指定,即返回几个可能值中的一个.我认为在C99中,它只能计算1,但实际上,各种版本的GCC将此程序编译成可返回的可执行文件2.Clang生成一个返回的可执行文件1,显然与我的直觉一致.
最后,这是C11改变了吗?
我只知道i = i++;是未定义的行为,但如果在表达式中调用了两个或更多函数,并且所有函数都相同.这是不确定的?例如:
int func(int a)
{
std::cout << a << std::endl;
return 0;
}
int main()
{
std::cout << func(0) + func(1) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud) 给出以下代码:
std::ofstream stream("somefile");
if (!stream)
{
return 1;
}
Run Code Online (Sandbox Code Playgroud)
调用.write(....)并使用stdc ++和libc ++时,流处于二进制模式(std::ios::binary)。
但是,当使用MSVC (2015 / 2017RC1)时,它似乎处于文本模式或某种奇怪的状态,因为生成的文件大于实际写入的文件。
但是,如果我明确设置了模式,则std::ios::binaryMSVC的行为与std::ofstream前面提到的其他标准库的实现类似。
示例代码:
#include <vector>
#include <cstdio>
#include <fstream>
std::size_t fsz(const char* filename) {
std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
return static_cast<std::size_t>(in.tellg());
}
int main() {
std::ofstream stream("filename");
if (!stream)
return 1;
std::vector<unsigned long long int> v = {0x6F1DA2C6AC0E0EA6, 0x42928C47B18C31A2, 0x95E20A7699DC156A, 0x19F9C94F27FFDBD0};
stream.write(reinterpret_cast<const char*>(v.data()),v.size() * sizeof(unsigned long long int));
stream.close();
printf("expect: %d\n", …Run Code Online (Sandbox Code Playgroud) 我想直接讲一下术语。考虑:
for (double d = 0.0; d != 1.0; d += 0.1)
cout << d << " ";
Run Code Online (Sandbox Code Playgroud)
如果我理解正确,由于双重运算不精确,因此此循环可以是有限的或无限的。是否认为这是未指定或未定义的行为?
std::frexp是一个从浮点变量中删除指数并将其放入exp类型变量中的函数int。int无论指数真正需要多少位,它都会根据链接页面使用:
如果要存储的值
*exp超出 的范围int,则行为未指定。
那么,如何检查“是否超出”*exp的范围呢?int
我正在考虑static_assert在我的代码中添加 a 来比较FLT_MIN_EXP&FLT_MAX_EXP与INT_MIN&INT_MAX。但是,我担心会犯一个相差一的错误,因为我不完全理解这些常量的描述。
FLT_MIN_EXP:
最小负整数,使得 FLT_RADIX 乘以比该整数小一倍的幂是归一化的
float...
FLT_MAX_EXP:
最大正整数,使得 FLT_RADIX 乘以该整数减一的幂是可表示的有限
float...
(我已经static_assert(FLT_RADIX == 2);在代码中包含了,所以在我的例子中基数等于 10 不是问题。)
例如,在以下代码中:
int myarray[3];
int x = myarray[1];
Run Code Online (Sandbox Code Playgroud)
代码是否保证在恒定时间内成功执行,x具有一些整数值?或者编译器是否可以跳过为这个完全/发出代码发出代码来启动GNU Chess并仍然符合C++标准?
这在类似于数组的数据结构中很有用,但可以在恒定时间内初始化.(对不起,我没有Aho,Hopcroft和Ullman的副本,所以不能查找名字.)
我从C编译器得到以下测试代码的asm代码错误.这是由于未定义的行为?
void SimulatedTest(void)
{
if ( (a) || (b && c || d) == 1 )
{
i = 2;
}
else
{
i = 4;
}
}
Run Code Online (Sandbox Code Playgroud)
标准说:
6.5.16分配操作员
操作数的评估顺序未指定.如果尝试修改赋值运算符的结果或在下一个序列点之后访问它,则行为未定义
C运算符优先规则
- ()
- ==
- || &&
对于问题情况:if((a)||(b && c || d)== 1)编译器按以下顺序计算表达式并生成错误的代码
1.(b && c || d) - > R1
2.R1 == 1 - > R2
3.(a)|| R2
但是,编译器会为以下情况生成正确的代码
案例1 : . 当没有关系'=='操作时
if ( (a) || (b && c || d) )//compiler generates expected code
Run Code Online (Sandbox Code Playgroud)
情况2:为逻辑OR运算添加括号时 …
在C++中,有些东西出现在明确定义和未定义之间.具体而言,这些被称为实现定义和未指定.现在,我对未指明的东西很感兴趣.
什么时候可以使用这些功能,什么时候应该避免?是否有正确代码的未指定行为的良好示例?在编写软件时,它是否是最佳选择?
Matt McNabb提供的定义:
未定义 - 任何事情都可能发生
实现定义 - 有限数量的结果是可能的,编译器的文档必须说明会发生什么
未指定 - 可能有限数量的结果 - 通常标准描述了可能结果的集合
定义明确 - 以上都不是
格式良好的程序 - 无错误编译的程序(可能表现出未定义的行为)
后续问题:
放松的原子是否被指定为未指定或明确定义?