Основные типы 1.1
PRINT(d,"5") | Формат %d указывает printf, что аргумент нужно напечатать как десятичное число. Аргумент "5" представляет собой ссылку на массив символов, т.е. адрес массива из двух символов '5' и '\0'. |
PRINT(d,'5') | %d требует напечатать десятичное значение символа '5'1. |
PRINT(d,5) | Целое число 5 печатается в десятичном виде. |
PRINT(s,"5") | Формат %s указывает printf, что аргумент является ссылкой на массив символов. Так как "5" - ссылка на массив символов, то печатается содержимое этого массива, т.е. число 5. |
PRINT(c,'5') | Формат %c указывает printf, что аргумент нужно рассматривать как значение некоторого символа (его код) и что этот символ нужно напечатать. Так как '5' как раз и есть значение символа, то напечатан будет символ 5. |
PRINT(c,53) | Десятичное число 53 - это код символа 5 в кодировке ASCII. |
PRINT(d,('5'>5) | Последней будет напечатана 1, так как '5' имеет большее значение (53), чем целое 5. |
1 Значение, которое используется здесь есть значение символа в кодировке ASCII (приложение 3). Кодировка ASCII - одна из возможных кодировок для представления символов там, где необходимо значение символа.
Основные типы 1.2
вначале ax=-8, ux=-8 | |
PRINT(o,sx) | %o указывает printf, что аргумент следует напечатать как восьмеричное число. |
PRINT(o,ux) | Значение -8 представляется как строка из 0 и 1, что верно как для переменных без знака, так и для переменных со знаком. |
PRINT(o,sx>>3) | С этой трудностью мы сталкивались уже и раньше. В некоторых версиях языка С сдвиг целого со знаком вправо приводит к тому, что знаковый разряд копируется в свободные старшие разряды слова, т.е. знак сохраняется. Однако, внимание, - это свойство зависит от транслятора! |
PRINT(o,ux>>3) | Когда происходит сдвиг целого без знака вправо, то освободившиеся старшие разряды всегда заполняются нулями. |
PRINT(d,sx>>3) | Сдвиг на 3 разряда вправо целого со знаком -8 дает ожидаемый результат -1 при условии, что знак сохраняется, и 8191 в противном случае (на 16-разрядной машине с дополнительным кодом). |
PRINT(o,ux>>3) | Для переменной типа unsigned со значением -8 результат всегда равен 8191 (на 16-разрядной машине). |
Основные типы 2.1
i = l = f = d = 100/3 | |
(i=(l=(f=(d=(100/3))))) | Вычисляем выражение справа налево. |
(i=(l=(f=(d=33)))) | Так как оба числа 100 и 3 - целые, то операция деления есть деление целых, поэтому у частного отбрасывается дробная часть. |
(i=(l=(f=(double)33))) и d=33 | Напоминаем, что значение, вырабатываемое операцией присваивания, есть значение правой части, преобразованное к типу, задаваемому левой частью. |
(i=(l=(float)33)) и f=33 (i=(long)33) и l=33 (integer)33 и i=33 33 целое |
Основные типы 2.2
d = f = l = i = 100/3 (d=(f=(l=(i=(100/3))))) (d=(f=(l=(integer)33))) и i=33 (d=(f=(long)33)) и l=33 (d=(float)33) и f=33 (double)33 и f=33 33 двойной точности
Основные типы 2.3
i = l = f = d = 100/3. (i=(l=(f=(d=(100/3.))))) | |
(i=(l=(f=(double)33.333333))) и d=33.333333 | Число 3. двойной точности, поэтому и частное будет двойной точности. |
(i=(l=(float)33.333333)) и f=33.33333x | В этой программе в printf используется формат %.8g, который задает печать числа с точностью до 8 значащих цифр. Но на самом деле на машинах PDP-1 и VAX максимальная точность для чисел с плавающей точкой не более 7 значащих цифр, так что точность до 8 цифр недостижима. Конечно, количество значащих цифр в числе зависит от машины. |
(i=(long)33.33333x))и l=33 | Преобразование чисел с плавающей точкой в длинные целые происходит с помощью отбрасывания дробной части. |
(integer)33 и i=33 33 целое |
Основные типы 2.4
d = f = l = i = (double)100/3 | |
(d=(f=(l=(i=((double)100)/3))))) | Заметьте, что операция приведения имеет более высокий приоритет, чем операция /. |
(d=(f=(l=(i=(100./3))))) (d=(f=(l=(integer)33.333333))) и i=33 (d=(f=(long)33)) и l=33 (d=(float)33) и f=33 (double)33 33 двойной точности |
Основные типы 2.5
i = l = f = d = (double)(100000/3) (i=(l=(f=(d=((double)(100000/3)))))) | |
(i=(l=(f=(d=(double)33333)))) | Операндом для операции приведения служит частное от деления 100000 на 3. |
(i=(l=(f=(double)33333))) и d=33333 (i=(l=(float)33333)) и f=33333 (i=(long)33333) и l=33333 (integer)33333 и i=33333 или переполнение | Число 33333 нельзя представить в виде 16-разрядного целого со знаком. Многие реализации языка спокойно допускают и переполнение, и потерю значимости числа. Если ваши вычисления могут в принципе превзойти границы, присущие данной машине, то будет разумным вставить явные проверки на попадание чисел в отводимый диапазон. |
33333 целое или переполнение |
Основные типы 3.1
вначале d=3.2, i=2 x = (y=d/i)*2 (x=(y=3.2/2)*2) | |
(x=(y=1.6)*2) | 3.2 - число двойной точности, этот тип выше типа int, типа числа 2, поэтому частное тоже будет двойной точности. Так как y - целое, то у значения 1.6 будет отброшена дробная часть |
(x=1*2) и y=1
(x=2) 2 и y=1 |
Основные типы 3.2
вначале d=3.2, i=2 y = (x=d/i)*2 (y=(x=1.6)*2) | |
(y=1.6*2) и x=1.6 | Так как x - типа double, то и результат присваивания будет типа double. |
(y=3.2) | Тип 1.6 - double определяет и тип произведения. |
3 и y=3 | Так как y типа int, то у 3.2 должна быть отброшена дробная часть |
Основные типы 3.3
вначале d=3.2, i=2 y = d * (x=2.5/d) (y=(d*(x=2.5/d)) | |
(y=d*2.5/d) и x=2.5/d | Тип x - double, так что у 2.5/d точность сохраняется. |
(y=2.5) 2 и y=2 | Тип y заставляет отбросить дробную часть у 2.5 |
Основные типы 3.4
вначале d=3.2, i=2 x = d * (y = ((int)2.9+1.1)/d) | |
(x=d*(y=(2+1.1)/d)) | Операция приведения более высокого порядка, чем операция +. |
(x=d*(y=3.1/d)) (x=d*(y=нечто)) | |
(x=d*0) и y=0 | y получит значение 0 независимо от величины "нечто", поскольку "нечто" находится между 0 и 1. |
0 и x=0 |
О смешении типов. К этому моменту было уже много примеров, когда смешивание целых значений и значений с плавающей точкой приводило к неожиданным результатам в выражениях. Лучше всего избегать арифметических действий с операндами разных типов. Если же это необходимо, то применять явные приведения типов.
d = f = l = i = 100000/3 (d=(f=(l=(i=(100000/3)))) | |
(d=(f=(l=(integer)33333))) и i=33333 или переполнение | Как мы уже видели раньше, 33333 - значение, переполняющее 16-разрядное целое со знаком. Если для представления целых использовать больше разрядов, то i так же, как l, f и d, получат значение 33333. Ниже мы ориентируемся на 16-разрядные целые. |
(d=(f=(long)-32203)) и l=-32203 | Результат операции, приведшей к переполнению, - это обычное число, но не то, которое ожидалось. Значение 33333 будет потеряно независимо от дальнейших приведений типов. |
(d=(float)-32203) и f=-32203 (double)-32203 и d=-32203 32203 двойной точности |