2013-02-08 3 views
7

unsigned char 포인터의 용도는 무엇입니까? 많은 곳에서 포인터가 포인터로 타입 캐스트되어있는 것을 보았습니다 unsinged char 왜 그렇게할까요?부호없는 char 포인터를 사용하는 경우

int에 대한 포인터를받은 다음 unsigned char*에 입력하십시오. 그러나 우리가 cout을 사용하여 그 배열에 요소를 인쇄하려고하면 아무 것도 출력하지 않습니다. 왜? 난 이해가 안 돼요. 나는 C++을 처음 사용합니다.

편집 샘플 코드

int Stash::add(void* element) 
{ 
    if(next >= quantity) 
    // Enough space left? 
     inflate(increment); 

    // Copy element into storage, starting at next empty space: 
    int startBytes = next * size; 
    unsigned char* e = (unsigned char*)element; 
    for(int i = 0; i < size; i++) 
     storage[startBytes + i] = e[i]; 
    next++; 
    return(next - 1); // Index number 
} 
+0

문자 포인터로 변환 할 때 첫 번째 바이트는 아마도 문자열 종결 자와 동일한 0 일 것이므로 아무 것도 인쇄되지 않습니다. 실제로하는 일을 보여줄 수 있다면 더 많은 도움이 될 것입니다. 즉, 코드를 게시하십시오. [SSCCE] (http://sscce.org/)를 작성하고 질문에 추가하십시오. –

+0

하지만 첫 번째 바이트가 0이고 실제로 4 바이트를 모두 인쇄하려고 시도하지만 아무 것도 인쇄하지 않으면 정보가 느슨해 질 것이라고 생각합니다. –

+2

귀하의 질문은 "언제"보다는 "이유"에 관한 것 같습니다. 매우 자주,'unsigned char * '는 다른 형식의 변수 나 메모리 주소에 도달하기위한 바이트 레벨 액세스 메소드로 사용됩니다. 그 중에서도 엄격한 앨리어싱 규칙에 대한 면책 ​​사항과 귀하가 던지는 주소와의 표준 보장 정렬에 대한 많은 신빙성이 있습니다. C++을 처음 접했을 때, C에 익숙하다면이 작업을 어렵게해서는 안됩니다. * 프로그래밍 *에 익숙하지 않은 분은 이것을 이해하기 어려운 것으로 생각합니다. 아마도 몇 가지 코드와 생각을 가지고있을 것입니다. – WhozCraig

답변

5

다음은 실제로 pointer arithmetic를 찾고 있습니다 :이 예에서

unsigned char* bytes = (unsigned char*)ptr; 
for(int i = 0; i < size; i++) 
    // work with bytes[i] 

, bytes[i]*(bytes + i) 같으며에 메모리에 액세스하는 데 사용됩니다 주소 : bytes + (i* sizeof(*bytes)). 즉 : 당신은 int* intPtr을 가지고 있고 당신은 당신이 실제로 바이트에 저장된 정수에 액세스하는, intPtr[1]에 액세스하려고하면 : 그것은 한 후 지적 곳

0 1 2 3 
4 5 6 7 <-- 

이 포인터 포인트를 입력의 크기에 영향을 미치는하기 : 4 ~ 7을 증가/감소합니다. 따라서 바이트 단위로 데이터를 반복하고 싶다면 크기가 1 바이트 인 유형의 포인터가 필요합니다 (그 이유는 unsigned char*입니다).


unsigned char은 일반적으로 0가 유효한 값이 여전히 데이터의 일부입니다 이진 데이터를 보유하는 데 사용됩니다. "알몸"으로 작업하는 동안 unsigned char* 버퍼의 길이를 보유해야 할 것입니다.

char은 일반적으로 문자열을 나타내는 문자를 유지하는 데 사용되고 0'\0' (종료 문자)와 같습니다. 문자 버퍼가 항상 '\0'으로 끝나면 문자의 종단이 정확하게 데이터의 끝을 지정하기 때문에 길이를 알 필요가 없습니다.

두 경우 모두 데이터의 내부 표현을 숨기고 메모리 관리를 담당하는 개체를 사용하는 것이 더 좋습니다 (RAII idiom 참조). 따라서 std::vector<unsigned char> (이진 데이터의 경우) 또는 std::string (문자열의 경우)을 사용하는 것이 좋습니다.

2

unsinged char 유형은 일반적으로 이진 데이터의 단일 byte의 표현으로 사용됩니다. 따라서, array는 자주 이진 데이터 버퍼로 사용되며, 각 요소는 단일 바이트입니다.

unsigned char* 구조체는 이진 데이터 버퍼 (또는 첫 번째 요소)에 대한 포인터가됩니다.

c++ 표준은 정확히 unsigned char의 크기에 대해 8 비트로 고정되어 있는지 여부를 100 % 확신하지 못합니다. 보통입니다. 나는 그것을 찾아서 게시하려고 노력할 것이다.코드

당신은 함수의 매개 변수로 void* input 같은 것을 사용보고 후

, 당신은 의도적으로 입력 원래 유형에 대한 정보를 제거. 이것은 입력이 매우 일반적인 방식으로 취급 될 것이라는 강한 제안입니다. 나는. 임의의 바이트 문자열로. 반면 int* input은 노래 된 정수의 "문자열"로 취급 될 것이라고 제안합니다. 당신이 그 내용에 대해 결론을 내릴 수 없기 때문에

void*

주로, 입력 인코딩됩니다 때 경우에 사용, 또는 어떤 이유 bit/byte 현명한 처리됩니다.

그렇다면 함수에서 바이트의 문자열로 입력을 처리하려는 것 같습니다. 그러나 객체를 조작하려면이 필요합니다. operator= (할당)을 수행하면 컴파일러는 무엇을해야하는지 알 필요가있다. 입력이 *input = something과 같이 지정되어 있기 때문에 *inputvoid 유형이므로 의미가 없습니다. input 요소를 "가장 작은 원시 메모리 조각"으로 처리하는 컴파일러를 만들려면 unsigned int 인 적절한 형식으로 변환합니다.

cout은 잘못되었거나 의도하지 않은 형식 변환으로 인해 작동하지 않았을 수 있습니다. char*은 null로 끝나는 문자열로 간주되며 singedunsigned 버전 코드와 혼동하기 쉽습니다. unsinged char*ostream::operator<<으로 char*으로 전달하면 00의 정수 값이 아닌 문자열의 끝인 것으로 간주하여 byte 입력을 일반 ASCII 문자로 간주하고 처리합니다. 메모리 내용을 인쇄하려면 명시 적으로 포인터를 캐스팅하는 것이 가장 좋습니다.

버퍼의 메모리 내용을 인쇄하려면 루프를 사용해야합니다. 인쇄 기능은 언제 중지해야하는지 알 수 없으므로 루프를 사용해야합니다.

+1

C 및 C++는 문자 유형 ('char','unsigned char' 및'signed char')을 1 바이트 크기로 정의하고 8 비트 이상을 요구합니다. 최근까지는 9 비트'char' 머신이 있었고, 32 비트 char을 가진 머신이있었습니다. (역사적으로, 물론 8 비트 미만의 바이트를 가진 많은 기계가 있었지만 C는 이것을 허용하지 않습니다.) –

+0

@James, 감사합니다. 나는 그것을 언급했다, 왜냐하면 나는 그것이 항상 8 비트임을 보장받지 못한다는 것을 기억하기 때문이다. 저수준 네트워크 프로토콜을 구현하거나 시스템에서 시스템으로 바이너리 파일을 옮기는 경우에 대비하여 이러한주의 사항을 접할 수도 있습니다. – luk32

+1

많은 것들은 당신이 얼마나 이식성이 있어야하는지에 달려 있습니다. 대부분의 사람들에게, 이식성 제약은'char '이 8 비트라는 가정을 허용하기에 충분할만큼 느슨 할 것이다. –

7

C에서는 unsigned char이 트래핑 값이없는 유일한 유형이며 복사를 통해 정확한 비트 이미지가 생성됩니다. (C++은이 보증을 char으로 확장합니다.) 따라서 "전통적 메모리"(예 : memcpy의 의미는 unsigned char으로 정의됩니다)에서 전통적으로 사용됩니다.

또한 비트 연산 (&, |, >> 등)을 사용할 때 일반적으로 부호없는 정수 유형이 사용됩니다. unsigned char은 최소 부호없는 정수 유형이며 비트 연산이 사용되는 작은 값의 배열을 조작 할 때 사용할 수 있습니다. 가끔씩, 오버 플로우의 경우 모듈로 동작이 필요하기 때문에 더 큰 유형 (예 : 해시 값을 계산할 때)이 더 빈번하기는하지만 때때로 사용되기도합니다. 이 두 가지 이유는 일반적으로 부호없는 유형에 적용됩니다. unsigned char은 메모리 사용을 줄여야 할 필요가있을 때만 일반적으로 사용됩니다.

+1

"C++은이 보증을'char'에도 적용합니다." - 이걸 가져갈 수 있을까요? – emlai

0

부호없는 char 포인터는 데이터를 바이트 단위로 액세스하려는 경우 유용합니다. 예를 들어, 기능이 다른 하나 개의 영역으로부터 데이터를 복사이 필요할 수 있음 : 또한 갖는다

void memcpy (unsigned char* dest, unsigned char* source, unsigned count) 
{ 
    for (unsigned i = 0; i < count; i++) 
     dest[i] = source[i]; 
} 

를 바이트 메모리의 가장 작은 단위는 사실과 관련.메모리에서 1 바이트보다 작은 내용을 읽으려면 해당 정보가 들어있는 바이트를 가져온 다음 비트 연산을 사용하여 정보를 선택해야합니다.

위의 함수에서 int 포인터를 사용하여 데이터를 복사 할 수는 있지만 일부 상황에서는 올바르지 않을 수있는 4 바이트 청크를 복사합니다.

cout을 사용하려고 할 때 화면에 아무 것도 표시되지 않는 이유는 데이터가 0 문자로 시작한다는 것입니다. C++에서는 문자의 끝을 표시합니다.

+0

0 문자로 시작하는 경우에도 다른 3 문자의 값을 인쇄해야합니다. 그리고 for 루프의 if (int i = 0; i

+0

"위 함수에서 'int' 포인터를 사용하여 데이터를 복사 할 수 있습니다."아니, 잘 할 수는 없습니다. (A) 기본 메모리의 모든 비트를 커버 할 수 없거나 (B) 임의의 바이트를'A '로 재 해석하려고 할 때 발생할 수있는 트래핑/유효하지 않은 값을 허용하지 않는다. int's. 'unsigned char * '가 아닌 다른 포인터를 쓰는 것은 본질적으로, & 아주, 이식성이 없다. 구현시이를 플랫폼에 종속적 인 세부 정보로 사용할 수 있지만 사용자는 그렇게해서는 안됩니다. –

관련 문제