Что будет выводом следующего фрагмента кода и почему? - PullRequest
4 голосов
/ 17 октября 2019
#include <stdio.h>
#include <stdlib.h>
typedef    unsigned     int    U32;
int main() {
    U32 var     = -1;
    printf("var = %u\n", var);
    if(var != -1)
    {
        printf("\n I'm not -1\n");
    }
    else
    {
        printf("I'm -1 and Var :%u\n", var);
    }
 }

Здесь «-1» следует преобразовать в unsigned int и присвоить var. И тогда при условии if оно не должно быть равно -1. Но это входит в утверждение else.

Ответы [ 3 ]

3 голосов
/ 17 октября 2019

Обратите внимание, что все целочисленные константы, такие как 1, имеют тип. Если U32 равно unsigned int, то:

  • В случае U32 var = -1; (присваивание) правый операнд типа int преобразуется в типлевый операнд.

  • В случае if(var != -1) операнд -1 преобразуется из типа int в unsigned int согласно обычным арифметическим преобразованиям , подробности здесь: Неявные правила продвижения типов

В обоих случаях происходит преобразование со знаком в беззнаковое, и такое преобразование четко определено согласно 6.3.1.3. :

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

Это означает, что в обоих вышеупомянутых случаях будет сгенерировано одинаковое значение без знака 0xFFFFFFFF.

2 голосов
/ 17 октября 2019

В этом операторе

if(var != -1)

компилятор должен определить общий тип операндов. Этот процесс называется обычными арифметическими преобразованиями. Из стандарта C (6.5.9 Операторы равенства)

4 Если оба операнда имеют арифметический тип, то выполняются обычные арифметические преобразования ....

Иотносительно обычных арифметических преобразований (Стандарт C, 6.3.1.8 Обычные арифметические преобразования)

В противном случае, если операнд с целочисленным типом без знака имеет ранг, больший или равный рангу типадругой операнд, , тогда операнд с целочисленным типом со знаком преобразуется в тип операнда с целочисленным типом без знака.

Таким образом, в соответствии с кавычкой в ​​выражении оператора ifцелочисленная константа -1, имеющая тип int, преобразуется в тип unsigned int, то есть в тип переменной var, поскольку типы int и unsigned int имеют одинаковый ранг, а переменная var имеет тип unsigned int.

В результате условие выдает false.

0 голосов
/ 17 октября 2019

An int, будь то со знаком или unsigned, представлен серией битов, таких как

B1B2 ... Bn

, где

Bi ∈ {0;1}

теперь самое большое представимое unsigned int выглядит как

1111...1

, однако, как значение со знаком, -1 представляется

1111...1

также

так, 1111 ... 1 == 1111 ... 1 верно. Преобразование в unsigned не изменило никаких значений, оно меняет способ восприятия данного значения. И с точки зрения памяти представление 2 ^ (32-1) и -1 фактически один и тот же чувак, одетый в разные одежды.

...