문제

부호 있는 정수와 부호 없는 정수가 동일한 레지스터 등을 사용하고 비트 패턴을 다르게 해석하며 C 문자는 기본적으로 8비트 정수일 뿐이라는 점을 고려하면 C에서 부호 있는 문자와 부호 없는 문자의 차이점은 무엇입니까?나는 char의 부호 있음이 구현에 따라 정의된다는 것을 이해하고 있으며 적어도 char가 수학을 수행하는 대신 문자열을 유지하는 데 사용될 때 이것이 어떻게 차이를 만들 수 있는지 이해할 수 없습니다.

도움이 되었습니까?

해결책

문자열에는 차이가 없습니다. 그러나 C에서는 차이를 만들 때 숯을 사용하여 수학을 할 수 있습니다.

실제로, 내장 된 8 비트 응용 프로그램과 같이 제한된 메모리 환경에서 작업 할 때 Char는 종종 수학을 수행하는 데 사용되는 다음 큰 차이를 만듭니다. 이것은 없기 때문입니다 byte C에서 기본적으로 입력

다른 팁

그들이 나타내는 값의 관점에서 :

부호없는 숯 :

  • 값 범위에 걸쳐 있습니다 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)

나는 이진 표현을 포함하여 가치 랩핑 동작이 순수하고 일관된 이진 산술이며, 서명/서명 된 숯과 관련이 없음을 보여줍니다 (올바른 교대에 대한 예상).

업데이트

의견에 언급 된 일부 구현 별 행동 :

#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

문자열을 정렬 할 때 중요합니다.

몇 가지 차이점이 있습니다.가장 중요한 것은 char에 너무 크거나 작은 정수를 할당하여 char의 유효한 범위를 오버플로하고 char이 부호 있는 경우 결과 값이 구현에 정의되거나 심지어 모든 부호 있는 유형과 마찬가지로 일부 신호(C에서)가 상승할 수 있다는 것입니다. .서명되지 않은 문자에 너무 크거나 작은 것을 할당하는 경우와 대조해 보세요.값이 순환되면 정확하게 정의된 의미를 얻게 됩니다.예를 들어, 서명되지 않은 문자에 -1을 할당하면 UCHAR_MAX를 얻게 됩니다.따라서 0에서 2^CHAR_BIT까지의 숫자와 같은 바이트가 있을 때마다 이를 저장하기 위해 실제로 unsigned char을 사용해야 합니다.

이 부호는 vararg 함수에 전달할 때에도 차이를 만듭니다.

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

c에 할당된 값이 char로 표현하기에는 너무 크고 기계가 2의 보수를 사용한다고 가정합니다.비트 패턴이 변경되지 않는다는 점에서 char에 너무 큰 값을 할당하는 경우 많은 구현이 작동합니다.int가 char의 모든 값(대부분의 구현에 해당)을 나타낼 수 있는 경우 char은 printf로 전달되기 전에 int로 승격됩니다.따라서 전달된 값은 음수가 됩니다.int로 승격하면 해당 기호가 유지됩니다.그래서 당신은 부정적인 결과를 얻게 될 것입니다.그러나 char가 부호가 없으면 값은 부호가 없으며 int로 승격하면 양의 int가 생성됩니다.unsigned char을 사용하면 변수에 할당하고 printf에 전달하여 긍정적인 내용을 인쇄하는 두 가지 동작 모두에 대해 정확하게 정의된 동작을 얻을 수 있습니다.

char, unsigned 및 signed char은 모두 다음과 같습니다. 적어도 8비트 폭.char이 반드시 필요하지는 않습니다. 정확히 8비트 폭.그러나 대부분의 시스템에서는 이것이 사실이지만 일부 시스템에서는 32비트 문자를 사용한다는 것을 알 수 있습니다.C 및 C++의 바이트는 char 크기로 정의되므로 C의 바이트도 항상 정확히 8비트는 아닙니다.

