Автор: Петър Пенчев (---.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
|
|