TCHAR은 여전히 ​​관련이 있습니까?


87

저는 Windows 프로그래밍을 처음 접했고 Petzold 책을 읽은 후 궁금합니다.

TCHAR유형과 _T()함수 를 사용하여 문자열을 선언 하는 것이 여전히 좋은 습관 입니까? 아니면 새 코드에서 wchar_tL""문자열을 사용해야 합니까?

Windows 2000 이상 만 대상 으로하고 시작부터 코드는 i18n 이됩니다.

답변:


15

오늘 새 프로젝트를 수행한다면 여전히 TCHAR 구문을 사용합니다. 그것을 사용하는 것과 WCHAR 구문을 사용하는 것 사이에는 실질적인 차이가 많지 않으며 문자 유형이 무엇인지 명시적인 코드를 선호합니다. 대부분의 API 함수와 도우미 개체는 TCHAR 유형 (예 : CString)을 사용 / 사용하므로 사용하는 것이 합리적입니다. 또한 어느 시점에서 ASCII 앱에서 코드를 사용하기로 결정했거나 Windows가 Unicode32 등으로 진화 한 경우 유연성을 제공합니다.

WCHAR 경로로 가기로 결정했다면 명시 적으로 설명하겠습니다. 즉, CString 대신 CStringW를 사용하고 TCHAR로 변환 할 때 매크로를 캐스팅합니다 (예 : CW2CT).

어쨌든 그것은 내 의견입니다.


실제로 문자 인코딩이``다시 ''변경 될 때 여전히 작동합니다.
Medinoc 2014 년

11
당신은 문자 유형이 무엇인지 명시적인 코드를 선호하므로 때때로 이것과 때로는 그 유형을 사용합니까? 매우 설득력이 있습니다.
Deduplicator

4
−1 : @Deduplicator에 의해 언급 된 불일치 및 부정적인 보상 조언은 무엇이든 될 수있는 매크로를 사용하는 것입니다 (일반적으로 하나 이상의 특정 값에 대해 테스트되지 않음).
건배와 hth. - 알프

90

짧은 대답 : 아니오 .

이미 작성한 다른 모든 프로그래머와 마찬가지로 많은 프로그래머가 여전히 TCHAR 및 해당 함수를 사용합니다. 저의 겸손한 의견으로 는 전체 개념이 나쁜 생각 이었습니다. UTF-16 문자열 처리는 단순한 ASCII / MBCS 문자열 처리와는 많이 다릅니다. 두 가지 모두에 동일한 알고리즘 / 함수를 사용하는 경우 (이것이 TCHAR 아이디어의 기반입니다!), 단순한 문자열 연결보다 조금 더 많은 작업을 수행하는 경우 (예 : 구문 분석 등). 주된 이유는 대리자 입니다.

유일한 예외로 당신은 때 정말 유니 나는 새로운 응용 프로그램에서 과거이 수하물을 사용하는 이유를 볼 지원하지 않는 시스템에 대한 귀하의 응용 프로그램을 컴파일해야합니다.


6
재미있는 사실 : UTF-16이 항상 NT 플랫폼에있는 것은 아닙니다. 대리 코드 포인트는 NT 4가 출시 된 해인 1996 년 유니 코드 2.0에서 도입되었습니다. IIRC (Windows 2000 포함)까지 모든 NT 버전은 UCS-2를 사용했습니다. 이는 사실상 각 문자를 하나의 코드 포인트로 표현할 수 있다고 가정하는 UTF-16의 하위 집합이었습니다 (즉, 서로 게이트 없음).
0xC0000022L

3
btw, TCHAR더 이상 사용해서는 안된다는 데 동의하지만 이것이 나쁜 생각이라는 데 동의 하지 않습니다. 또한 사용하는 대신 명시 적으로 선택 하는 경우 모든 곳에서TCHAR 명시 적이어야한다고 생각 합니다. 즉 , 선언에서 / (예 :)와 함께 함수를 사용하지 마십시오 . 간단히 말해 일관성을 유지하십시오. +1, 여전히. TCHAR_TCHAR_tmain
0xC0000022L

3
처음 소개되었을 때는 좋은 아이디어 였지만 새 코드에서는 무관해야합니다.
Adrian McCarthy

