真的很简短
如何创建一个所有位都设置的无符号常量?
...您可以使用它来初始化带有 { } 的字段,
...没有从 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
基本上,编写 {} 初始化的用户不知道 ufield 的类型。他只知道它是无符号类型,但不知道它有多宽。不完全是哪种无符号类型。
* 我想要尽可能简单优雅的语法的另一个原因 *
我不妨提点别的:这里的“用户”实际上并不是在编写 C 或 C++ 程序。他正在编辑一个配置文件。一个程序,一个简单的 Perl 或 Python 脚本,处理配置文件,并生成 C 代码。这个程序不是很复杂,目前通过的文本块看起来像
Foo: {-1,2,3};
生成 typedef struct Some_Struct { unsigned a; 无符号 b,无符号 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);
}
尽管早期版本的 GCC 毫无警告地接受了这一点,但相当新的 GCC 4.7.2 版本提供了一个警告:
> /SOME-PATH/import/gcc/gcc-4.7.2.pkg/installdir/bin/g++ -Wall ./-1u.cpp
./-1u.cpp:3:46: warning: narrowing conversion of '-1' from 'int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
注意:这只是一个警告。将 -1 转换为无符号的结果在 C/C++ 标准中得到了很好的定义:
> ./a.out
ustruct.ufield = ffffffff
我不喜欢警告,所以我想消除这个烦人的警告。我不喜欢使用适用于整个文件的#pragmas,因为这可能会禁用对真正错误的警告。
(顺便说一句,只有在初始化字段时才会收到此警告。在初始化非字段时不会
unsigned u = -1; // no cmpiler warning.
正在做
struct U { unsigned ufield; } ustruct = { ~0U };
使错误沉默。
但有人指出,如果字段的类型不是无符号的,而是 uint64_t,那么 ~0U 提供的结果与 -1 不同:0x00000000FFFFFFFF 而不是 0xFFFFFFFFFFFFFFFF。(即 32 位 1,而不是 64 位 1。)
struct U 和初始化代码可能位于完全不同的位置,我们希望能够在不通知用户的情况下增加字段的大小,即位掩码。目的是获得正在使用的任何无符号类型的“全 1 掩码”。
相似地
struct U { unsigned ufield; } ustruct = { -1u };
使错误沉默。(令我惊讶的是 - 我不知道 -1 可以被认为是无符号的。)
但也是一个有限宽度常数。
细节
这是一个测试程序。(顺便说一句,我要问的是使用有符号文字常量 -1 来初始化无符号成员。其他警告只是测试。你不需要向我解释 64 位数字不需要适合 32 位。)
sh-3.2$ cat ./-1u.cpp
#include <stdio.h>
unsigned um1 = -1;
unsigned un0u = ~0u;
unsigned un0ull = ~0ull;
struct Foo {
unsigned um1;
unsigned un0u;
unsigned un0ull;
};
Foo foo = { -1, ~0u, ~0ull };
int main(int argc, char** argv)
{
printf("um1 = %08x\n",um1);
printf("un0u = %08x\n",un0u);
printf("un0ull = %08x\n",un0ull);
printf("foo.um1 = %08x\n",foo.um1);
printf("foo.un0u = %08x\n",foo.un0u);
printf("foo.un0ull = %08x\n",foo.un0ull);
}
sh-3.2$ /mips/proj/performance/import/gcc/gcc-4.7.2.pkg/installdir/bin/gcc -Wall ./-1u.cpp
./-1u.cpp:7:20: warning: large integer implicitly truncated to unsigned type [-Woverflow]
./-1u.cpp:15:28: warning: narrowing conversion of '-1' from 'int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
./-1u.cpp:15:28: warning: narrowing conversion of '18446744073709551615ull' from 'long long unsigned int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
./-1u.cpp:15:28: warning: large integer implicitly truncated to unsigned type [-Woverflow]
sh-3.2$ /mips/proj/performance/import/gcc/gcc-4.7.2.pkg/installdir/bin/g++ -Wall ./-1u.cpp
./-1u.cpp:7:20: warning: large integer implicitly truncated to unsigned type [-Woverflow]
./-1u.cpp:15:35: warning: narrowing conversion of '-1' from 'int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
./-1u.cpp:15:35: warning: narrowing conversion of '18446744073709551615ull' from 'long long unsigned int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
./-1u.cpp:15:35: warning: large integer implicitly truncated to unsigned type [-Woverflow]
在早期的编译器中不会出现:
sh-3.2$ /usr/bin/g++ -Wall ./-1u.cpp
./-1u.cpp:7: warning: large integer implicitly truncated to unsigned type
./-1u.cpp:15: warning: large integer implicitly truncated to unsigned type
/usr/bin/g++ --version
g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-51)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.