C++ 使用-1初始化结构或数组的{}初始化中的无符号
非常简短 如何创建设置了所有位的无符号常量 …可用于用{}初始化字段 …未从GCC 4.7.2中获得-Wnarrowing警告 以下情况并不令人满意:C++ 使用-1初始化结构或数组的{}初始化中的无符号,c++,c,c++11,initialization,narrowing,C++,C,C++11,Initialization,Narrowing,非常简短 如何创建设置了所有位的无符号常量 …可用于用{}初始化字段 …未从GCC 4.7.2中获得-Wnarrowing警告 以下情况并不令人满意: struct U { unsigned ufield; }; struct Uc { unsigned char ufield; }; struct ULL { unsigned long long ufield; }; struct U32 { unsigned ufield; }; struct U64 { uint64_t u
struct U { unsigned ufield; };
struct Uc { unsigned char ufield; };
struct ULL { unsigned long long ufield; };
struct U32 { unsigned ufield; };
struct U64 { uint64_t ufield; }
typedef
//any of the above U Uc ULL U32 U64, we will arbitrarily choose:
U Ueg;
// somewhere far away
Ueg u = {-1}; // well defined by C standard, GCC 4.7.2 -Wnarrowing warning
Ueg u = {~0U}; // finit width constant, warnings in some places, silent non-all-1s-mask others
Ueg u = {~0ULL}; // ditto
Ueg u = {-1ULL}; // ditto
基本上,用户,编写{}初始化的人,
不知道飞机场的类型。
他只知道它是一个无符号类型,但不知道它有多宽。
不完全是哪种无符号类型
*我希望语法尽可能简单优雅的另一个原因*
我不妨提一下别的:这里的“用户”实际上并没有编写C或C++程序。
他正在编辑一个配置文件。
一个程序,一个简单的Perl或Python脚本,处理配置文件并生成C代码。
这个程序不是很复杂,目前通过的文本块看起来像
Foo: {-1,2,3};
产生
类型定义
struct Some_struct{unsigned a;unsigned b,unsigned c;}
Some_Struct={-1,2,3};//同上
基本上,我希望能够为一个表示
“设置此无符号值中的所有位”。
不必知道一个未签名的文件有多大。
而且没有处理配置文件的程序变得太复杂
以免潜在的答案提供者抱怨这是一个新的约束,不现实,等等:我对模板也有同样的问题。 也就是说,对于模板类型,我想写一个“无符号的任何宽度,都是1”的文本。 在模板中,我可能更愿意使用一些丑陋、丑陋、丑陋的语法 这显然能够做到: 但我真的希望有一个简单、优雅的语法 *真正的问题* 问:有没有办法创建一个“都是1”的常数 不触发GCC 4.7.2警告 简介 我遇到一个程序,该程序使用文本常量-1初始化结构的一个字段,例如
> cat ./-1u.cpp
#include <stdio.h>
struct U { unsigned ufield; } ustruct = { -1 };
int main(int argc, char** argv)
{
printf("ustruct.ufield = %08x\n",ustruct.ufield);
}
注意:这只是一个警告。将-1转换为无符号的结果在C/C++标准中有很好的定义:
> ./a.out
ustruct.ufield = ffffffff
我不喜欢警告,所以我想让这个恼人的警告保持沉默。我不喜欢使用适用于整个文件的#pragmas,因为这可能会禁用对真正bug的警告
(顺便说一句,只有在初始化字段时才会收到警告,而不是在初始化非字段时
unsigned u = -1; // no cmpiler warning.
做
让虫子安静下来
但有人指出,如果字段的类型不是无符号的,而是uint64_t,
然后~0U提供与-1不同的结果:0x00000000FFFFFFFF而不是0xFFFFFFFFFF。
(即1的32位,而不是1的64位。)
结构U和初始化代码可能位于完全不同的位置,
我们希望能够增加字段的大小,一个位掩码,而不通知用户。
其目的是得到一个“所有1的掩码”,无论使用什么无符号类型
同样地
struct U { unsigned ufield; } ustruct = { -1u };
使bug静音。(令我惊讶的是-我不知道-1可以被认为是未签名的。)
但它也是一个有限宽度常数
细节
这是一个测试程序。
(顺便说一句,我所要问的是有符号文字常量-1的用法
初始化未签名的成员。其他警告只是测试。
您无需向我解释64位数字不适合32位。)
这个怎么样?它只适用于未签名的类型,但问题特别指出未签名。(请参见下面的rubenvb评论。)
#包括
#包括
#包括
#包括
#包括
模板
T所有的位都是一个(){
static_assert(std::is_unsigned::value,“类型必须无符号”);
返回std::numeric_limits::max();
}
结构用户界面{
typedef unsigned int表示_类型;
_型飞机场;
};
结构{
typedef unsigned long_类型;
_型飞机场;
};
结构U64{
typedef uint64_类型;
_型飞机场;
};
int main(){
使用名称空间std;
Ui={all_bits_one()};
ULL={all_bits_one()};
U64 U64={all_bits_one()};
不能为什么不随型号提供口罩
C:
C++:
抛开所有花哨的模板代码不谈,下面是一些花哨的C++11代码:
struct Foo
{
unsigned a;
unsigned long b;
unsigned long long c;
};
Foo foo = { decltype(Foo::a)(-1), decltype(Foo::b)(-1), decltype(Foo::c)(-1) };
这很容易出错,但功能强大
最好的解决方案仍然是为此使用(键入的)enum(类)
。受Ali启发,但使用模板参数推断
T all_bits_one(T& dummy) { return ~(T()); }
unsigned long u = all_bits_one(u);
@Ali的答案的一个稍微友好一点的版本:
#include <type_traits>
struct all_ones_type {
template <typename T,
typename = typename std::enable_if<std::is_unsigned<T>::value>::type>
constexpr operator T () const
{ return static_cast<T>(-1); }
} const all_ones;
#include <iostream>
struct X {
unsigned short a;
unsigned long b;
unsigned long long c;
};
int main() {
X x = { all_ones, all_ones, all_ones };
std::cout << x.a << "\n"
<< x.b << "\n"
<< x.c << std::endl;
}
#包括
结构所有\u个\u类型{
模板
constexpr运算符T()const
{返回静态_cast(-1);}
}康斯特所有人;
#包括
结构X{
无符号短a;
无符号长b;
无符号长c;
};
int main(){
X X={all_one,all_one,all_one};
std::cout另一种方法
// C++03 and C++11
Ueg u = { (Ueg().ufield - 1) };
// C99 and C11 (works only inside of functions)
Ueg u = { (Ueg){0}.ufield - 1 };
通过将uint初始化为-1,您可能希望所有位都设置为“1”?
在这种情况下:
typedef uint MyUIntType;
MyUIntType mID = (MyUIntType)~0;
~
将“1的补码”应用于0
,有效地翻转其所有位。
结果将是uint类型可以容纳的最大值,这在0是有意义的值并且变量需要初始化为“其他值”的情况下非常有用“为什么不使用<代码> ~0UL/<代码>?<代码> -1U/<代码>不是“代码< >代码> U>代码>的后缀:它是常数<代码> 1U/COD>作为一元否定操作符<代码> -/COD>的操作数。<代码> -1 < /C>是正确的方式,为什么HCC GCC对此警告,这是愚蠢的。-哦,你编译为C++,然后是GCC。可能有一点(不确定,但它说C++11不允许)。@H2CO3-~0ULL得到-Woverflow错误。//另外,我生活的世界中,有时可能很快就会使用uint128,甚至可能会使用uint512。\0ULL不能保证是最广泛的数字。@D
struct U { unsigned ufield; };
#define U_MASK (-1U)
// somewhere far away
U u = {U_MASK};
struct U { unsigned ufield; static constexpr unsigned MASK = -1; };
// somewhere far away
U u = {U::MASK};
struct Foo
{
unsigned a;
unsigned long b;
unsigned long long c;
};
Foo foo = { decltype(Foo::a)(-1), decltype(Foo::b)(-1), decltype(Foo::c)(-1) };
T all_bits_one(T& dummy) { return ~(T()); }
unsigned long u = all_bits_one(u);
#include <type_traits>
struct all_ones_type {
template <typename T,
typename = typename std::enable_if<std::is_unsigned<T>::value>::type>
constexpr operator T () const
{ return static_cast<T>(-1); }
} const all_ones;
#include <iostream>
struct X {
unsigned short a;
unsigned long b;
unsigned long long c;
};
int main() {
X x = { all_ones, all_ones, all_ones };
std::cout << x.a << "\n"
<< x.b << "\n"
<< x.c << std::endl;
}
// C++03 and C++11
Ueg u = { (Ueg().ufield - 1) };
// C99 and C11 (works only inside of functions)
Ueg u = { (Ueg){0}.ufield - 1 };
typedef uint MyUIntType;
MyUIntType mID = (MyUIntType)~0;