4
당신은 무엇을 잘못 TCHAR윈 9x와 윈도우 NT의 Windows 기반 버전에 대한 코드의 개발을 쉽게하기 : 처음 도입 된의. 그 당시 Windows NT의 UTF-16 구현은 UCS-2였으며 문자열 구문 분석 / 조작 알고리즘은 동일했습니다. 대리자가 없었습니다. 서로 게이트를 사용하더라도 DBCS (Windows에서 유일하게 지원되는 MBCS 인코딩) 및 UTF-16에 대한 알고리즘은 동일합니다. 두 인코딩에서 코드 포인트는 하나 또는 두 개의 코드 단위로 구성됩니다.
IInspectable 2015

FormatMessage ()를 사용하여 WSAGetLastError ()의 값을 인쇄 가능한 값으로 변환한다고 가정합니다. WSAGetLastError ()에 대한 문서는 LPTSTR을 버퍼에 대한 포인터로 사용한다고 말합니다. 정말 선택의 여지가 많지 않지만 TCHAR을 사용할 수 있습니다.
Edward Falk

81

나는 Sascha에 동의해야합니다. TCHAR/ _T()/ etc. 의 기본 전제 는 "ANSI"기반 응용 프로그램을 작성한 다음 매크로를 정의하여 마술처럼 유니 코드 지원을 제공 할 수 있다는 것입니다. 그러나 이것은 몇 가지 나쁜 가정을 기반으로합니다.

소프트웨어의 MBCS 및 유니 코드 버전을 모두 적극적으로 빌드해야합니다.

그렇지 않으면, 당신은 까지 미끄러 보통 사용하는 char*많은 장소에서 문자열을.

_T ( "...") 리터럴에서 ASCII가 아닌 백 슬래시 이스케이프를 사용하지 않습니다.

"ANSI"인코딩이 ISO-8859-1 이 아니면 결과 char*wchar_t*리터럴은 동일한 문자를 나타내지 않습니다.

UTF-16 문자열은 "ANSI"문자열처럼 사용됩니다.

그들은 아니야. 유니 코드는 대부분의 레거시 문자 인코딩에 존재하지 않는 몇 가지 개념을 도입합니다. 대리. 문자 결합. 표준화. 조건부 및 언어 구분 대소 문자 규칙.

그리고 아마도 가장 중요한 것은 UTF-16이 디스크에 저장되거나 인터넷을 통해 전송되는 경우가 드물다는 사실입니다. UTF-8은 외부 표현에 선호되는 경향이 있습니다.

애플리케이션이 인터넷을 사용하지 않는다는 사실

(이제,이에 대한 올바른 가정 할 수있다 당신의 ... 소프트웨어 만)

웹은 UTF-8더 희귀 한 인코딩으로 실행 됩니다. 이 TCHAR개념은 "ANSI"( UTF-8 일 수 없음 )와 "유니 코드"(UTF-16) 두 가지만 인식 합니다. Windows API 호출이 유니 코드를 인식하도록 만드는 데 유용 할 수 있지만 웹 및 전자 메일 앱이 유니 코드를 인식하도록 만드는 데는 쓸모가 없습니다.

타사 라이브러리를 사용하지 않음

다른 누구도 TCHAR. Pocostd::stringUTF-8을 사용합니다. SQLite 에는 UTF-8 및 UTF-16 버전의 API가 있지만 TCHAR. TCHAR표준 라이브러리에도 없으므로 std::tcout직접 정의 하지 않는 한 없습니다 .

TCHAR 대신 내가 추천하는 것

유효한 UTF-8이 아닌 파일을 읽어야하는 경우를 제외하고 "ANSI"인코딩이 존재한다는 사실을 잊어 버리십시오. TCHAR너무 잊어라 . 항상 Windows API 함수의 "W"버전을 호출하십시오. #define _UNICODE실수로 "A"함수를 호출하지 않도록하기 위해서입니다.

문자열에는 항상 UTF 인코딩을 사용합니다. 문자열에는 UTF-8, char문자열에는 UTF-16 (Windows) 또는 UTF-32 (Unix 계열 시스템)를 wchar_t사용합니다. typedef UTF16UTF32문자 유형은 플랫폼의 차이를 방지 할 수 있습니다.


6
2012 년 전화 : 지금도없이 유지해야 할 응용 프로그램이 있습니다 #define _UNICODE. 전송 종료 :)
0xC0000022L

