2010-02-28 2 views
12

У меня есть следующий массив, который мне нужно использовать вручную на растровых изображениях.C++: предупреждение компилятора для большого unsigned int

const unsigned int BITS[32] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 
           2048, 4096, 8192, 16384, 32768, 65536, 131072, 
           262144, 524288, 1048576, 2097152, 4194304, 
           8388608, 16777216, 33554432, 67108864, 134217728, 
           268435456, 536870912, 1073741824, 2147483648}; 

К сожалению, при компиляции я получаю

предупреждение: это десятичная константа без знака только в ISO C90

Как я могу удалить это?

+0

Смотрите этот же вопрос: http://stackoverflow.com/questions/2347936/cant-get-ride-of-this-decimal-constant -is-unsigned-only-in-iso-c90-warning –

+0

Зачем вы это делаете? Если вы считаете, что таблица поиска будет быстрее, чем просто вычислять эти значения по мере необходимости, подумайте еще раз ... – Nemo

ответ

15

Целочисленные литеры в C по умолчанию имеют тип «signed int» (изменить: но см. Комментарии для оговорок). Последнее число есть слишком большой, чтобы быть представлена ​​в виде подписанного 32-разрядного целого числа, и поэтому вы должны сообщить компилятору, что это целое число без знака от суффикса его с «U», как:

2147483648U 

Обратите внимание, что вы также можете добавить суффикс «L», чтобы сделать его «длинным», но на многих системах, которые все еще 32-битные и, следовательно, не имеют значения.

Кроме того, есть гораздо менее подвержены ошибкам (и проще для чтения) способ, чтобы написать этот код, с помощью оператора битового сдвига:

const unsigned int BITS[32] = {1U, 1U<<1, 1U<<2, 1U<<3, 1U<<4, 
           /* and so on */ 
           1U<<31}; 

Или писать в шестнадцатеричном, если вы не 't любят битовые сдвиги по какой-то причине:

const unsigned int BITS[32] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 
           /* and so on */ 
           0x80000000U}; 
+0

Почему компилятор рассматривает его тогда как int, а не автоматически превращает его в uint? Тем более, что он точно знает, в каком типе он будет храниться. – gruszczy

+0

Во многих случаях вы не можете знать, какой тип является константой (например, как аргумент функции в функции varargs), поэтому он должен быть указан явно. Затруднительно предположить, что тип подразумевается несколько раз, и его нужно явно указывать в других, а также путать с тем, чтобы одна и та же константа была разным для систем с разными размерами int. Кроме того, поскольку C никогда не делает вывод типа такого рода, добавление его для этого одного случая может значительно усложнить парсер без значительной выгоды. –

+3

@gruszczy: В C89/90 неопределенная десятичная константа должна интерпретироваться как 'int',' long' или 'unsigned long' (какая из них подходит). В C99 он должен интерпретироваться как 'int',' long' или 'long long' (в зависимости от того, что подходит первым). Это то, что компилятор пытается сказать этим предупреждением. По-видимому, на этой платформе 'long' имеет тот же размер, что и' int'. Компилятор в основном говорит: «Возможно, вы пытались создать« подписанный длинный »connstant или даже константу« long long », но по правилам C89/90 я должен сделать это« unsigned long ». – AnT

6

Ваша постоянная должна быть указана в качестве знака тоже использовать

2147483648UL 

(UL = Unsigned Long), или просто

2147483648U 

для неподписанных Int.

Как ваш код прямо сейчас, константа, по умолчанию равная int и, следовательно, подписанная, назначается unsigned int, которая генерирует ваше предупреждение.

+0

Это сработало, спасибо большое :-) – gruszczy

+3

Педально говоря, ошибка не в том, что (обычная int) константа присваивается неподписанному int; назначение не имеет значения. Ошибка заключается в том, что значение «2147483648» слишком велико, чтобы быть подписанным int, и поэтому возникает переполнение при создании подписанной константы int в первую очередь. –

+2

На самом деле, настоящая причина для предупреждения заключается в том, что компилятор должен выбрать 'unsigned long' для постоянного типа. (Обратите внимание, что эта константа не является 'unsigned int', это' unsigned long'.) И она должна выбрать ее в C89/90 специально, вместо того, чтобы выбирать более крупный подписанный тип (который он может поддерживать) или после C99 правила и выбор 'long long'. Вот что такое предупреждение и почему оно относится к «ISO C90». Например, в C99 неопределенная десятичная константа никогда не будет иметь тип unsigned. – AnT

1

Не нужно определять тип данных как беззнаковый тип;

int variable_name=2147483648U; 

остальное просто преобразовать десятичное значение в шестнадцатеричный ...

Смежные вопросы