2016-07-13 6 views
1

UNICODE_STRING에서 버퍼를 사용하고 싶습니다. 그러나 참조를 복사하여 직접 사용할 수없는 것 같습니다. 언젠가는 문자열 중간에 null 바이트가 있다는 것을 알기 때문에, Length은 디버거에서 보는 것보다 큽니다. 나는이UNICODE_STRING to wchar_t * null

UNICODE_STRING testStr; 
//after being used by some function it has data like this 'bad丣\0more_stuff\0' 

wchar_t * wStr = testStr.Buffer; 

을 할 그렇다면 나는 wStr = "bad丣"; 종료 널이를 변환하는 방법이 있나요, 유효 wchar_t*으로 끝날 것인가?

+1

당신이 Buffer 데이터가 널 (null)로 구분 된 여러 문자열을 포함 알고있는 경우

또는, 당신은 대신 문자열의 배열로 예를 Buffer 데이터를 분할에 선택적으로 수 어떤 인코딩에서 유니 코드 문자열입니까? – 2501

+3

그래서 [이중 null로 끝나는 문자열] (https://blogs.msdn.microsoft.com/oldnewthing/20091008-00/?p=16443)이 있습니다. 그다지 드물지 않다. –

+1

종료 문자로 '0'을 사용하는 모든 문자열 시스템에서 작동합니다. –

답변

3

wchar_t*은 포인터 일뿐입니다. wchar_t 문자가 정확히 얼마나 많은 수를 가리키는 지 디버거 (또는 wchar_t*에 전달하는 함수)에 지시하지 않는 한, 어딘가에서 멈추어야하므로 첫 번째 null 문자에서 멈 춥니 다.

UNICODE_STRING::Buffer은 Null 종료가 보장되지 않지만 Null이 포함될 수 있습니다. UNICODE_STRING::Length 필드를 사용하여 Buffer에 포함 된 요소가 얼마나 많은지 알 수 있습니다 (포함 된 널 (null)은 포함하지만 후미 null 종결 자 (존재하는 경우)는 포함되지 않습니다. 널 (Null) 터미네이터가 필요하면 Buffer 데이터를 사용자의 버퍼에 복사하고 터미네이터를 추가하십시오.

#include <string> 

UNICODE_STRING testStr; 
// fill testStr as needed... 

std::wstring wStrBuf(testStr.Buffer, testStr.Length/sizeof(WCHAR)); 
const wchar_t *wStr = wStrBuf.c_str(); 

내장 널 (null)이 여전히 존재하지만, c_str() 당신을위한 후행 null 종결을 추가합니다 :

그 작업을 수행하는 가장 쉬운 방법은 예를 들어, std::wstring을 사용하는 것입니다.디버거은 디버거에서 데이터에있는 실제 숫자가 WCHAR 인 경우를 제외하고는 첫 번째 null까지만 데이터를 표시합니다.

#include <string> 
#include <vector> 

UNICODE_STRING testStr; 
// fill testStr as needed... 

std::vector<std::wstring> wStrArr; 

std::wstring wStr(testStr.Buffer, testStr.Length/sizeof(WCHAR)); 
std::wstring::size_type startidx = 0; 
do 
{ 
    std::wstring::size_type idx = wStr.find(L'\0', startidx); 
    if (idx == std::wstring::npos) 
    { 
     if (startidx < wStr.size()) 
     { 
      if (startidx > 0) 
       wStrArr.push_back(wStr.substr(startidx)); 
      else 
       wStrArr.push_back(wStr); 
     } 
     break; 
    } 
    wStrArr.push_back(wStr.substr(startidx, idx-startidx)); 
    startidx = idx + 1; 
} 
while (true); 

// use wStrArr as needed... 

또는 :

#include <vector> 
#include <algorithm> 

UNICODE_STRING testStr; 
// fill testStr as needed... 

std::vector<std::wstring> wStrArr; 

WCHAR *pStart = testStr.Buffer; 
WCHAR *pEnd = pStart + (testStr.Length/sizeof(WCHAR)); 

do 
{ 
    WCHAR *pFound = std::find(pStart, pEnd, L'\0'); 
    if (pFound == pEnd) 
    { 
     if (pStart < pEnd) 
      wStrArr.push_back(std::wstring(pStart, pEnd-pStart)); 
     break; 
    } 
    wStrArr.push_back(std::wstring(pStart, pFound-pStart)); 
    pStart = pFound + 1; 
} 
while (true); 

// use wStrArr as needed... 
+0

[std :: string :: c_str()] (http://en.cppreference.com/w/cpp/string/basic_string/c_str)는 'const'에 대한 포인터를 반환합니다. – IInspectable

1

UNICODE_STRING은 문자 데이터와 길이를 모두 저장하는 구조입니다. 따라서 예를 들어 std::wstring처럼 내장 된 NUL 문자를 사용할 수 있습니다.

C 스타일 문자열 (예 : wchar_t*)은 명시 적 문자열 길이를 저장하지 않습니다. 규칙 상 NUL 문자로 종료됩니다. 길이가 함축되어 있습니다. 이것의 결론은 내장 된 NUL 문자를 포함 할 수 없다는 것입니다.

즉 길이 정보를 잃지 않고 UNICODE_STRING에서 wchar_t*으로 변환 할 수 없음을 의미합니다. wchar_t* 포인터와 함께 길이를 명시 적으로 저장하거나 해석을위한 규칙을 설정해야합니다 (예 : 문자 시퀀스를 이중 null로 끝나는 문자열로 해석하여) 1) 길이를 다시 계산할 수있는 규칙을 설정해야합니다.


추가 정보 : 디버거가 0 종료 문자열로 wchar_t* 해석합니다


1) . 전체 시퀀스를보고 싶다면 format specifier을 사용하여 어레이 크기를 명시 적으로 제공해야합니다.