, C++ 또는 C 함께 일하고
은 당신이 포인터의 유형을 알 방법이 없습니다.
이 문제를 해결하는 일반적인 방법은 포인터가 구조체를 가리키게하고 구조체의 알려진 위치에 데이터 형식을 나타내는 것입니다. 일반적으로 알려진 위치는 구조체의 첫 번째 위치입니다.
예 :
// signature value; use any value unlikely to happen by chance
#define VAR_SIG 0x11223344
typedef enum
{
vartypeInvalid = 0,
vartypeInt,
vartypeFloat,
vartypeDouble,
vartypeString,
vartypeMax // not a valid vartype
} VARTYPE;
typedef struct
{
VARTYPE type;
#ifdef DEBUG
uint32_t sig;
#endif // DEBUG
union data
{
int i;
float f;
double d;
char *s;
};
} VAR;
당신은 다음 전성 검사를 수행 할 수 있습니다 type
필드가 vartypeInvalid
미만 vartypeMax
보다 큰 값이 있는지를 알 수 있습니다 (당신은에서 그 이름을 편집 할 필요가 없습니다 것입니다 청결성 체크 코드를 입력하고, 더 많은 유형을 추가하면 목록에 vartypeMax
앞에 추가합니다. 또한 DEBUG
빌드의 경우 서명 필드 sig
에 특정 서명 값이 포함되어 있는지 확인할 수 있습니다. (즉, 초기화 코드 VAR
인스턴스는 항상 sig
필드를 설정해야합니다.)
이렇게하면 초기화하는 방법은 무엇입니까? 런타임 코드는 항상 작동합니다 :
VAR v;
#ifdef DEBUG
v.sig = VAR_SIG;
#endif // DEBUG
v.type = vartypeFloat;
v.data = 3.14f;
컴파일 타임에 초기화 하시겠습니까?
VAR v =
{
vartypeInt,
#ifdef DEBUG
VAR_SIG,
#endif // DEBUG
1234
};
당신이 C의 C99 호환 버전을 사용하는 경우, 당신이 실제로 가진 구조체를 초기화 할 수 있습니다 : 당신은 정수 값을 초기화 할 경우 int
유형이 union
의 첫 번째 유형이 있기 때문에, 쉽게 필드 이름을 지정하고 모든 유형을 지정하십시오. 그러나 Microsoft C는 C99과 호환되지 않으므로 float
또는 double
값으로 구조체를 초기화하려는 경우 위의 사항은 악몽입니다.float 값을 정수로 변환하면 C는 유형을 변경하는 것이 아니라 값을 반올림하고 32 비트 정수 값을 올바르게 나타내는 32 비트 정수 값을 이식 할 수있는 트릭이 없습니다. C 프로그램의 컴파일시에 떠.)
Compile time float packing/punning
당신이 포인터로 작업하는 경우,하지만, 그건 간단합니다. 유니온의 첫 번째 필드 이름을 포인터 유형으로 만들고, 포인터를 void *
으로 캐스팅하고 위와 같이 구조체를 초기화하십시오. 포인터는 1234
이 위를 차지하는 곳으로 갈 것입니다.
타인의 코드로 작성된 테이블을 읽고 유형 식별자 필드를 추가 할 방법이없는 경우 일반적인 대답이 없습니다. 나는 당신이 다른 타입으로 포인터를 읽는 것을 시도 할 수 있었고, 어떤 것이 작동하는지 볼 수있을 것 같아요?
'char a = * (char *) 0x8c334dd;' – ouah
내 가정은 포인터를 역 참조하는 것이 여기에서 작동하지 않는다는 것입니다. 왜냐하면 주소가있는 변수를 역 참조하면 그것은 두 번째 변수의 내용이 아니라 콘텐츠 (동일한 주소 임)가 될 것입니다. 맞습니까? 또한 데이터를 가져 오려는 변수의 유형이 무엇인지 모르겠다. – attis
응? "두 번째 변수"는 무엇입니까? 포인터를 역 참조하는 경우 해당 주소에 저장된 내용을 가져옵니다. (또한 C 질문 인 경우 왜 C++ 태그가 붙습니까?) –