또 다른 차이점은 C에서 unsigned char에는 패딩 비트가 없어야 한다는 것입니다.즉, CHAR_BIT가 8인 경우 부호 없는 char 값의 범위는 0 ..2^CHAR_BIT-1.서명되지 않은 char의 경우에도 마찬가지입니다.부호 있는 문자의 경우 컴파일러가 부호 항목(2의 보수 또는 기타 옵션)을 구현하는 방법을 알고 있더라도 값 범위에 대해 아무 것도 가정할 수 없으며 사용되지 않은 패딩 비트가 있을 수 있습니다.C++에는 세 가지 문자 유형 모두에 패딩 비트가 없습니다.

"숯이 서명한다는 것은 무엇을 의미합니까?"

전통적으로 ASCII 문자 세트는 7 비트 문자 인코딩으로 구성됩니다. (8 비트 Ebcidic과는 반대로)

C 언어가 설계되고 구현되었을 때 이것은 중요한 문제였습니다. (직렬 모뎀 장치를 통한 데이터 전송과 같은 여러 가지 이유로.) 추가 비트는 패리티와 같은 용도가 있습니다.

"서명 된 캐릭터"는이 표현에 완벽합니다.

이진 데이터 인 OTOH는 단순히 각 8 비트 "청크"의 값을 취하고 있으므로 부호가 필요하지 않습니다.

바이트의 산술은 컴퓨터 그래픽에서 중요합니다 (8 비트 값은 종종 색상을 저장하는 데 사용됩니다). 그 외에도, 나는 Char Sign이 중요한 두 가지 주요 사례를 생각할 수 있습니다.

  • 더 큰 int로 변환
  • 비교 기능

불쾌한 점은 모든 문자열 데이터가 7 비트라면 당신을 물지 않을 것입니다. 그러나 C/C ++ 프로그램을 8 비트를 깨끗하게 만들려고한다면 끝없는 모호한 버그의 원천이 될 것입니다.

서명은 거의 같은 방식으로 작동합니다 char다른 통합 유형에서와 마찬가지로. 당신이 언급했듯이, 숯은 실제로 단지 1 바이트 정수입니다. (반드시 8 비트는 아닙니다, 그렇지만! 차이가 있습니다. 바이트는 일부 플랫폼에서 8 비트보다 클 수 있으며 chars는의 정의로 인해 바이트에 묶여 있습니다. char 그리고 sizeof(char). 그만큼 CHAR_BIT 정의 된 매크로 <limits.h> 또는 C ++ 's <climits>, 얼마나 많은 비트가 char.).

표지판이있는 캐릭터를 원하는 이유 : C 및 C ++에서는 표준 유형이 없습니다. byte. 컴파일러에 charS는 바이트이고 그 반대도 마찬가지이며, 그것들을 구별하지 않습니다. 그러나 때로는 당신이 원합니다 - 때로는 당신이 원하다 저것 char 1 바이트 숫자와 그 경우 (특히 바이트가 얼마나 작은 지), 일반적으로 숫자가 서명되었는지 여부를 관리합니다. 나는 개인적으로 Signedness (또는 부호없는)를 사용하여 char 캐릭터가 아닌 (숫자) "바이트"이며 수치 적으로 사용될 것입니다. 지정된 서명없이 char 실제로 캐릭터이며 텍스트로 사용되도록 의도됩니다.

나는 오히려 그렇게했다. 이제 C 및 C ++의 최신 버전은 (u?)int_least8_t (현재 typedef'd <stdint.h> 또는 <cstdint>), 더 명시 적으로 숫자 인 경우 (일반적으로 서명 및 서명되지 않은 경우 유형이 될 것입니다. char 어쨌든 유형).

이것이 문제라고 생각할 수있는 유일한 상황은 당신이 숯으로 수학을 선택하는 경우입니다. 다음 코드를 작성하는 것은 완벽하게 합법적입니다.

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

Char의 서명에 따라 C는 두 값 중 하나 일 수 있습니다. Char가 서명되지 않으면 C는 (char) 162가됩니다. 서명 된 경우 서명 된 숯의 최대 값이 128이므로 오버플로 케이스가됩니다. 대부분의 구현이 단지 char (char) -32를 반환 할 것이라고 생각합니다.

서명 된 숯의 한 가지는 C> = ''(공간)를 테스트하고 일반 인쇄 가능한 ASCII 숯임을 확인할 수 있다는 것입니다. 물론 휴대용은 아니기 때문에 그다지 유용하지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top