Как компьютер делает разницу между типами? - PullRequest
0 голосов
/ 06 января 2020

Мне интересно, как мой компьютер может сделать разницу между точно таким же набором 0 и 1. Я действительно не знаю, в чем должен быть вопрос, но я хочу знать, например, когда у меня в C:

int main(){
   __uint8_t a = 97;
   printf(" Here is a char : %c\n Here is a number : %d\n", a, a);
   return 0;
}

Как он узнает, когда ему лучше напечатать «a» или 97. Я знаю, что это связано с% c и% d, но что происходит на самом деле?

Спасибо всем!

Ответы [ 4 ]

1 голос
/ 06 января 2020

Мне интересно, как мой компьютер может различать один и тот же набор 0 и 1.

В общем случае разные инструкции по-разному интерпретируют одну и ту же последовательность битов. Например, инструкция x86 ADDL интерпретирует свои операнды как 32-разрядные целочисленные значения, тогда как ADDSD интерпретирует свои операнды как скалярные значения с плавающей запятой двойной точности.

Тип информации, которую вы указываете в своем исходном коде (int, double, char, et c.), Определяет, какие машинные инструкции генерирует компилятор. Например, если у вас есть код

double a = 1.0, b = 2.0;
double c = a + b;

, компилятор переведет его на

movsd   -8(%rbp), %xmm0     // move value of a (1.0) to xmm0 register
addsd   -16(%rbp), %xmm0    // add value of b (2.0) to value in xmm0, store result in xmm0
movsd   %xmm0, -24(%rbp)    // copy value in xmm0 (3.0) to c

Если вы измените double на int:

int a = 1, b = 2;
int c = a + b;

тогда компилятор генерирует код:

movl    -4(%rbp), %edx   // move value of a (1) to edx register
movl    -8(%rbp), %eax   // move value of b (2) to eax register
addl    %edx, %eax       // add value in edx to eax, store result in eax
movl    %eax, -12(%rbp)  // copy value in eax to c

Для вашего конкретного вопроса c, хотя:

Я знаю, что это из-за% c и% d, но что происходит на самом деле?

Целое число значение 97 сохраняется как последовательность битов - при условии 8-битного типа, эта последовательность битов равна 01100001 или 0x61.

* * * * * * * * * * * * *1038* * * * * * * * * * * *1038* * * * * * * * * * * *1038* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 'a' В основном %c говорит «представить это значение как соответствующий символ в базовом c наборе символов» - IOW, символ *1040*. Где-то есть отображение между целочисленными значениями и соответствующими символами.

Спецификатор преобразования %d в основном гласит «создать десятичное строковое представление этого значения» - то есть испустить последовательность символов {'9', '7'}.

Точно, как значения отображаются в символы и отображаются, является функцией реализации и драйвера терминала, и это будет варьироваться от системы к системе.

1 голос
/ 06 января 2020

Когда вы запрашиваете печать с% c, компьютер смотрит в сторону таблицы ASCII. Компьютер может понимать только числа (двоичные), и эта таблица является справочной информацией о том, как изменить число на символ (см. Ниже), поскольку вы можете видеть a = 97 в десятичном виде, равный 0110 0001 в двоичном. В коде вы можете попросить отобразить значение в разных форматах (% d для десятичного числа,% f для числа с плавающей запятой,% c для символа ...), но это всегда двоичное слово в компьютере

ASCII table

Спросите меня, хотите ли вы получить больше информации о слабых аппаратных слоях

1 голос
/ 06 января 2020

То, что вы упомянули %c или %d, называется спецификатором преобразования, каждый из которых имеет значение Speci c. Они заранее решили, как соответствующий аргумент будет обрабатываться, форматироваться и печататься.

Цитирование из C11, глава §7.21.6.1, некоторые примеры:

Спецификаторы преобразования и их значения:

d,i Аргумент int преобразуется в десятичное число со знаком в стиле [-] d ddd.

и

c Если модификатор длины l отсутствует, аргумент int преобразуется в unsigned char, и результирующий символ

Таким образом, каждый спецификатор преобразования имеет соответствующие правила о том, как они интерпретируют и выводят предоставленные аргументы или игнорируют их (например: %%).

0 голосов
/ 06 января 2020

Компьютер не знает. Вы говорите ему по %c и %d в строке формата printf.

И это соединение используется этой конкретной архитектурой для использования кодов ASCII, где 97 - это a

Вы можете написать свою собственную функцию вывода, используя любую кодировку, какую пожелаете.

...