Что означает то, чтобы был подписан символ?

19
задан Prince 4 February 2014 в 06:09
поделиться

8 ответов

Это не будет иметь значения для строк. Но в C можно использовать символ, чтобы сделать математику, когда это будет иметь значение.

На самом деле, при работе в ограниченных средах памяти, как встроенные приложения на 8 битов символ будет часто использоваться, чтобы сделать математику, и затем это имеет большое значение. Это вызвано тем, что нет никакого byte тип по умолчанию в C.

23
ответ дан 30 November 2019 в 02:13
поделиться

С точки зрения значений они представляют:

неподписанный символ:

  • промежутки диапазон значений 0..255 (00000000..11111111)
  • значения переполняются вокруг низкого края как:

    0 - 1 = 255 (00000000 - 00000001 = 11111111)

  • значения переполняются вокруг высокого края как:

    255 + 1 = 0 (11111111 + 00000001 = 00000000)

  • поразрядный оператор (>>) сдвига вправо делает логический сдвиг:

    10000000 >> 1 = 01000000 (128 / 2 = 64)

символ со знаком:

  • промежутки диапазон значений -128..127 (10000000..01111111)
  • значения переполняются вокруг низкого края как:

    -128 - 1 = 127 (10000000 - 00000001 = 01111111)

  • значения переполняются вокруг высокого края как:

    127 + 1 = -128 (01111111 + 00000001 = 10000000)

  • поразрядный оператор (>>) сдвига вправо делает арифметический сдвиг:

    10000000 >> 1 = 11000000 (-128 / 2 = -64)

я включал двоичные представления, чтобы показать, что поведение обертывания значения является чистой, последовательной двоичной арифметикой и не имеет никакого отношения к символу, являющемуся со знаком/неподписанным (ожидайте для сдвигов вправо).

Обновление

Некоторое определенное для реализации поведение упомянуло в комментариях:

21
ответ дан 30 November 2019 в 02:13
поделиться
#include <stdio.h>

int main(int argc, char** argv)
{
    char a = 'A';
    char b = 0xFF;
    signed char sa = 'A';
    signed char sb = 0xFF;
    unsigned char ua = 'A';
    unsigned char ub = 0xFF;
    printf("a > b: %s\n", a > b ? "true" : "false");
    printf("sa > sb: %s\n", sa > sb ? "true" : "false");
    printf("ua > ub: %s\n", ua > ub ? "true" : "false");
    return 0;
}


[root]# ./a.out
a > b: true
sa > sb: true
ua > ub: false

Это важно при сортировке строк.

10
ответ дан 30 November 2019 в 02:13
поделиться

"Что означает то, чтобы символ был подписан?"

Традиционно, набор символов ASCII состоит из 7-разрядных кодировок символов. (В противоположность EBCIDIC на 8 битов.)

, Когда язык C был разработан и реализовал, это было значительной проблемой. (По различным причинам как передача данных по устройствам последовательного модема.) Дополнительный бит имеет использование как четность.

А "подписанный символ", оказывается, идеально подходит для этого представления.

Двоичные данные, OTOH, просто принимают значение каждого 8-разрядного "блока" данных, таким образом никакой знак не необходим.

2
ответ дан 30 November 2019 в 02:13
поделиться

Арифметика на байтах важна для компьютерной графики (где 8-разрядные значения часто используются для хранения цветов). Кроме этого, я могу думать о двух основных случаях, где символ подписывает вопросы:

  • преобразование в больший интервал
  • функции сравнения

противная вещь, они не укусят Вас, если все Ваши строковые данные будут 7-разрядными. Однако это обещает быть бесконечным источником неясных ошибок, при попытке сделать свою программу C/C++ 8-разрядной чистый.

1
ответ дан 30 November 2019 в 02:13
поделиться

Единственная ситуация я могу вообразить этот являющийся проблемой, состоит в том, если Вы принимаете решение сделать математику на символах. Совершенно законно написать следующий код.

char a = (char)42;
char b = (char)120;
char c = a + b;

В зависимости от со знаком из символа, c мог быть одним из двух значений. Если символ будет не подписан затем c, то будет (символ) 162. Если они будут подписаны затем, то это будет водосливный случай, поскольку макс. значение для символа со знаком равняется 128. Я предполагаю, что большинство реализаций просто возвратилось бы (символ)-32.

0
ответ дан 30 November 2019 в 02:13
поделиться

Существует несколько различий. Самое главное, если Вы переполняете допустимого диапазона символа путем присвоения ему слишком большого или маленького целого числа, и символ подписывается, получающееся значение является определенной реализацией, или даже некоторый сигнал (в C) мог быть повышен, что касается всех типов со знаком. Контраст, что к случаю, когда Вы присваиваете что-то слишком большое или маленькое к неподписанному символу: значение повторяется, Вы получите точно определенную семантику. Например, присваивая-1 неподписанному символу, Вы получите UCHAR_MAX. Таким образом каждый раз, когда у Вас есть байт как в числе от 0 до 2^CHAR_BIT, необходимо действительно использовать неподписанный символ для хранения его.

знак также имеет значение при передаче функциям vararg:

char c = getSomeCharacter(); // returns 0..255
printf("%d\n", c);

Предполагают, что значение, присвоенное c, было бы слишком большим, чтобы символ представил, и машина использует дополнение two. Многие реализация ведет себя для случая, что Вы присваиваете слишком большое значение символу, в котором не изменится комбинация двоичных разрядов. Если интервал сможет представить все значения символа (который это для большинства реализаций), то символ продвигается на интервал прежде, чем передать printf. Так, величина того, что передается, была бы отрицательна. Продвижение интервала сохранило бы тот знак. Таким образом, Вы получите отрицательный результат. Однако, если символ не подписан, то значение не подписано, и продвигающий интервал приведет к положительному интервалу. Можно использовать неподписанный символ, затем Вы получите точно определенное поведение и для присвоения на переменную, и для передающий printf, который затем распечатает что-то положительное.

Примечание, что символ, неподписанный и символ со знаком все по крайней мере 8 битов шириной. Нет никакого требования, чтобы символ был точно 8 битов шириной. Однако для большинства систем это правда, но для некоторых, Вы найдете, что они используют символы на 32 бита. Байт в C и C++ определяется, чтобы иметь размер символа, таким образом, байт в C также - не всегда точно 8 битов.

Другое различие, что в C, неподписанный символ не должен иметь никаких дополнительных битов. Таким образом, если Вы находите, что CHAR_BIT равняется 8, затем значения неподписанного символа должны колебаться от 0.. 2^CHAR_BIT-1. То же верно для символа, если это не подписано. Для символа со знаком Вы ничего не можете принять о диапазоне значений, даже если Вы знаете, как Ваш компилятор реализует материал знака (дополнение two или другие опции), могут быть неиспользованные дополнительные биты в нем. В C++ нет никаких дополнительных битов для всех трех типов символов.

3
ответ дан 30 November 2019 в 02:13
поделиться

Одна вещь о символах со знаком состоит в том, что можно протестировать c> = '' (пространство) и быть уверены, что это - нормальный печатаемый символ ASCII. Конечно, это не портативно, таким образом, не очень полезный.

0
ответ дан 30 November 2019 в 02:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: