2011-04-05 2 views
7

안녕하세요, C에서 void *를 일반적인 데이터 형식으로 사용하려고합니다. 내가 원하는 것은 무엇이든 저장할 수 있고 무엇이든 사용할 수있는 메커니즘입니다. 나는 약간의 코드를 작성했지만, 마지막 경우에는 실패하고있다. 아무도 코드를 살펴볼 수 있습니까? 다른 생각이 있다면 알려주세요.C의 일반적인 데이터 형식 [void *]

나는 무엇을 저장하려고하는지 알기 때문에 그 시점에서 데이터 유형을 알고 있지만 재 시도 중에는 시작 주소와 크기 만 알고 있습니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <assert.h> 


static void store(void *destination, void *source, size_t size) { 
    memcpy ((char*)destination, source, size); 
} 
static void retrieve (void *destination, void *source, size_t size) { 
    memcpy (destination, (char*)source, size); 
} 

void *storage_char_ptr = (void*) malloc (sizeof(char*)); 
void *storage_int_ptr = (void*) malloc (sizeof(int*)); 
void *storage_int  = (void*) malloc (sizeof(int)); 

int main() { 

    int int_in = 65; 
    void *int_out_ptr; 
    int *ptr = (int*) malloc (sizeof(int)); 
    memcpy (ptr, &int_in, sizeof(int)); 

    store (storage_int_ptr, &ptr, sizeof(int*)); 
    retrieve (&int_out_ptr, storage_int_ptr, sizeof(int*)); 
    assert (int_in == *(int*)int_out_ptr); 

    char *char_in = "HelloWorld!!"; 
    void *char_out; 
    store (storage_char_ptr, &char_in, sizeof(char*)); 
    retrieve (&char_out, storage_char_ptr, sizeof(char*)); 
    assert (strcmp (char_in, (char*)char_out) == 0); 

    char_in = _strdup("HelloWorld!!"); 
    store (storage_char_ptr, &char_in, sizeof(char*)); 
    retrieve (&char_out, storage_char_ptr, sizeof(char*)); 
    assert (strcmp (char_in, (char*)char_out) == 0); 

    /* This is where it is failing */ 
    int_in = 55; 
    void* int_out; 
    store (storage_int, &int_in, sizeof(int)); 
    retrieve (&int_out, storage_int, sizeof(int)); 
    assert (55 == *(int*)int_out); 

} 
+2

어떻게 실패합니까? – MByD

답변

9

void* 대신에 필요한 모든 유형의 합집합을 선택한 유형의 열거 형과 함께 사용하는 것이 훨씬 좋습니다. 형식의 유한 목록이 없으면 최소한 void* 포인터와 크기가 할당 된 구조체를 사용하십시오.예를 들어

는 :

struct ANYTYPE 
{ 
    enum { 
     typUndefined, 
     typInt,   // 1 
     typUint, 
     typString, 
     typByteString, 
     typLong,   // 5 
     typFloat, 
     typDouble, 
    } iType; 

    void* value; 
}; 

이 쉽게 정확하게 메모리를 할당 해제하고 값에 작용하기 전에 유형을 분석 할 수 있습니다 일반적인 코드를 만들 수 있습니다. 당신은 조합과 비슷한 옵션이 있습니다 모든 요소가 동일한 메모리 공간을 사용하고 하나가 액세스해야, 노동 조합에서

struct ANYTYPE 
{ 
    enum { 
     typUndefined, 
     typInt,   // 1 
     typUint, 
     typString, 
     typLong 
    } iType; 

    union 
    { 
     int i; 
     unsigned int u; 
     char* s; 
     long l; 
    } value; 
} 

합니다. 열거를 통해 어떤 요소에 액세스해야하는지 알 수 있습니다. 물론 C++처럼 OO 보호 기능이 없으므로이 구조체를 사용하는 모든 곳에서 열거 형을 올바르게 설정해야합니다.

+0

@Benoit Thiery, 설명해 주시겠습니까? 나는 구조체 솔루션에 intrested입니다. – Avinash

+0

감사합니다 Benoit,하지만 형식의 유한 목록이 있으므로 구조체 접근 방식에 대해 더 자세히 설명해주십시오. – Avinash

+0

@Avinash, 유형의 유한 목록이 있더라도 유니온은 여전히 ​​좋습니다. 공용체는 구조체와 거의 같습니다. –

5

당신은 포인터 int_out에 정수 값 (55) 복사 : 여기

는 코드입니다. (에서 다음 4 ~ 8 바이트)에서 무엇이든 거짓말은 55를 해결, 대신 숫자 값 (55)을 가질 가능성이, 당신의 코드를

int int_in = 55; 
int int_out; 
store (storage_int, &int_in, sizeof(int)); 
retrieve (&int_out, storage_int, sizeof(int)); 
assert (55 == int_out); 

또 다른 문제를 시도해보십시오 char_in/char_out 부분에서, 당신이 포인터 값만 복사합니다. 이것은 (이 경우) 작동하지만, 실제로 의도 한 것이 아닌가? 그렇지 않습니까? 당신이 정말로 포인터를 저장하려면, 당신은 storeretrieve 부분을 건너 뛸 수 있습니다 :

char* str_in = "hello, world";  // Original value 
void* generic_ptr = str_in;  // ... a pointer to which is stored in some data structure 
char* str_out = generic_ptr;  // ... which can later be retrieved 

은 잘 작동합니다. 반면에 문자열의 실제 내용을 저장하려면 두 번째 예제에서와 같이 _strdup과 같이 복사해야하며 사본 사본 문자열

으로 저장해야합니다.
char* str_in = _strdup("copy me"); 
void* generic_ptr = str_in;   // Gets stored in your data structures 
4

포인터를 덮어 쓰고 역 참조 해제하면 ... 코드가 이렇게 생겼을 때 포인터가 작동하는 것처럼 보이지만 그 포인터가 뒤를 쫓을 수는 없습니다.

int int_out; 
    store (storage_int, &int_in, sizeof(int)); 
    retrive (&int_out, storage_int, sizeof(int)); 
    assert (55 == int_out); 

나 : 당신이있어 모두 'INT'그 'INT *'같은 크기, 그래서 가정하기 때문에

int *int_out; 
    store (storage_int, &int_in, sizeof(int)); 
    retrive (&int_out, storage_int, sizeof(int)); 
    assert (55 == (int)int_out); 

그러나, 두 번째 경우에 이것은 조금 반신 반의입니다 검색 할 때 다른 것을 위에 저장할 수 있습니다. 나는 이것이 모든 시스템에 해당하지 않는다고 생각합니다.

1

더크는 완전히 맞습니다. 이 표현하는 또 다른 방법에 검색된 데이터를 입력하기 위해 할당 공백이 없다는 것입니다

시도 :.

물론
int_in = 55; 
void* int_out = malloc (sizeof (int_in)); 
store (storage_int, &int_in, sizeof(int)); 
retrieve (int_out, storage_int, sizeof(int)); 
assert (55 == *(int*)int_out); 

, 당신이 malloc을 이외의()를 사용하고자하고 있습니다 malloc()이 실패했는지 알기위한 검사가 없지만, 이것이 올바른 방향으로 나아갈 것입니다.

관련 문제