Преобразуване на типа
АЛТЕ ДОКУМЕНТ
Ако изразите съдържат p&# 12412c29m 1072; операнди от различни типове, те се преобразуват в общия тип според малък набор от правила. По принцип автоматично се извършват само преобразувания, които имат смисъл, като например преобразуване на цяло число в число с плаваща замък в изрази като f+i. Изрази, които нямат смисъл, като например използването на променлива с плаваща задна буква като индекс, не са разрешени.
Първо, типовете char и int могат да се смесват свободно в аритметични изрази: всяка променлива от тип char автоматично се преобразува в int. Това осигурява значителна гъвкавост при извършването на определени трансформации на знаци.
Пример 3-2. Пример е функцията atoi, която преобразува низ от цифри в неговия цифров еквивалент.
atoi(char s[]) // Преобразуване на s в цяло число
Както беше обсъдено в Глава 2, изразът s[i]-'0' има числовата стойност на знака в s[i], тъй като стойността на символите '0', '1' и т.н. образуват възходяща последователност от последователни положителни числа.
Пример 3-3. Друг пример за преобразуване на char в int е функцията lower, която преобразува дадена главна буква в малка. Ако символният аргумент не е главна буква, тогава low го връща непроменен. Следващата програма е валидна само за ASCII символния набор.
lower( int c) // Преобразуване на главни букви в малки букви
Тази функция работи правилно с ASCII код, тъй като цифровите стойности, съответстващи на главни и малки букви в този код, се различават с постоянна стойност и всяка азбука е непрекъсната - няма нищо друго освен букви между a и z. Това е последната бележка за набор от знациEBCDIC на системите IBM 370 е несправедлив, поради което тази програма не работи правилно на такива системи - конвертира не само букви.
Когато преобразувате символни променливи в цели числа, има един тънък момент. Въпросът е, че самият език не уточнява дали char променливите трябва да съответстват на числови стойности със знак или без знак. Може ли преобразуването на char в int да доведе до отрицателно цяло число? За съжаление, отговорът на този въпрос варира от машина до машина, отразявайки разликите в тяхната архитектура. На някои машини (например PDP-11) променлива char, чийто най-ляв бит съдържа 1, се преобразува в отрицателно цяло число ("разширение на знак"). При други машини това преобразуване е придружено от добавяне на нули от лявата страна, което винаги води до положително число.
Дефиницията на езика "C" гарантира, че всеки знак в стандартния набор от символи на машината никога няма да произведе отрицателно число, така че тези знаци да могат да се използват свободно в изрази като положителни стойности. Но произволни комбинации от двоични знаци, съхранени като символни променливи на някои машини, могат да произведат отрицателни стойности, но положителни стойности на други.
Най-типичният пример за такава ситуация е, когато стойността 1 се използва като eof. Помислете за програмата:
На машина, която не извършва разширяване на знак, c винаги е положителен, защото е деклариран като char и тъй като eof е отрицателен, условието никога не е изпълнено. За да избегнем тази ситуация, винаги разумно сме използвали int вместо char за всяка променлива, която получава стойност от getchar.
Основната причина за използването на int вместо char няма нищо общо свсеки въпрос относно възможно разширяване на знака. просто функцията getchar трябва да предава всички възможни знаци (така че да може да се използва за произволен вход) и в допълнение различна стойност на eof. Следователно стойността на eof не може да бъде представена като char, а трябва да се съхранява като int.
Друга полезна форма на автоматично преобразуване на типове е, че релационни изрази като i>j и булеви изрази, свързани с && и по дефиниция имат стойност 1, ако са верни и 0, ако са неверни. Така че заданието е:
isdigit = c >= '0' && ° С
задава isdigit на 1, ако c е цифра и 0 в противен случай. (В тестовата част на изразите if, while, for и т.н. „true“ просто означава „not null“).
Неявните аритметични преобразувания работят предимно според очакванията. Най-общо казано, ако операция от тип + или *, която свързва два операнда (двоична операция), има операнди от различни типове, тогава "по-нисшият" тип се преобразува в "по-висок" тип, преди да се изпълни операцията, и се получава резултатът от "по-високия" тип. По-точно, следната последователност от правила за преобразуване се прилага към всяка аритметична операция.
1. Типовете char и short се преобразуват в int, а float в double.
2. След това, ако един от операндите е от тип double, тогава другият се преобразува в double и резултатът е от тип double.
3. В противен случай, ако един от операндите е от тип long, тогава другият се преобразува в long и резултатът е от тип long.
4. В противен случай, ако един от операндите е от тип unsigned, тогава другият се преобразува в unsigned и резултатът е от тип unsigned.
5. В противен случай операндите трябва да са от тип int и резултатът е от типвътр.
Подчертаваме, че всички плаващи променливи в изразите се преобразуват в double; в C цялата аритметика с плаваща запетая се извършва с двойна точност.
Преобразувания се случват и при задания; стойността на дясната страна се преобразува в типа на лявата страна, което е типът на резултата. Знаковите променливи се преобразуват в цели числа със или без разширение на знаци, както е описано по-горе. Обратното преобразуване на int в char се държи добре - допълнителните битове от висок ред просто се изхвърлят. Така, ако:
тогава стойността на символа c не се променя. Това е вярно, независимо дали е включено подписано разширение или не.
Ако x е от тип float и i е от тип int, тогава как
водят до трансформации; докато float се преобразува в int чрез изхвърляне на дробната част. Типът double се преобразува в float чрез закръгляване. Дългите цели числа се преобразуват в по-къси цели числа и в char променливи чрез изхвърляне на допълнителни битове от висок ред.
Тъй като аргументът на функцията е израз, когато аргументите се предават на функциите, също се извършва преобразуване на типа: по-специално char и short стават int, а float става double. Ето защо декларирахме аргументите на функцията като int и double, дори когато имахме достъп до тях с променливи char и float.
И накрая, изрично преобразуване на тип може да бъде извършено ("принудено") на всеки израз с помощта на конструкция, наречена каст. В тази конструкция, която изглежда така:
(тип име) израз
изразът се преобразува в посочения тип съгласно правилата за преобразуване, посочени по-горе. Всъщност точното значение на операцията за превод може да се опише по следния начин: изразът е, така да се каже, присвоен на някаква променлива от посочения тип, която след това се използвавместо цялата структура. Например процедурата на библиотеката sqrt очаква двоен аргумент и ще произведе безсмислен отговор, ако бъде небрежно извикана с нещо друго. Така, ако n е цяло число, тогава изразът:
sqrt ((двойно) n)
преди да предаде аргумента на функцията, sqrt преобразува n в тип double.
Упражнение 3-2. Напишете програма за функцията htoi(s), която преобразува низ от шестнадесетични цифри в неговата еквивалентна целочислена стойност. В този случай валидните числа са числата от 1 до 9 и буквите от a до f.