2013-10-30 3 views
0

void * &을 사용하여 메모리에 몇 개의 int를 저장하려고 시도하지만이를 검색하지만 "산술 연산에 사용 된 void * '유형의 포인터를 계속 throw합니다.C++ void * memory traversal

void *a = new char[4]; 
memset(a, 0 , 4); 


unsigned short d = 7; 
memcpy(a, (void *)&d, 2); 

d=8; 
memcpy(a+2, (void *)&d, 2); //pointer of type ‘void *’ used in arithmetic 


/*Retrieving*/ 
unsigned int *data = new unsigned int(); 
memcpy(data, a, 2); 
cout << (unsigned int)(*data); 

memcpy(data, a+2, 2); //pointer of type ‘void *’ used in arithmetic 
cout << (unsigned int)(*data); 

결과는 예상대로이지만 일부 컴파일러에서는 이러한 경고가 오류로 변할 수 있습니다. 이 일을하는 또 다른 방법이 있습니까?

정상적인 시나리오에서는이 방법이 좋지 않을 수 있지만 문제 진술에 따르면 부호없는 정수가 저장되어 2 바이트 패킷으로 전송되어야합니다. 내가 틀렸다면 정정하십시오. 그러나 제 이해에 따라, void * 대신 char *를 사용하면 3 자리 숫자에 3 바이트를 사용하게됩니다.

+2

왜'void *'를 원합니까? 'char *' –

+0

새로운 연산자는 동적으로 메모리를 할당하므로 memset이 필요 없다. 일반 데이터 유형의 경우 C++에는 템플 릿이 있습니다. –

+0

부호없는 정수가 2 바이트로 저장되도록 이진 데이터가 필요합니다. char *가 3 자리 숫자에 대해 3 바이트를 차지한다고 생각합니까? – mindreader

답변

2

문제는 컴파일러가 "

a+2 

이 명령으로 무엇을 의미 알고 2 *에 의해 'A'앞으로 포인터를 이동하지 않는다는 것입니다 (sizeof 연산자 --것입니다 - 지적 -에 -에 의해 -'에이')".

a가 void * 인 경우 컴파일러는 대상 객체의 크기를 알지 못하므로 오류가 발생합니다. 컴파일러는 2를 추가하는 방법을 알고,

memcpy(data, ((char *)a)+2, 2); 

이 방법을 - 그것은 sizeof(char) 알고 :

당신은 할 필요가있다.

3

a+2, 포인터가 a 인 경우 포인터는 포인터 유형의 두 항목에 대한 공간을 허용하기 위해 포인터가 증가한 것을 의미합니다. 예를 들어 aint32 * 인 경우 a + 2은 "위치 더하기 8 바이트"를 의미합니다.

void *은 유형이 없으므로 a + 2이 무엇을 의미하는지 추측 할 수 있습니다. 참조되는 유형의 크기를 알지 못하기 때문입니다.

+0

을 보내 주셔서 감사합니다. 나는 정말로 +2 메모리 위치에 관심이있다. 어떻게 액세스 할 수 있습니까? – mindreader

+1

'a '를 바이트 크기의 포인터 (또는 더블 바이트 크기의 포인터를 넣은 다음'1 '만 추가)로 변환하십시오. 분명한 선택은'char'이지만 실제 크기는 플랫폼에 따라 다르므로 확인하십시오. – SJuan76

+2

@mindReader'a + 2 (what ???)'2 바이트? 당신은 명시 적이어야 할 필요가있을 것이다.'char'와'int' 타입은 다른 메모리 공간을 점유하므로 포인터 연산에 의해 반영된다. –

0

잘못된 것이지만 내 이해에 따라 char * 대신 void *를 사용하면 3 자리 숫자로 3 바이트를 차지하게됩니다.

예, 잘못된 숫자입니다. 숫자를 문자로 전송하는 경우에 해당됩니다. 'char *'는 8 비트 값을 참조하는 편리한 방법입니다. 바이트 쌍을 받으면 간단한 메모리를 처리하기 위해 대상 메모리를 처리 할 수 ​​있습니다. 그러나 사람들이 네트워크 데이터 스트림에 'char'배열을 사용하는 것은 꽤 일반적입니다.

BYTE 또는 uint8_t과 같은 문자를 사용하면 char 또는 기타 값과는 반대로 '내가 바이트로 작업하고 있습니다.'라고 분명하게 나타낼 수 있습니다.

void*은 알려지지 않은 더 중요한 것은 0 크기 유형 (void)에 대한 포인터입니다. 크기가 0이기 때문에 오프셋 수학은 0이되므로 컴파일러는 유효하지 않음을 알려줍니다.

솔루션은 네트워크에서 바이트를 바이트 기반 배열로 수신하는 것처럼 간단 할 수 있습니다. int는 32 비트, 4 바이트입니다. 그것들은 "char"값이 아니고 4 바이트 정수의 쿼드입니다.

#include <cstdint> 

uint8_t buffer[4]; 

당신이 버퍼를 작성했습니다 알게되면, 당신은 단순히이 바이트가 네트워크 또는 호스트 순서에 있는지에 따라 달라집니다 올바른지 여부

uint32_t integer = *(static_cast<uint32*>(buffer)); 

을 말할 수있다. 아마 당신이 필요하다고 생각합니다 :

uint32_t integer = ntohl(*(static_cast<uint32*>(buffer)));