这个问题出现在问题答案的评论中.当类型转换为int时,C/C++ bool类型总是保证为0或1吗?
有问题的代码在bool不初始化其值的情况下分配(本地)数组.
const int n = 100;
bool b[n];
Run Code Online (Sandbox Code Playgroud)
显然,价值观b是不确定的.
一些评论者认为阅读b[0]是不明确的行为.这是在C++标准中的任何地方陈述的吗?我仍然相信相反:
显然存储已分配,并且基本bool类型的初始化已完成,因为它没有构造函数.因此,它肯定与取消引用未初始化的指针或在未初始化的非平凡对象上调用方法/强制转换操作符不同.标准似乎涵盖了这些具体案例.
C中的行为确实未定义:C中声明的未初始化变量会发生什么?它有价值吗?一些受访者似乎对这两者感到困惑.
在最新的C++ 0x草案中,我找不到不确定值的定义,尤其是没有允许访问这样的值来触发处理器陷阱的定义.事实上,Bjarne的Stroustrup的是不知道的inderminate值可能是什么:http://zamanbakshifirst.blogspot.com/2007/02/c-indeterminate-value.html
我检查过自己,我写了一个这样的程序
int main() {
int i;
cout << i;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我运行了几次程序,结果一直都是一样的,零.我在C中尝试过,结果是一样的.
但我的教科书说
如果不初始化在函数内定义的变量,则变量值保持未定义.这意味着该元素将采用先前驻留在内存中该位置的任何值.
当程序总是为变量分配空闲内存位置时,这怎么可能?怎么可能是零以外的东西(我假设默认的空闲内存值为零)?
我偶然发现了令我惊讶的行为:
写作时:
int x = x+1;
Run Code Online (Sandbox Code Playgroud)
在C/C++程序中(或者涉及新创建的变量x的更复杂的表达式),我的gcc/g ++编译没有错误.在上述情况下,X之后为1.请注意,前一个声明的范围中没有变量x.
所以我想知道这是否是正确的行为(甚至可能在某些情况下有用)或者只是我的gcc版本或gcc的解析器pecularity.
顺便说一句:以下不起作用:
int x++;
Run Code Online (Sandbox Code Playgroud) 我终于追查了一个错字错误,这与下面的代码类似.但是编译器不应该检测到这个(默认选项)吗?
#include <stdio.h>
int main()
{
int c = c;
return printf("%d\n", c);
}
$ gcc --version
gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3
Run Code Online (Sandbox Code Playgroud) 如果具有静态存储持续时间的对象的C++构造函数未初始化成员,那么是否需要保留先前的零初始化,或者是否使成员具有不确定的值?
我对C++规范的解读是它与自身相矛盾.
例:
#include <iostream>
struct Foo { Foo(); int x; } object;
Foo::Foo() { }
int main() { std::cout << object.x << std::endl; }
Run Code Online (Sandbox Code Playgroud)
Foo()构造函数没有显式初始化成员object.x,因此根据12.6.2第8段中的注释:
该成员具有不确定的价值.
但是,通过各种初始化的细节,这似乎是不正确的.成员object.x由于具有静态存储持续时间而被零初始化,然后我看不到任何改变它的东西.
关于构造函数,适用的12.6.2中的文本是:
该实体是默认初始化的.
在8.5第7段中,默认初始化的相关情况是:
......没有执行初始化
我读到这意味着默认初始化不会改变先前的零初始化.
我是否遗漏了一些其他文本,它们在构造函数调用开始时将所有成员重置为"不确定值"?
我在stackoverflow上发现了关于零初始化和默认初始化的各种其他问题,但我看不到任何分析在默认初始化跟随同一实体的早期初始化之后会发生什么.
在这种情况下,可能没有实际效果.但是在一个更复杂的构造函数中,一些成员被初始化而其他成员没有,编译器是否必须准确地跟踪哪些字节/位被初始化?或者它是否只是初始化整个对象(例如,将构造函数简化为memset()调用) )?
以下代码是否有效C++,根据标准(折扣... s)?
bool f(T& r)
{
if(...)
{
r = ...;
return true;
}
return false;
}
T x = (f(x) ? x : T());
Run Code Online (Sandbox Code Playgroud)
众所周知,在这个项目使用的GCC版本中编译(4.1.2和3.2.3 ...甚至没有让我开始...),但应该吗?
编辑:我添加了一些细节,例如f()概念在原始代码中的样子.基本上,它意味着在某些条件下初始化x.
以下C++程序编译得很好(g ++ 5.4至少在调用时发出警告-Wall):
int main(int argc, char *argv[])
{
int i = i; // !
return 0;
}
Run Code Online (Sandbox Code Playgroud)
甚至像
int& p = p;
Run Code Online (Sandbox Code Playgroud)
被编译器吞噬了.
现在我的问题是:为什么这样的初始化合法?是否有任何实际的用例,或者它只是语言的一般设计的结果?
以下是现代C中未定义的行为:
union foo
{
int i;
float f;
};
union foo bar;
bar.f = 1.0f;
printf("%08x\n", bar.i);
Run Code Online (Sandbox Code Playgroud)
并打印1.0f的十六进制表示.
但是以下是未定义的行为:
int x;
printf("%08x\n", x);
Run Code Online (Sandbox Code Playgroud)
那这个呢?
union xyzzy
{
char c;
int i;
};
union xyzzy plugh;
Run Code Online (Sandbox Code Playgroud)
这应该是未定义的行为,因为没有plugh编写成员.
printf("%08x\n", plugh.i);
Run Code Online (Sandbox Code Playgroud)
但是这个呢.这是未定义的行为吗?
plugh.c = 'A';
printf("%08x\n", plugh.i);
Run Code Online (Sandbox Code Playgroud)
现在大多数C编译器都有sizeof(char) < sizeof(int),sizeof(int)或者是2或4.这意味着在这些情况下,最多plugh.i会写入50%或25%,但读取剩余的字节将读取未初始化的数据,因此应该是未定义的行为.在此基础上,是整个读取未定义的行为?
int a = a ;
Run Code Online (Sandbox Code Playgroud)
根据赋值运算符规则,它应该从右到左读取行.看到'a'未声明的编译器后应该给出编译错误.
但是it is giving garbage value.请澄清一下.
我在 Debian 8 x86_64 上使用 g++ 4.9.2。我发现未定义行为消毒剂 (UBsan) ( -fsanitize=undefined) 错误:
algebra.cpp:206:8: runtime error: load of value 127,
which is not a valid value for type 'bool'
Run Code Online (Sandbox Code Playgroud)
代码来自 Crypto++ 库。这是代码algebra.cpp:206(和一些相关代码):
206 struct WindowSlider
207 {
208 WindowSlider(const Integer &expIn, bool fastNegate, unsigned int windowSizeIn=0)
209 : m_exp(expIn), m_windowModulus(Integer::One()), m_windowSize(windowSizeIn), m_windowBegin(0), m_fastNegate(fastNegate), m_firstTime(true), m_finished(false)
210 {
...
249 Integer m_exp, m_windowModulus;
250 unsigned int m_windowSize, m_windowBegin;
251 word32 m_expWindow;
252 bool m_fastNegate, m_negateNext, m_firstTime, m_finished;
253 };
Run Code Online (Sandbox Code Playgroud)
它在几个地方被调用,例如: …