Диапазон символов положительный, тогда, если я сохраню в нем целое число, он все равно должен напечатать значение между (0-255). Почему Выход равен -24 - PullRequest
1 голос
/ 27 мая 2020

'' '

void main()
{
   int i=1000;
   char c='A';
   c=i;
   printf("%d",c);
}

' ''

Вывод равен -24

почему этот вывод, когда диапазон символа равен (0 -255)

Ответы [ 3 ]

2 голосов
/ 27 мая 2020

При объяснении такого поведения необходимо учитывать следующие моменты:

Во-первых, в таком задании, как c=i в

int i=1000;
char c='A';
c=i;

, мы должны учитывать, что i является перед назначением преобразован в тип c. Интегральное преобразование определяется здесь в онлайн-проекте стандарта C99:

6.3.1.3 Целые числа со знаком и без знака

1 Когда значение с целочисленным типом преобразуется в другой целочисленный тип, отличный от _Bool, если значение может быть представлено новым типом, оно не изменяется.

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

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

Таким образом, необходимо знать, является ли char индивидуальным целочисленным типом или нет. Это может отличаться от компилятора к компилятору, но кажется, что ваш компилятор считает тип char как signed char по умолчанию.

В случае signed char, «результат определяется реализацией», и нам нужно будет взглянуть на спецификацию компилятора.

Общая реализация состоит в том, что целое значение 1000, которое в двоичном формате равно 00000011 11101000, усекается до 8 бит и сохраняется в значении char.

Что означает 11101000 для signed char определяется в представлении типов :

6-2-6-2 Целочисленные типы

2 Для целого числа со знаком типов, биты представления объекта должны быть разделены на три группы: биты значения, биты заполнения и бит знака. Никаких дополнительных битов быть не должно; знаковый char не должен иметь битов заполнения. Должен быть ровно один знаковый бит. Каждый бит, который является битом значения, должен иметь то же значение, что и тот же бит в объектном представлении соответствующего беззнакового типа (если есть M битов значений в типе со знаком и N в типе без знака, тогда M <= N). Если знаковый бит равен нулю, он не влияет на результирующее значение. Если знаковый бит равен единице, значение должно быть изменено одним из следующих способов: </p>

  • соответствующее значение со знаковым битом 0 инвертируется (знак и величина);

  • знаковый бит имеет значение - (2M) (дополнение до двух);

  • знаковый бит имеет значение - (2M - 1) (дополнение до единиц).

Что из этого применимо, определяется реализацией, как ...

Опять же, результат определяется в реализацией компилятора; но обычная интерпретация - это дополнение до двух, интерпретирующее наиболее значимый бит как знаковый бит:

В вашем случае 8 битов 11101000 - это один знаковый бит (установленный) и 7 битов остатка; остаток равен 1101000, что составляет 104; тогда фактическое значение в дополнении до двух будет - (127-104 + 1), что равно -24.

Обратите внимание, что неясно, будет ли результат -24; другие компиляторы могут дать другие результаты.

Есть даже еще один шаг, который необходимо рассмотреть, поскольку вы печатаете значение символа со знаком с использованием спецификатора формата "% d": отрицательное значение signed char повышается до типа int; но тогда это даст "то же самое" отрицательное значение. Я опускаю объяснение «продвижения» и почему аргументы в printf вообще продвигаются.

1 голос
/ 27 мая 2020

Как сказал @JohnBollinger, типичный диапазон типа char, который обычно подписан, составляет от -128 до 127. Когда вы назначаете 1000 (1111101000 в двоичном формате) char, только 8 наименее значимых биты (при условии, что ваши char - 8 бит) сохраняются, приводя к 11101000 в двоичном формате. Это переводится в -24, когда оно печатается как целое число со знаком.

1 голос
/ 27 мая 2020

Ваш компилятор по умолчанию рассматривает тип char как целочисленный тип со знаком аналогично типу signed char.

Диапазон значений для типа signed char:

— minimum value for an object of type signed char
  SCHAR_MIN -127 // −(27 − 1)
— maximum value for an object of type signed char
  SCHAR_MAX +127 // 27 − 1

Из стандарта C (5.2.4.2.1 Размеры целых типов <limits.h>)

2 Если значение объекта типа char обрабатывается как целое число со знаком, когда используется в выражении, значение CHAR_MIN должно быть таким же, как у SCHAR_MIN, а значение CHAR_MAX должно быть таким же, как у SCHAR_MAX. В противном случае значение CHAR_MIN должно быть 0, а значение CHAR_MAX должно быть то же, что и UCHAR_MAX. 20) Значение UCHAR_MAX должно быть равно 2CHAR_BIT - 1.

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

#include <stdio.h>

int main(void) 
{
    int i = 1000;
    unsigned char c;

    printf( "i = %#x\n", i );

    c = i;

    printf( "c = %d\n", c );

    return 0;
}

Вывод программы:

i = 0x3e8
c = 232

Как вы можете видеть, объект типа signed char не может содержать такое большое значение, как 232. Если вы вычтете 232 из 256, вы получите 24. Таким образом, это значение и значение 232, используемое как внутреннее представление знака со знаком, получат 0. Таким образом, это внутреннее представление 232, интерпретируемое как значение со знаком, должно быть равно -24, то есть 24 + -24 = 0.

...