programing

Char에 저장된 유니코드

lovejava 2023. 10. 6. 20:47

Char에 저장된 유니코드

저는 지금 리눅스에서 C언어를 배우고 있는데 조금 이상한 상황을 발견했습니다.

C 로 char데이터 유형은 ASCII, 1바이트(8비트)입니다.ASCII 문자만 사용할 수 있다는 의미여야 합니다.

내가 사용하는 프로그램에서char input[],에.getchar다음 의사 코드와 같은 기능을 합니다.

char input[20];
int z, i;
for(i = 0; i < 20; i++)
{
   z = getchar();
   input[i] = z;
}

뿐만 아니라 은 ASCII 입니다와 내가 입니다.@&@{čřžŧ¶'`[łĐŧđж←^€~[←^ø{&}čž

제 질문은 - 어떻게 가능할까요?C의 많은 아름다운 예외 중 하나인 것 같지만, 설명해주시면 정말 감사하겠습니다.OS, 컴파일러, 히든 언어의 추가적인 초기능의 문제인가요?

감사해요.

여기에는 마법이 없습니다. C 언어를 사용하면 컴퓨터 메모리에 저장된 원시 바이트에 액세스할 수 있습니다.터미널에서 utf-8을 사용하는 경우(가능한 경우), ASC가 아닌 경우II 문자는 메모리에서 1바이트 이상을 사용합니다.다시 표시할 때, 는 이러한 시퀀스를 하나의 표시된 문자로 변환하는 당사의 단말기 코드입니다.

를 하면 됩니다.strlen내 말이 무슨 뜻인지 알게 될 겁니다

utf-8 비ASC를 적절히 처리하려면 다음과 같이 하십시오.C의 II chars 당신은 glib, qt, 또는 다른 많은 것들처럼 당신을 위해 그것들을 다루기 위해 어떤 라이브러리를 사용해야 합니다.

ASCII는 7비트 문자 집합입니다.in C는 일반적으로 8비트 문자로 표시됩니다.8비트 바이트의 가장 높은 비트가 설정되어 있으면 ASCII 문자가 아닙니다.

또한 ASCII를 기본으로 보장하지 않지만 다른 시나리오는 무시하는 경우가 많습니다."원시" 바이트가 알파 문자인지 확인하고 싶다면, 다시 말해 모든 시스템에 주의를 기울일 때는 다음과 같이 말할 수 있습니다.

is_alpha = (c > 0x40 && c < 0x5b) || (c > 0x60 && c < 0x7b);

입니다를 ctype.h다음과 같이 말합니다.

isalpha(c);

유일한 예외인 AFAIK는 숫자에 대한 것이며, 적어도 대부분의 테이블에서는 연속된 값을 가집니다.

따라서 작동합니다.

char ninec  = '9';
char eightc = '8';

int nine  = ninec  - '0';
int eight = eightc - '0';

printf("%d\n", nine);
printf("%d\n", eight);

그러나 이는 'a'가 될 것을 보장하지는 않습니다.

alhpa_a = 0x61;

ASCII를 기반으로 하지 않는 시스템, 즉 EBCD 사용IC; C 플랫폼에서는 여전히 잘 실행되지만 여기서는 (대부분) 7비트 대신 8비트를 사용합니다.A십진법으로 코딩할 수 있습니다.193 안 돼요.65ASCII에 있는 것처럼.


그러나 ASCII의 경우, 10진수 128 - 255(8비트 사용)인 바이트가 확장되며 ASCII 집합의 일부가 아닙니다.즉, ISO-8859는 이 범위를 사용합니다.

흔히 행해지는 일; 또한 두 개 이상의 바이트를 하나의 문자에 결합하는 것입니다.그래서 만약 당신이 두 바이트를 차례로 인쇄한다면 그것은 say, utf8로 정의됩니다. 0xc3 0x98== Ø, 그러면 이 캐릭터가 나올 겁니다.

이것은 다시 여러분이 어떤 환경에 있느냐에 따라 달라집니다.많은 시스템/환경에서 ASCII 값을 인쇄하면 문자 집합, 시스템 등에서 동일한 결과를 얻을 수 있습니다.그러나 바이트 > 127 또는 더블 바이트 문자를 인쇄하면 로컬 구성에 따라 다른 결과를 얻을 수 있습니다.

예를 들어:

프로그램을 운영하는 A씨는

재스 ŋ€

B씨가 받는 동안

재스

이는 확장 문자 등의 단일 바이트 표현의 ISO-8859 시리즈 및 Windows-1252와 특히 관련이 있을 수 있습니다.


  • UTF-8#Codepage_layout, UTF-8에는 ASCII가 있고, 그 다음에는 바이트의 특별한 시퀀스가 있습니다.
    • 각 시퀀스는 바이트 > 127(마지막 ASCII 바이트)로 시작합니다.
    • 수 에, 합니다.10.
    • 다시 말해, 멀티바이트 UTF-8 표현에서 ASCII 바이트를 찾을 수 없습니다.

즉, UTF-8의 첫 번째 바이트는 ASCII가 아닐 경우 이 문자의 바이트 수를 알려줍니다.가장 높은 비트가 0이므로 ASCII 문자가 더 이상 바이트를 따르지 않는다고 말할 수도 있습니다.

예를 들어 파일이 UTF-8로 해석되는 경우:

fgetc(c);

if c  < 128, 0x80, then ASCII
if c == 194, 0xC2, then one more byte follow, interpret to symbol
if c == 226, 0xE2, then two more byte follows, interpret to symbol
...

예를 들면.여러분이 말씀하시는 캐릭터 중에 하나를 보시면.UTF-8 터미널에 있는 경우:

$ echo -n "ch" | xxd

산출량:

0000000: c48d..

즉, "ch"는 두 바이트 0xc4와 0x8d로 표현됩니다.xxd 명령어에 -b를 추가하면 바이트의 이진법 표현을 얻을 수 있습니다.다음과 같이 분석합니다.

 ___  byte 1 ___     ___ byte 2 ___                       
|               |   |              |
0xc4 : 1100 0100    0x8d : 1000 1101
       |                    |
       |                    +-- all "follow" bytes starts with 10, rest: 00 1101
       |
       + 11 -> 2 bits set = two byte symbol, the "bits set" sequence
               end with 0. (here 3 bits are used 110) : rest 0 0100

Rest bits combined: xxx0 0100 xx00 1101 => 00100001101
                       \____/   \_____/
                         |        |
                         |        +--- From last byte
                         +------------ From first byte

이것은 우리에게: 00100001101 = 269 = 0x10D ==> 코드 포인트 U+010D = "q"를 줍니다.

이 에서 는 HTML 에서도.&#269;

이것과 다른 많은 코드 시스템에서 공통적인 것은 8비트 바이트가 기본이라는 것입니다.


종종 그것은 문맥에 대한 질문이기도 합니다.예를 들어, ETSI GSM 03.38/03.40(3GPP TS 23.038, 3GPP 23038)을 사용한 GSM SMS를 예로 들 수 있습니다.또한 7비트 문자 테이블, 7비트 GSM 기본 알파벳도 있지만 8비트로 저장하는 대신 7비트로1 저장됩니다.이렇게 하면 더 많은 문자를 지정된 바이트 수로 포장할 수 있습니다.즉 표준 SMS 160 문자는 ASCII로 1280비트 또는 160바이트가 되고 SMS로 1120바이트 또는 140바이트가 됩니다.

1 예외가 없는 것은 아닙니다. (그것은 이야기에 더 가깝습니다.

즉, ASC에 대한 SMS UDP 형식으로 셉텟(7bit) C8329BFD06으로 저장된 바이트의 간단한 예II:

                                _________
7 bit UDP represented          |         +--- Alphas has same bits as ASCII
as 8 bit hex                   '0.......'
C8329BFDBEBEE56C32               1100100 d * Prev last 6 bits + pp 1
 | | | | | | | | +- 00 110010 -> 1101100 l * Prev last 7 bits 
 | | | | | | | +--- 0 1101100 -> 1110010 r * Prev 7 + 0 bits
 | | | | | | +----- 1110010 1 -> 1101111 o * Last 1 + prev 6
 | | | | | +------- 101111 10 -> 1010111 W * Last 2 + prev 5
 | | | | +--------- 10111 110 -> 1101111 o * Last 3 + prev 4
 | | | +----------- 1111 1101 -> 1101100 l * Last 4 + prev 3
 | | +------------- 100 11011 -> 1101100 l * Last 5 + prev 2
 | +--------------- 00 110010 -> 1100101 e * Last 6 + prev 1
 +----------------- 1 1001000 -> 1001000 H * Last 7 bits
                                 '------'
                                    |
                                    +----- GSM Table as binary

그리고 9바이트 "unpacked"는 10자가 됩니다.

ASCII는 8비트가 아니라 7비트입니다.char []는 바이트를 보유하며, 임의의 인코딩 - iso8859-1, utf-8, 원하는 대로 가능합니다.C는 신경 안 써요.

이게 UTF-8의 마법이라 어떻게 작동하는지 걱정할 필요도 없습니다.유일한 문제는 C data-type의 이름이 붙여졌다는 것입니다.char(문자의 경우), 실제로 의미하는 것은 바이트입니다.문자와 문자를 인코딩하는 바이트 사이에는 1:1 대응 관계가 없습니다.

코드에서 일어나는 일은 프로그램의 관점에서 바이트 시퀀스를 입력하면 바이트가 메모리에 저장되고 텍스트를 인쇄하면 바이트가 인쇄됩니다.이 코드는 이러한 바이트가 문자를 어떻게 인코딩하는지는 중요하지 않으며 입력 시 인코딩하고 출력 시 정확하게 해석하는 것에 대해 걱정해야 하는 것은 터미널뿐입니다.

물론 이러한 기능을 수행하는 라이브러리가 많이 있지만 UTF8 유니코드를 빠르게 해독하기 위해서는 다음과 같은 작은 기능이 유용합니다.

typedef unsigned char utf8_t;

#define isunicode(c) (((c)&0xc0)==0xc0)

int utf8_decode(const char *str,int *i) {
    const utf8_t *s = (const utf8_t *)str; // Use unsigned chars
    int u = *s,l = 1;
    if(isunicode(u)) {
        int a = (u&0x20)? ((u&0x10)? ((u&0x08)? ((u&0x04)? 6 : 5) : 4) : 3) : 2;
        if(a<6 || !(u&0x02)) {
            int b,p = 0;
            u = ((u<<(a+1))&0xff)>>(a+1);
            for(b=1; b<a; ++b)
                u = (u<<6)|(s[l++]&0x3f);
        }
    }
    if(i) *i += l;
    return u;
}

코드를 고려할 때 문자열을 반복하고 유니코드 값을 읽을 수 있습니다.

int l;
for(i=0; i<20 && input[i]!='\0'; ) {
   if(!isunicode(input[i])) i++;
   else {
      l = 0;
      z = utf8_decode(&input[i],&l);
      printf("Unicode value at %d is U+%04X and it\'s %d bytes.\n",i,z,l);
      i += l;
   }
}

데이터 유형이 있습니다.wint_t(#include <wchar.h>ASC가 아닌 경우2자.방법을 사용하시면 됩니다.getwchar()그것들을 읽습니다.

언급URL : https://stackoverflow.com/questions/10017328/unicode-stored-in-c-char