Прошу прощения, если вопрос покажется странным. Я отлаживаю свой код, и это кажется проблемой, но я не уверен.
Спасибо!
Прошу прощения, если вопрос покажется странным. Я отлаживаю свой код, и это кажется проблемой, но я не уверен.
Спасибо!
Это зависит от того, каким вы хотите видеть поведение. int не может содержать многие значения, которые может содержать unsigned int.
Вы можете использовать как обычно:
int signedInt = (int) myUnsigned;
но это вызовет проблемы, если значение unsigned превышает максимально допустимое значение int. Это означает, что половина возможных значений unsigned приведет к ошибочному поведению, если вы специально не следите за этим.
Вам, вероятно, следует пересмотреть, как вы храните значения, в первую очередь, если вам нужно конвертировать без уважительной причины.
EDIT: Как упоминалось в комментариях ProdigySim, максимальное значение зависит от платформы. Но вы можете получить к нему доступ с помощью INT_MAX и UINT_MAX.
Для обычных 4-байтовых типов:
4 bytes = (4*8) bits = 32 bits
Если используются все 32 бита, как в unsigned, максимальное значение будет 2^32 - 1 или 4,294,967,295.
Знаковое int эффективно жертвует одним битом ради знака, поэтому максимальное значение будет 2^31 - 1 или 2,147,483,647. Обратите внимание, что это половина другого значения.
<limits.h>) требуются даже в автономной (т. е. не размещенной) системе.
- person DevSolar; 11.07.2021
Целое число без знака может быть преобразовано в знаковое (или наоборот) с помощью простого выражения, как показано ниже:
unsigned int z;
int y=5;
z= (unsigned int)y;
Хотя это не относится к вопросу, вы хотели бы прочитать следующие ссылки:
ИМХО вопрос вечный. Как указано в различных ответах, присвоение значения без знака, которое не находится в диапазоне [0, INT_MAX], определяется реализацией и может даже вызвать сигнал. Если беззнаковое значение считается представлением числа со знаком в виде дополнения до двух, вероятно, наиболее переносимым способом является IMHO способ, показанный в следующем фрагменте кода:
#include <limits.h>
unsigned int u;
int i;
if (u <= (unsigned int)INT_MAX)
i = (int)u; /*(1)*/
else if (u >= (unsigned int)INT_MIN)
i = -(int)~u - 1; /*(2)*/
else
i = INT_MIN; /*(3)*/
Ветвь (1) очевидна и не может вызывать переполнение или ловушки, поскольку она сохраняет значение.
Ветвь (2) прилагает некоторые усилия, чтобы избежать переполнения целого числа со знаком, беря дополнение значения до единицы с помощью побитового НЕ, приводит его к 'int' (которое теперь не может переполняться), отрицает значение и вычитает единицу, что также может здесь не перелить.
Ветвь (3) обеспечивает яд, который мы должны принять в отношении целей дополнения или знака/величины, потому что диапазон представления целого числа со знаком меньше, чем диапазон представления дополнения до двух.
Скорее всего, это сведется к простому перемещению по цели с дополнением до двух; по крайней мере, я наблюдал такое с GCC и CLANG. Также ветвь (3) недостижима для такой цели - если кто-то хочет ограничить выполнение двумя дополнительными целями, код может быть сжат до
#include <limits.h>
unsigned int u;
int i;
if (u <= (unsigned int)INT_MAX)
i = (int)u; /*(1)*/
else
i = -(int)~u - 1; /*(2)*/
Рецепт работает с любой парой типов со знаком/без знака, и код лучше всего поместить в макрос или встроенную функцию, чтобы компилятор/оптимизатор мог разобраться с ним. (В этом случае полезно переписать рецепт с тернарным оператором. Но он менее читаем и, следовательно, не является хорошим способом объяснить стратегию.)
И да, некоторые приведения к «unsigned int» избыточны, но
они могут помочь случайному читателю
некоторые компиляторы выдают предупреждения при сравнении со знаком/без знака, потому что неявное приведение приводит к некоторому неинтуитивному поведению из-за дизайна языка
(unsigned int)INT_MIN правильно определен?
- person Dan Bechard; 17.03.2021
Если у вас есть переменная unsigned int x;, вы можете преобразовать ее в int с помощью (int)x.
Это так просто:
unsigned int foo;
int bar = 10;
foo = (unsigned int)bar;
Или наоборот...
Если в одном и том же выражении используются unsigned int и (signed) int, подписанный int неявно преобразуется в unsigned. Это довольно опасная особенность языка C, о которой вам нужно знать. Это может быть или не быть причиной вашей ошибки. Если вам нужен более подробный ответ, вам придется опубликовать код.
Некоторые пояснения из C++Primer 5th стр. 35
Если мы присвоим значение вне диапазона объекту беззнакового типа, результатом будет остаток значения по модулю количества значений, которые может содержать целевой тип.
Например, 8-битный символ без знака может содержать значения от 0 до 255 включительно. Если мы присваиваем значение вне диапазона, компилятор присваивает остаток от этого значения по модулю 256.
unsigned char c = -1; // assuming 8-bit chars, c has value 255
Если мы присвоим значение вне допустимого диапазона объекту подписанного типа, результат будет неопределенным. Может показаться, что программа работает, может произойти сбой или она может выдавать неверные значения.
Страница 160: Если какой-либо операнд является беззнаковым типом, тип, в который преобразуются операнды, зависит от относительных размеров целочисленных типов на машине.
... Когда подписанность отличается, а тип беззнакового операнда такой же или больше, чем у подписанного операнда, подписанный операнд преобразуется в беззнаковый.
Оставшийся случай — это когда операнд со знаком имеет больший тип, чем операнд без знака. В этом случае результат зависит от машины. Если все значения беззнакового типа помещаются в большой тип, то беззнаковый операнд преобразуется в знаковый тип. Если значения не подходят, то знаковый операнд преобразуется в беззнаковый тип.
Например, если операнды long и unsigned int, а int и long имеют одинаковый размер, длина будет преобразована в unsigned int. Если тип long имеет больше битов, то unsigned int будет преобразован в long.
Я нашел чтение этой книги очень полезным.