一个主要是为了好玩/好奇的问题:如何for
在C++中编写循环,迭代两个a bool
(ie true
和false
)的值,只使用操作bool
(即没有转换到其他类型)?
背景是我想检查一个等式有多少解决方案存在(A && B) || (!B && !C && !D) == true
,并开始编写类似的东西,for (bool A=false; ??? ; ++A) for (bool B=false; ...)
但立即被卡住???
- 即继续循环的条件是什么?当然我把它重写为使用int,我也知道do ... while
循环会起作用,但是如果有可能编写这样的for
循环我很好奇吗?既然SO似乎没有答案,我决定问:)
更新:请注意,for(bool A=false; !A; A=true)
在至少两个现在删除的答案中建议的"明显"变体将仅运行一次迭代,因为对于第二次迭代,条件!A
变为false
循环结束.
经过一番思考之后,我相信如果没有第二个变量或者像DietmarKühl建议的基于指针的构造,在C++ 03中这样做是不可能的.条件应该在期望的执行中测试三次,因此bool的两个值是不够的.do-while循环有效,因为第一次迭代是无条件执行的,条件只检查两次,因此可以使用bool值在继续和退出之间进行选择.
这不是建议的做法(也不是未定义的行为),而是关于将整数类型的所有字节转换为值的c ++标准实际上保证的内容
(unsigned char)0
.
在下面的代码片段中,if-statement使用的表达式是否保证在c ++ 11中被评估为true?
std::memset (
reinterpret_cast<char*> (&a), // int a;
(unsigned char)0,
sizeof (int)
);
if (a == 0) {
...
}
Run Code Online (Sandbox Code Playgroud)
通过阅读C99和C++ 11标准中的引文(在本文中进一步说明),我们发现C99明确保证所有位设置为的整数类型0
将表示该0
类型中的值.
我在C++ 11标准中找不到这种保证.
5.2.1.2/1多字节字符
所有位为零的字节应被解释为与移位状态无关的空字符.这样的字节不应作为任何其他多字节字符的一部分出现.
6.2.6.2/1整数类型
任何填充位的值都是未指定的.45)符号位为零的有符号整数类型的有效(非陷阱)对象表示是相应无符号类型的有效对象表示,并且应表示相同的值.
对于任何整数类型,所有位为零的对象表示应该是该类型中零值的表示.
2.3/3字符集[lex.charset]
基本执行字符集和基本执行宽字符集应各自包含基本源字符集的所有成员,以及表示alert,backspace和回车符的控制字符,以及空字符(分别为null宽字符),其表示具有全零位.
这很尴尬,但按位AND运算符在C++标准中定义如下(强调我的).
执行通常的算术转换; 结果是其操作数的按位AND功能.运算符仅适用于整数或无范围的枚举操作数.
这看起来对我来说毫无意义.据我所知,"按位AND函数"在标准中的任何地方都没有定义.
我知道AND功能已被充分理解,因此可能不需要解释."按位"一词的含义也应该相当清楚:该函数应用于其操作数的相应位.但是,操作数的位构成不清楚.
是什么赋予了?
我有以下代码:
#include <iostream>
struct T
{
int a, b, c;
};
int main()
{
T t = {0};
std::cout << t.a << ',' << t.b << ',' << t.c << '\n';
}
Run Code Online (Sandbox Code Playgroud)
输出:
0,0,0
Run Code Online (Sandbox Code Playgroud)
经过多年的代码在一个关键的生产环境中愉快地运行,提供一个重要的功能,项目的要求发生了变化,我需要输出1,1,1
.
于是,我换{0}
到{1}
:
#include <iostream>
struct T
{
int a, b, c;
};
int main()
{
T t = {1};
std::cout << t.a << ',' << t.b << ',' << t.c << '\n';
}
Run Code Online (Sandbox Code Playgroud)
输出:
1,0,0
Run Code Online (Sandbox Code Playgroud)
我1,1,1
反而期待了. …
正如文档中已经讨论过的,bool
数据类型占用至少一个字节的内存.之前在SO上问了一个类似的问题(bool类型变量如何存储在内存中?(C++)),但是这个讨论和文档似乎只讨论了布尔数据类型占用的空间量,而不是实际发生的事情.我这样做的记忆:
bool b = true;
那么在记忆中实际发生了什么?7位未用于存储此信息的情况会怎样?标准是否规定了此行为?
他们是不确定的?或者在C++总部有人这样做:
enum bool : char
{
false = 0,
true = 1
};
Run Code Online (Sandbox Code Playgroud) 我应该如何将匿名联盟归零?我在cppreference页面上找不到任何关于它的内容.将memset
荷兰国际集团是最大的成员与0
在这里工作?
例如 -
#include <iostream>
#include <cstring>
struct s{
char a;
char b[100];
};
int main(){
union {
int a;
s b;
char c;
};
// b.a = 'a'; (1)
std::memset(&b, 0, sizeof(b));
std::cout << a << "\n";
std::cout << b.a << " " << b.b << "\n";
std::cout << c << "\n";
}
Run Code Online (Sandbox Code Playgroud)
如果这样可行,我应该在使用memset()
激活最大的成员之前取消注释(1)吗?
在严格别名方面,这段代码是明确定义的行为吗?
_Bool* array = malloc(n);
memset(array, 0xFF, n);
_Bool x = array[0];
Run Code Online (Sandbox Code Playgroud)
有效类型的规则具有memcpy
和memmove
(C176.5§6)的特殊情况,但不适用于memset
.
我认为有效的类型就变成了unsigned char
.因为第二个参数memset
需要转换为unsigned char
(C17 7.24.6.1)并且由于有效类型的规则,(C176.5§6):
...或者被复制为字符类型数组,然后该访问的修改对象的有效类型以及不修改该值的后续访问是从中复制值的对象的有效类型,如果它有一个.
array
后存储的数据的有效类型是memset
什么?array[0]
访问是否违反了严格的别名?因为_Bool
不是严格别名规则中排除的类型(与字符类型不同).Bool应该转换为1表示真值,否则为0.但是,它没有说明它们实际上如何存储在内存中.如果我在bool中存储任意非零值会发生什么?标准是否保证在将其转换为整数时的正确行为?
例如,给定以下程序,
#include <string.h>
int main()
{
bool b;
memset( &b, 123, sizeof( b ) );
return b;
}
Run Code Online (Sandbox Code Playgroud)
标准是否保证程序将返回1?
这个程序0
在我的机器中返回:
#include <stdbool.h>
union U {
_Bool b;
char c;
};
int main(void) {
union U u;
u.c = 3;
_Bool b = u.b;
if (b == true) {
return 0;
} else {
return 1;
}
}
Run Code Online (Sandbox Code Playgroud)
AFAICT _Bool
是一种整数类型,至少可以存储0
和1
,并且true
是整数常量1
.在我的机器上,_Bool
有一个sizeof(_Bool) == 1
,和CHAR_BITS == 8
,这意味着_Bool
有256个表示.
我在C标准中找不到关于陷阱表示的更多内容_Bool
,我无法找到创建_Bool
一个表示不同于0
或1
(在支持两个以上表示的实现上)是否正常,如果可以,这些陈述是表示真或假.
我可以在标准的发现是什么情况,当_Bool
与整数相比,整数转换成0
它是否有值表示0
,并给1 …