Беззнаковое цэлалікавых значэнне ў C паводзіць сябе адмоўным

Я не разумею, чаму выхад без знака міжнар негатыўны для наступнага кода. Гэтак жа, як падпісаная Int.

  uint32_t yyy=1<<31;
  printf("%d\n",yyy);

выхад:

<�Р> -2147483648 </р>

які -2 ^ 31 .

0
Паспрабуйце Е ( "% і \ п", YYY);
дададзена аўтар Suvarna Pattayil, крыніца
Нават да выкліку Printf , гэты код мае нявызначаны паводзіны, калі Int мае 32 біт у вашай рэалізацыі C. Значэнне 1 << 31 перацякае ў Int . Вы павінны выкарыстоўваць 1u << 31 , так што ён зрушвае непадпісаным Int .
дададзена аўтар Eric Postpischil, крыніца

8 адказы

Спецификатор фармату для % D чакае Int , не беззнаковое INT , таму код мае нявызначаны паводзіны. З стандартнай секцыі C99 7.19.6.1 Функцыя fprintf :

<�Р> Калі які-небудзь аргумент не правільны тып для адпаведнага спецыфікацыі пераўтварэнні, паводзіны не вызначана. </Р>

Выкарыстоўвайце % і для непадпісаным Int :

uint32_t yyy=1u<<31;
printf("%u\n",yyy);

выхад:

2147483648
6
дададзена
Для пераноснасці праблемы, можна выкарыстоўваць наступныя для друку uint32_t (які можа быць больш, чым без знака): «Е ("% "PRIu32" \ п ", ууу);"
дададзена аўтар chux, крыніца

Гэта таму, што ваш Printf аргумент, так як% D, няяўна пераўтварэнне лікі ў міжнар.

Выкарыстоўвайце% U замест гэтага.

4
дададзена
Разумею. Дзякуючы ваш адказ ~
дададзена аўтар user2418047, крыніца

Як многія ўжо казалі, выкарыстоўвайце % і ідэнтыфікатар.

Прычынай гэтага з'яўляецца тое, што Printf не мае магчымасці сказаць, што тып любога з дадатковых параметраў (яны прыведзеныя ў выглядзе va_list ), так што вы праграміст павінен даць гэтую інфармацыю, выкарыстоўваючы радок фармату. Калі вы затым даць % d , Printf будзем называць гэта:

int val;
val = va_arg(va_list, int);

і няяўна вашыя непадпісаныя Int ў знакавых.

1
дададзена

Выкарыстоўвайце % і для вываду лікаў без знаку:

printf("%u\n", yyy);
1
дададзена

printf takes a variable number of arguments. When you call it the compiler will dutifully put them all on the stack. Because it's C there's no reflection — printf can't subsequently infer the types of things it has received. At the bit level you can't prima facie tell a signed integer from an unsigned integer or a float, a suitably small structure, part of a larger struct, etc.

Вось чаму вы павінны паставіць радок фармату. Гэта сведчыць Printf якія тыпы чытання з стэка і ў якім парадку. Гэта цалкам залежыць ад той радкі фармату, не маючы магчымасці праверыць яго.

Такім чынам, згодна з адной лініі з адказамі на пытанні ўжо адказваў, калі сказаць яму, каб інтэрпрэтаваць поле як знакавую колькасць, то ён будзе друкавацца ў якасці падпісанага колькасці.

0
дададзена

Вы павінны выкарыстоўваць непадпісаным Int спецификатор фармату:

printf("%u\n",yyy);
        ^^

выкарыстоўваючы няправільны спецификатор фармату для Printf не вызначана паводзіны, якое разглядаецца ў C99 праекце стандарту раздзеле 7.19.6.1 Функцыя fprintf , які таксама вечка Printf ў адносінах да спецификаторам фармату кажа:

<�Р> Калі спецыфікацыя пераўтварэння з'яўляецца несапраўдным, паводзіны   не вызначана. 248) Калі які-небудзь аргумент не з'яўляецца правільным тыпам для   адпаведная спецыфікацыя пераўтварэнні, паводзіны не вызначана. </р>

cppreference старонка Printf мае прыемны табліца з указаннем спецификаторы фармату даступныя.

0
дададзена

Таму што вы друкуеце яго як знакавую. Выкарыстоўвайце % і замест гэтага.

0
дададзена

Integers are stored in Two's Complement format. This means there is no way to tell if the number is signed or unsigned just by looking at the value. You must tell the machine which representation you want it to use and keep track of it yourself.

У вашым прыкладзе вы кажаце машыну, што JJJ гэта без знака (для праверкі тыпу), але затым задаць Е() , каб разглядаць яго як знакавую, выкарыстоўваючы % d ў радку фармату (яна не можа атрымаць у інфармацыі пра тып). Калі вы хочаце надрукаваць без знака выкарыстоўваць Int % і замест гэтага.

0
дададзена