Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用-1初始化结构或数组的{}初始化中的无符号_C++_C_C++11_Initialization_Narrowing - Fatal编程技术网

C++ 使用-1初始化结构或数组的{}初始化中的无符号

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

非常简短

如何创建设置了所有位的无符号常量

…可用于用{}初始化字段

…未从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 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;