Форум - Мрежова Сигурност (сайта на курса)

 Нова тема  |  Начало  |  Към тема  |  Търсене  |  Вход   По-нова тема  |  По-стара тема 
 Малко уточнение на нещо от последната лекция
Автор: Евгени Каралъмов (---.megalan.bg)
Дата:   14-04-05 02:02

На последната лекция ставаше въпрос за С и неговите особености и, струва ми се, desync каза нещо, което не е съвсем вярно. Беше зададен въпрос какво става когато се shift-ва надясно (към младшите битове) стойността на signed израз. desync, доколкото си спомням каза, че shift-ването не го интересува дали изразът е от signed или unsigned тип, т.е. винаги присвоява на "опразнените" битове нули. Тази презумпция беше довела до грешни резултати от една моя програма, но не бях много сигурен как точно стояха нещата, за да се обадя на лекцията. Вече проверих и: в случай на shift-ване на signed израз надясно зависи от имплементацията дали въпросните битове ще се запълнят с нули или със стойността на знаковия бит. И на двете места където ми се е налагало да правя такова нещо се случваше второто. И в двата случаи компилаторът беше gcc.

Това, което имам предвид е следното:

ако а = 11...1100(2), което е -4,
то a >> 2 = 11...1111(2), което е -1.

Това представяне на отрицателните числа се нарича "допълнителен код" (?!?!) и не знам дали навсякъде е такова, но знам, че с тази операция това трябва да се има предвид и че трябва да се cast-ва към unsigned когато искате нули и нищо друго освен нули.



Отговори на това съобщение
 
 Re: Малко уточнение на нещо от последната лекция
Автор: Blade al'Slayer (---.ddns.HomeLan.BG)
Дата:   14-04-05 10:41

Допълнителният код се използва за вътрешно представяне на отрицателните числа в паметта и това е така при всики архитектури (до колкото знам - може и да бъркам). Причината е, че позволява да не се реализират някои от операциите с цели числа отделно (изваждане, но май имаше и други... ).
А въпроса с >> на числа със знак май наистина зависи от реализацията на компилатора.

Отговори на това съобщение
 
 Re: Малко уточнение на нещо от последната лекция
Автор: Петър Пенчев (---.nanolink.com)
Дата:   15-04-05 04:01

Аз още тогава изскимтях тихичко, ама Георги (другояче известен като desync) не щя да чуе... С две думи: представянето в допълнителен код е де факто стандартно, почти няма да видите нещо друго, но не можете да *разчитате* на него, защото са позволени и други варианти. Поведението на << върху отрицателни числа не е определено, а поведението на >> върху отрицателни числа също не е определено, но *трябва* да бъде документирано за всеки компилатор/runtime/платформа и т.н.

По-дългият отговор:

Представянето с допълнителен код е на практика стандарт при кажи-речи всички използвани в момента архитектурI, но не е задължително: то е един от трите начина, описани в секция 6.2.6.2 Integer types на нормативния документ N843, който определя стандарта C99. Можете да го намерите на
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n843.htm
Там е описана и идеята за padding bits, с която най-вероятно няма да се срещнете в реалния живот и реалното програмиране, но тук-там се намира още по някоя архитектурка, която използва parity bit точно след бита за знак.

Предупреждавам, че внимателно зачитане в този нормативен документ може да предизвика виене на свят, замъгляване на съзнанието, спорадично наблюдение на хвърчащи розови слонове, и главозамаяние, и кракопреплитание, и въвзидаудряние, и носоразбивание, вмилициювкарвание и други подобни нежелани ефекти!

Колкото до същинския въпрос - поведението на операторите за побитово изместване върху отрицателни аргументи - там трябва да прескочим чак до секция 6.5.7 Bitwise shift operators, където точки #4 и #5 гласят:

[#4] The result of E1 << E2 is E1 left-shifted E2 bit
positions; vacated bits are filled with zeros. If E1 has an
unsigned type, the value of the result is E1×2E2, reduced
modulo one more than the maximum value representable in the
result type. If E1 has a signed type and nonnegative value,
and E1×2E2 is representable in the result type, then that is
the resulting value; otherwise, the behavior is undefined.

[#5] The result of E1 >> E2 is E1 right-shifted E2 bit
positions. If E1 has an unsigned type or if E1 has a signed
type and a nonnegative value, the value of the result is the
integral part of the quotient of E1 divided by the quantity,
2 raised to the power E2. If E1 has a signed type and a
negative value, the resulting value is implementation-
defined.

С други думи, поведението на << върху отрицалтени числа не е определено, а поведението на >> върху отрицателни числа зависи от реализацията - компилатор, библиотека, платформа и т.н.

И тук се сблъскваме с един от моментите на гореспоменатото главозамаяние, кракопреплитание и т.н. - каква е разликата между неопределено (undefined) и зависещо от реализацията (implementtion-defined) поведение? Според секция 3. Terms and Definitions, неопределено (undefined) поведение е такова, на което програмистът не може да разчита, защото този стандарт не казва нищо по въпроса - може да е и така, и така, а може и да не е изобщо. Поведение, определено от реализацията (implementation-defined), е неопределено поведение (т.е. недефинирано в стандарта), което обаче *трябва* да бъде документирано за всяка реализация! Интересен момент е, че в дефиницията за определено от реализацията поведение се дава за пример... поведението на оператора >> върху отрицателни цели числа със знак :)

Та така..... и за тези, които четенето на споменатите дотук секции на стандарта още не е довело до носоразбивание и въвзидаудряние, мога да препоръчам само също така кандидат-стандартизираните разширения и допълниния на езика C за embedded реализации, които можете да намерите в документа N1021:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1021.pdf
Там пък, за по-весело, поведението на << и >> е дефинирано да бъде *точно* като поведението на умножение и деление със степен на 2, т.е. най-смисленият вариант, при който << и >> на отрицателен ляв операнд запазват знака с изключение на случаите на препълване, които се обработват специално. Но това се отнася само за реализации върху embedded платформи, и то реализации върху embedded платформи, които спазват този нормативен документ. Във всички други случаи поведението на << върху отрицателен ляв операнд е неопределено, а поведението на >> - определено от реализацията.

и за който е прочел дотук - олеле... хора... абе аз че съм луд да пиша толкова много глупости наведнъж, луд съм, ама вас какво ви прихвана да ги четете?! :P



Отговори на това съобщение
 
 Re: Малко уточнение на нещо от последната лекция
Автор: Петър Пенчев (---.nanolink.com)
Дата:   15-04-05 04:02

Уф... и след като изписах толкова глупости, разбира се, забравих да спомена още нещо: тези документи, както и много други интересни (и някои дори по-разбираеми ;) неща, свързани с езика C, можете да намерите, като следвате една-две връзки, след като тръгнете от http://www.lysator.liu.se/c/

Поздрави,
Петър

Отговори на това съобщение
 Дървовиден изглед   По-нова тема  |  По-стара тема 


 Искате да влезете в системата? Регистрирайте се тук 
 Вход за потребители
 Потребителско име:
 Парола:
 Автоматично влизане:
   
 Забравена парола
Моля въведете Вашият email или потребителско име и Вашата нова парола ще бъде изпратена на email адреса, асоцииран с Вашия профил.

phorum.org