ДЕЙСТВИТЕЛЬНО BRIEF
Как создать неподписанную константу со всеми установленными битами?
..., который вы можете использовать для инициализации поля с помощью {} s,
..., который не получает предупреждения от GCC 4.7.2.
Следующие неудобны:
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 или С++. Он редактирует файл конфигурации. Программа, простой Perl или Python script, обрабатывает конфигурационный файл и генерирует код C. Эта программа не очень сложна и в данный момент проходит через куски текста, которые выглядят как
Foo: {-1,2,3};
для генерации ЬурейеЕ struct Some_Struct {unsigned a; unsigned b, unsigned c; } Some_Struct = {-1,2,3};//ditto
В принципе, я хочу иметь удобный синтаксис для простого литерала, который гласит: Msgstr "Все биты в этом значении без знака установлены". Не зная, насколько велика неподписанная. И без программы, которая обрабатывает конфигурационный файл, становясь слишком сложным.
Чтобы потенциальный поставщик ответов не жаловался, что это новое ограничение, не реалистичное и т.д.:
У меня была такая же проблема с шаблонами.
То есть с типами шаблонов, где я хочу написать литерал, который "без знака любой ширины, все 1s".
В шаблоне я мог бы быть более готов сделать некоторые из уродливых, Ugly, UGLY синтаксиса
что, очевидно, способно это сделать:
но я действительно хотел, чтобы был простой, элегантный, синтаксис.
* Реальный вопрос *
Q: существует ли способ создать константу, которая является "все 1s set" без запуска предупреждения 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 в unsigned хорошо определен в стандартах 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. (I.e 32 бита 1s, а не 64 бит 1s.)
Структура U и код инициализации могут жить в совершенно разных местах, и мы хотели бы иметь возможность увеличить размер поля, битмаску, не сообщая пользователям. И цель состоит в том, чтобы получить "маску всех 1s" любого беззнакового типа.
Аналогично
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.