продвижение типа в C - PullRequest
       24

продвижение типа в C

6 голосов
/ 31 октября 2011

Я смущен следующим кодом:

#include <stdio.h>
#include <stdint.h>

int main(int argc, char ** argv)
{
    uint16_t a = 413;
    uint16_t b = 64948;

    fprintf(stdout, "%u\n", (a - b));
    fprintf(stdout, "%u\n", ((uint16_t) (a - b)));

    return 0;
}

Возвращает:

$ gcc -Wall test.c -o test
$ ./test
4294902761
1001
$ 

Кажется, что выражение (a - b) имеет тип uint32_t. Я не понимаю, почему, поскольку оба оператора являются uint16_t.

Кто-нибудь может мне это объяснить?

Ответы [ 3 ]

14 голосов
/ 31 октября 2011

Стандарт C объясняет это довольно четко (§6.5.6 Аддитивные операторы):

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

(§6.3.1.8 Обычные арифметические преобразования):

... целочисленные преобразования выполняются для обоих операндов.

(§6.3.1.1 логическое значение, символы и целые числа):

Если int может представлять все значения исходного типа, значение преобразуется в int;... Они называются целочисленными акциями.Все остальные типы не изменяются целочисленными акциями.

Поскольку int может представлять все значения uint16_t на вашей платформе, a и b преобразуются в int довычитание выполняется.Результат имеет тип int и передается в printf как int.Вы указали форматер %u с аргументом int;Строго говоря, это вызывает неопределенное поведение, но на вашей платформе аргумент int интерпретируется как его представление, дополняющее два, и это печатается.

1 голос
/ 31 октября 2011

Если вы отбросите старшие биты числа (путем явного приведения к 16-битному целому числу без знака), то вы получите меньший результат (в диапазоне от 0 до 2 ^ 16- 1) чем раньше.

0 голосов
/ 31 октября 2011

C переводит аргументы в unsigned int перед выполнением вычитания.Это стандартное поведение.

См., Например, В выражении C, где присутствуют unsigned int и sign int, какой тип будет повышен до какого типа? для получения подробной информации.

...