12
@ 0xC0000022L 질문은 새로운 코드 에 관한 것이 었습니다 . 당신은 예전의 코드를 유지하는 경우, 당신은 분명히 환경과 일해야 하는 것이 코드를 위해 작성되었습니다. COBOL 응용 프로그램을 유지 관리하는 경우 COBOL이 좋은 언어인지 여부는 중요하지 않습니다. 그리고 TCHAR에 의존하는 애플리케이션을 유지하고 있다면 그것이 좋은 결정인지 아닌지는 중요하지 않습니다.
jalf

2
사실, TCHAR은 COBOL이 아니면 유용하지 않습니다)
Pavel Radzivilovsky

1
_UNICODECRT에서 일반 텍스트 매핑이 확인되는 방식을 제어합니다. ANSI 버전의 Windows API를 호출하지 않으려면 UNICODE.
IInspectable

18

아직 실행 중인지 궁금하다면 예-여전히 꽤 많이 사용됩니다. TCHAR와 _T ( "")를 사용하면 아무도 당신의 코드를 재미있게 보지 않을 것입니다. 내가 지금 작업하고있는 프로젝트는 ANSI에서 유니 코드로 변환하는 것입니다. 그리고 우리는 휴대용 (TCHAR) 경로로 가고 있습니다.

하나...

내 투표는 모든 ANSI / UNICODE 포터블 매크로 (TCHAR, _T ( "") 및 모든 _tXXXXXX 호출 등)를 잊어 버리고 모든 곳에서 유니 코드를 가정하는 것입니다. ANSI 버전이 필요하지 않다면 이식성에 대한 요점을 알지 못합니다. 모든 와이드 문자 기능과 유형을 직접 사용합니다. 모든 문자열 리터럴을 L로 미리 시작합니다.


3
ANSI 버전이 필요한 다른 곳에서 사용하고 싶은 코드를 작성하거나 (Nick이 말했듯이) Windows가 DCHAR 또는 기타로 이동할 수 있으므로 여전히 TCHAR 대신 TCHAR을 사용하는 것이 좋습니다. WCHAR.
arke 2010 년

Windows가 UTF-32로 전환 될 것 같지는 않습니다.
dan04

7
UTF-16 권장 사항의 경우 -1입니다. 이로 인해 라이브러리에서 허용되지 않는 이식 불가능한 (Windows 중심) 코드가 생성 될뿐만 아니라 UI 코드와 같은 가장 단순한 경우에 사용될 수 있지만 Windows 자체에서도 효율적이지 않습니다. utf8everywhere.org
Pavel Radzivilovsky

11

소개하여 Windows 프로그래밍 기사 MSDN에 말한다

새 애플리케이션은 항상 API의 유니 코드 버전을 호출해야합니다.

TEXTTCHAR의 모든 응용 프로그램이 유니 코드를 사용해야하기 때문에 매크로는 오늘 덜 유용합니다.

나는 wchar_tL"".


4
스티븐, 당신은 '유니 코드'라는 단어의 의미를 이해하지 못하는 사람이 쓴 텍스트를 인용하고 있습니다. 그것은 UCS-2 혼란 당시의 불행한 문서 중 하나입니다.
Pavel Radzivilovsky

2
@PavelRadzivilovsky :이 문서는 유니 코드UTF-16LE 가 일반적으로 같은 의미로 사용되는 시스템 용으로 작성되었습니다 . 기술적으로는 부정확하지만 그럼에도 불구하고 분명합니다. 이것은 또한 명시 적으로 동일한 텍스트의 도입으로 지적되고있다 : "윈도우는 UTF-16 인코딩 [...]를 사용하여 유니 코드 문자를 나타냅니다" .
IInspectable

11

다른 접근법을 제안하고 싶습니다 (둘 중 어느 것도 아님).

요약하면 UTF-8 인코딩을 가정하고 char * 및 std :: string을 사용하고 API 함수를 래핑 할 때만 UTF-16으로 변환합니다.

Windows 프로그램에서이 접근 방식에 대한 자세한 정보와 이유는 http://www.utf8everywhere.org 에서 찾을 수 있습니다 .


