Ответ 1
Отказ от ответственности: я ссылаюсь на пункт 11 пункта 5 последнего проекта N4606 С++ 17. Текст, который я цитирую и цитирую, содержится в абзаце 9 из N3337, который практически идентичен стандарту С++ 11, и в этой форме также в FD С++ 14, поэтому этот ответ также относится к этим стандартам.
Предполагая, что ssize_t
и size_t
имеют одинаковый ранг, в вашем первом случае [expr]/(11.5.5) применяется:
В противном случае оба операнда должны быть преобразованы в целочисленный тип без знака, соответствующий тип операнда со знаком целочисленного типа.
1 будет преобразован в неподписанную версию ssize_t
, которая должна быть size_t
— следовательно, неподписанное нижнее течение и значение 2 sizeof(size_t)*8
-4.
Для вашего второго случая, считая, что ранг unsigned
меньше, чем ранг ssize_t
, а последний может содержать все прежние значения; см. [expr]/(11.5.4):
В противном случае, если тип операнда со знаком целочисленного типа может представлять все значения тип операнда с целым типом без знака, операнд с целым типом без знака должен преобразуется в тип операнда со знаком целочисленного типа.
т.е. 5
будет преобразован в ssize_t
, и мы получим отрицательный результат. Если ssize_t
не имеет большего ранга, чем unsigned
, мы получим 2 sizeof(unsigned)*8
-4; если вместо ssize_t
не удалось сохранить все значения unsigned
, мы снова получим отрицательный результат, потому что мы переходим к вышесказанному (11.5.5).