Я читаю книгу Страуструпа «Язык программирования С++, 4-е издание», и у меня есть три вопроса относительно переполнения заданий (особенно для подписанных/беззнаковых символов, как показано в книге). Во-первых, согласно стандартному пункту 5/4:
Если во время вычисления выражения результат не определен математически или не находится в диапазоне представляемых значений для его типа, поведение не определено.
(За исключением случаев, когда целевая переменная не имеет знака - в этом случае результат четко определен). Но относится ли это определение и к назначениям?
Потому что, на мой взгляд, в книге много противоположных утверждений, все в главе 6. Первое соответствует вышеупомянутому абзацу, а следующие комментарии — нет:
Переменные трех типов
char
можно свободно назначать друг другу. Однако присвоение слишком большого значенияsigned char
по-прежнему не определено. Например:void g(char c, signed char sc, unsigned char uc) { c = 255; //implementation-defined if plain chars are signed and have 8 bits c = sc; //OK c = uc; //implementation-defined if plain chars are signed and if uc's value is too large sc = uc; //implementation-defined if uc's value is too large uc = sc; //OK: conversion to unsigned sc = c; //implementation-defined if plain chars are unsigned and if c's value is too large uc = c; //OK: conversion to unsigned }
Первый вопрос: поскольку присвоение слишком большого значения является UB, то почему в комментариях говорится, что это определяется реализацией?
Далее у нас есть следующий пример:
Чтобы быть конкретным, предположим, что
char
составляет 8 бит:signed char sc = -160; unsigned char uc = sc; //uc == 116 (because 256-160==116) cout << uc; //print 't'
Второй вопрос: помимо того факта, что первое задание якобы UB, какую именно формулу использовал автор, чтобы получить 116? В моем тесте uc
получил значение 96.
И последняя цитата:
Целое число может быть преобразовано в другой целочисленный тип. Если назначение
signed
, значение не изменяется, если оно может быть представлено в типе назначения; в противном случае значение определяется реализацией:
signed char sc = 1023; //implementation-defined
Правдоподобные результаты 127 и -1.
Третий вопрос: опять же, помимо того факта, что это противоречит тому, что было сказано ранее о UB, почему возможные результаты 127 и -1? Я предполагаю, что это как-то связано с дополнением до единиц и до двух, но какие точные формулы используются?