@PavelRadzivilovsky, VC ++ 애플리케이션에서 제안을 구현할 때 VC ++ 문자를 '없음'또는 '멀티 바이트 (MBCS)'로 설정 하시겠습니까? 내가 묻는 이유는 방금 Boost :: Locale을 설치했고 기본 문자 집합이 MBCS 였기 때문입니다. FWIW, 내 순수한 ASCII 응용 프로그램은 'None'으로 설정되었고 이제 'MBCS'로 설정했습니다 (Boost :: Locale를 사용할 것이므로). 잘 작동합니다. 조언하십시오.
Caroline Beltran

utf8everywhere에서 권장하는대로 '유니 코드 문자 집합 사용'으로 설정합니다. 이 광고는 추가 안전을 제공하지만 필수는 아닙니다. Boost :: locale의 저자는 매우 똑똑한 사람이지만 그가 옳은 일을했다고 확신합니다.
Pavel Radzivilovsky

1
UTF-8 모든 곳 만트라가 더 자주 반복해서, 최적의 솔루션이 될 수 없습니다. UTF-8은 의심 할 여지없이 직렬화 (예 : 파일 또는 네트워크 소켓)를위한 매력적인 인코딩이지만 Windows에서는 내부적으로 기본 UTF-16 인코딩을 사용하여 문자 데이터를 저장하고 응용 프로그램 경계에서 변환하는 것이 더 적절합니다. 한 가지 이유는 UTF-16이 지원되는 다른 인코딩으로 즉시 변환 할 수있는 유일한 인코딩이기 때문입니다. UTF-8에서는 그렇지 않습니다.
IInspectable

"..UTF-16은 지원되는 다른 인코딩으로 즉시 변환 할 수있는 유일한 인코딩입니다." 무슨 말이야? UTF-8 인코딩을 다른 것으로 변환하는 데 문제가 있습니까?
Pavel Radzivilovsky

1
난 이해가 안 돼요. 다른 무엇이든-뭐처럼? 예 : UCS-4? 왜 안돼? 모든 숫자 알고리즘, 아주 쉬운 것 같은데 ..
파벨 Radzivilovsky

7

TCHAR/ WCHAR일부 레거시 프로젝트에는 충분할 수 있습니다. 그러나 새로운 응용 프로그램의 경우 아니오 라고 말할 것 입니다.

이러한 모든 TCHAR/ WCHAR물건 때문에 역사적 이유가있다. TCHARANSI 텍스트 인코딩 (MBCS)과 유니 코드 텍스트 인코딩 (UTF-16) 사이를 전환하는 깔끔한 방법 (가장)을 제공합니다. 과거에 사람들은 세계의 모든 언어의 문자 수를 이해하지 못했습니다. 그들은 2 바이트가 모든 문자를 표현하기에 충분하다고 가정했고 따라서를 사용하는 고정 길이 문자 인코딩 체계를 가지고 WCHAR있습니다. 그러나 1996 년 유니 코드 2.0이 출시 된 이후에는 더 이상 사실이 아닙니다 .

즉 , CHAR/ WCHAR/ 에서 무엇을 사용하든 TCHAR프로그램의 텍스트 처리 부분은 국제화 를 위해 가변 길이 문자 를 처리 할 수 ​​있어야합니다 .

따라서 실제로 Windows에서 프로그래밍하기 위해 CHAR/ WCHAR/ 에서 하나를 선택하는 것 이상을 수행해야합니다 TCHAR.

  1. 응용 프로그램이 작고 텍스트 처리가 필요하지 않은 경우 (예 : 텍스트 문자열을 인수로 전달) WCHAR. 유니 코드를 지원하는 WinAPI로 작업하는 것이이 방법이 더 쉽기 때문입니다.
  2. 그렇지 않으면 UTF-8을 내부 인코딩으로 사용하고 텍스트를 char 문자열 또는 std :: string에 저장하는 것이 좋습니다. 그리고 WinAPI를 호출 할 때 UTF-16으로 변환합니다. 이제 UTF-8 이 지배적 인 인코딩이며 UTF-8 문자열을 처리하기위한 편리한 라이브러리와 도구가 많이 있습니다.

자세한 내용은이 멋진 웹 사이트를 확인하세요 : http://utf8everywhere.org/


2
"UTF-8이 이제 지배적 인 인코딩입니다." -인용문의 두 번째 부분 ( "for the World Wide Web" )을 생략하여 잘못되었습니다 . 데스크톱 응용 프로그램의 경우 가장 많이 사용되는 기본 문자 인코딩은 여전히 ​​UTF-16입니다. Windows는이를 사용하고 Mac OS X도 사용하며 .NET 및 Java의 문자열 유형도 사용합니다. 그것은 엄청난 양의 코드를 설명합니다. 오해하지 마십시오. 직렬화를위한 UTF-8에는 아무런 문제가 없습니다. 그러나 종종 (특히 Windows에서) 내부적으로 UTF-16을 사용하는 것이 더 적절하다는 것을 알게 될 것입니다.
IInspectable

4

네 그럼요; 적어도 _T 매크로의 경우. 하지만 와이드 캐릭터에 대해서는 잘 모르겠습니다.

그 이유는 WinCE 또는 기타 비표준 Windows 플랫폼을 더 잘 지원하기 위해서입니다. 코드가 NT에 남아있을 것이라고 100 % 확신한다면 일반 C- 문자열 선언을 사용할 수 있습니다. 그러나 수천 줄의 코드를 처리하고 일부 라이브러리를 이식해야하는 경우 모든 곳에 추가하는 것에 비해 Windows가 아닌 플랫폼에서 매크로를 # 정의하는 것이 훨씬 쉽기 때문에보다 유연한 접근 방식을 선호하는 것이 가장 좋습니다. 윈도우 모바일에.


1
WinCE는 Win32와 마찬가지로 16 비트 wchar_t 문자열을 사용합니다. WinCE 및 Win32에서 실행되는 대규모 코드 기반이 있으며 TCHAR을 사용하지 않습니다.
mhenry1384

2

IMHO, 코드에 TCHAR이 있으면 잘못된 추상화 수준에서 작업하고있는 것입니다.

사용 어떤 이 잘하면 뭔가 지원하는 유니 코드 수 있지만 그건 당신에게 달려 - 텍스트 처리를 처리 할 때 문자열 유형이 당신을 위해 가장 편리한. 필요에 따라 OS API 경계에서 변환을 수행하십시오.

파일 경로를 다룰 때 문자열을 사용하는 대신 사용자 정의 유형을 작성하십시오. 이렇게하면 OS에 독립적 인 경로 구분 기호를 사용할 수 있고 수동 문자열 연결 및 분할보다 코드에 대한 더 쉬운 인터페이스를 제공하며 다른 OS (ansi, ucs-2, utf-8 등)에 훨씬 쉽게 적응할 수 있습니다. .


유니 코드에는 최소한 3 개의 현재 인코딩 (UTF-8, UTF-16, UTF-32)과 사용되지 않는 인코딩 (UCS-2, 현재 UTF-16의 하위 집합)이 있습니다. 어느 것을 언급합니까? 나는 나머지 제안을 좋아하지만 +1
0xC0000022L

2

명시 적 WCHAR 이외의 것을 사용하는 유일한 이유는 이식성과 효율성입니다.

최종 실행 파일을 가능한 한 작게 만들고 싶다면 char를 사용하십시오.

RAM 사용에 신경 쓰지 않고 국제화를 간단한 번역처럼 쉽게하려면 WCHAR을 사용하십시오.

코드를 유연하게 만들려면 TCHAR을 사용하십시오.

라틴 문자 만 사용하려는 경우 사용자가 RAM을 많이 필요로하지 않도록 ASCII / MBCS 문자열을 사용하는 것이 좋습니다.

"시작부터 i18n"을 사용하는 사람들을 위해 소스 코드 공간을 절약하고 모든 유니 코드 함수를 사용하십시오.


-1

이전 질문에 추가하기 :

아니

VS2010에서 새로운 CLR C ++ 프로젝트를 시작하십시오. 마이크로 소프트는 스스로 사용 L"Hello World"한다.


13
CLR은 관리되지 않는 코드와는 매우 다른 환경입니다. 그것은 논쟁 이 아닙니다 .
Cody Gray

3
마이크로 소프트도 실수를합니다.
Pavel Radzivilovsky

6
-1 질문에 태그가 지정 C되고 C++. 답변은 항상 해당 작성자가 삭제할 수 있습니다. 이 조항을 사용하기에 좋은시기입니다.
IInspectable 2013 년

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.