변수가 C에서 특정 유형(두 유형을 비교)인지 확인하는 방법
C(C++/C#가 아님)에서 변수가 특정 유형인지 확인하는 방법
예를 들어 다음과 같은 것이 있다.
double doubleVar;
if( typeof(doubleVar) == double ) {
printf("doubleVar is of type double!");
}
또는 보다 일반적인 경우:두 가지 유형을 어떻게 비교해서compare(double1,double2)
진실로 평가될 것이다.compare(int,double)
거짓으로 평가될 것이다.또한 다른 구성의 구조도 비교하고 싶다.
기본적으로 나는 "구조 a"와 "구조 b" 유형의 변수에 작용하는 기능을 가지고 있다.나는 "구조 a" 변수와 "구조 b" 변수에 대해 한 가지 일을 하고 싶다.C는 과부하와 과부하를 지원하지 않기 때문에void
포인터 유형 정보가 손실되어 유형을 확인해야 한다.BTW, 어떤 의미일까?typeof
연산자, 유형을 비교할 수 없다면?
방법의 크기가 내게는 실용적인 해결책인 것 같다.도와줘서 고맙습니다.컴파일 시간에 유형이 알려져 있기 때문에 아직은 좀 이상하다고 생각하지만, 내가 볼 수 있는 기계 안의 과정을 상상한다면, 정보가 왜 유형별로 저장되지 않고 바이트 크기로 저장되는가 하는 것이다.주소 말고는 사이즈밖에 없어.
변수의 유형을 얻는 것은 현재 C11에서 가능하다._Generic
총칭 선 발 컴파일 그것은 컴파일 시간에 작동한다.
그 구문은 에 대해 약간 비슷하다.switch
. 여기 (이 답안으로부터) 샘플이 있다.
#define typename(x) _Generic((x), \
_Bool: "_Bool", unsigned char: "unsigned char", \
char: "char", signed char: "signed char", \
short int: "short int", unsigned short int: "unsigned short int", \
int: "int", unsigned int: "unsigned int", \
long int: "long int", unsigned long int: "unsigned long int", \
long long int: "long long int", unsigned long long int: "unsigned long long int", \
float: "float", double: "double", \
long double: "long double", char *: "pointer to char", \
void *: "pointer to void", int *: "pointer to int", \
default: "other")
시간 컴일 시일 시동 수인인인인인인에에에에에에 define define define define 를 정의하면 된다.enum
당신이 기대하는 모든 타입을 가지고, 다음과 같은 것.
enum t_typename {
TYPENAME_BOOL,
TYPENAME_UNSIGNED_CHAR,
TYPENAME_CHAR,
TYPENAME_SIGNED_CHAR,
TYPENAME_SHORT_INT,
TYPENAME_UNSIGNED_CHORT_INT,
TYPENAME_INT,
/* ... */
TYPENAME_POINTER_TO_INT,
TYPENAME_OTHER
};
그리고 나서 사용하라._Generic
여기에 유형을 일치시키다enum
:
#define typename(x) _Generic((x), \
_Bool: TYPENAME_BOOL, unsigned char: TYPENAME_UNSIGNED_CHAR, \
char: TYPENAME_CHAR, signed char: TYPENAME_SIGNED_CHAR, \
short int: TYPENAME_SHORT_INT, unsigned short int: TYPENAME_UNSIGNED_SHORT_INT, \
int: TYPENAME_INT, \
/* ... */ \
int *: TYPENAME_POINTER_TO_INT, \
default: TYPENAME_OTHER)
C는 이러한 형태의 자기반성을 지원하지 않는다.당신이 묻고 있는 것은 C에서는 가능하지 않다(적어도 컴파일러별 확장이 없다면 C++에서는 가능하겠지만).
일반적으로 C를 사용하면 변수의 유형을 알 수 있을 것으로 예상된다.모든 함수에는 매개변수에 대한 구체적인 유형이 있으므로(바라크, 내 생각엔) 함수 본체를 체크 인할 필요가 없다.내가 볼 수 있는 유일한 경우는 거시적인 몸 안에 있는 것 뿐이고, 음, C 매크로가 그렇게 강력하지는 않아.
또한 C는 런타임에 어떠한 유형 정보도 보유하지 않는다는 점에 유의한다.즉, 가정적으로 유형비교 연장이 있었다고 해도, 컴파일 시간에 유형이 알려져 있을 때만 제대로 작동한다는 것이다(즉, 두 가지가 맞는지 시험하는 것은 효과가 없을 것이다).void *
동일한 유형의 데이터를 가리킴).
에 관하여typeof
: 먼저typeof
GCC 확장자야그것은 C의 표준적인 부분이 아니다.일반적으로 (GCC 매뉴얼에서) 자신의 주장을 한 번만 평가하는 매크로를 작성하는 데 사용된다.
#define max(a,b) \
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })
그typeof
키워드는 매크로가 인수의 값을 저장하기 위한 로컬 임시 값을 정의하여 한 번만 평가할 수 있도록 한다.
요컨대 C는 과부하를 지지하지 않고, 단지 과부하만 하면 된다.func_a(struct a *)
그리고func_b(struct b *)
, 그리고 정확한 것을 불러라.또는, 당신은 당신만의 자기성찰 시스템을 만들 수 있다.
struct my_header {
int type;
};
#define TYPE_A 0
#define TYPE_B 1
struct a {
struct my_header header;
/* ... */
};
struct b {
struct my_header header;
/* ... */
};
void func_a(struct a *p);
void func_b(struct b *p);
void func_switch(struct my_header *head);
#define func(p) func_switch( &(p)->header )
void func_switch(struct my_header *head) {
switch (head->type) {
case TYPE_A: func_a((struct a *)head); break;
case TYPE_B: func_b((struct b *)head); break;
default: assert( ("UNREACHABLE", 0) );
}
}
물론 이러한 객체를 만들 때는 헤더를 올바르게 초기화해야 한다.
Gnu GCC에는 유형 비교를 위한 기능이 내장되어 있다.__builtin_types_compatible_p
.
https://gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc/Other-Builtins.html
이 내장 함수는 형식 1과 형식 2의 부적격 버전(표현이 아닌 형식)이 호환되면 1을 반환하고, 그렇지 않으면 0을 반환한다.이 내장 함수의 결과는 정수 상수 식에 사용할 수 있다.
이 내장 기능은 최상위 한정자(예: 항상성, 휘발성)를 무시한다.예를 들어, int는 const int와 동등하다.
예제에서 사용:
double doubleVar;
if(__builtin_types_compatible_p(typeof(doubleVar), double)) {
printf("doubleVar is of type double!");
}
언급된 또 다른 답변으로, C11에서 다음과 같이 할 수 있다._Generic
.
예를 들어, 일부 입력이 다른 유형과 호환되는지 확인하는 매크로가 있다.
#include <stdbool.h>
#define isCompatible(x, type) _Generic(x, type: true, default: false)
다음과 같이 매크로를 사용할 수 있다.
double doubleVar;
if (isCompatible(doubleVar, double)) {
printf("doubleVar is of type double!\n"); // prints
}
int intVar;
if (isCompatible(intVar, double)) {
printf("intVar is compatible with double too!\n"); // doesn't print
}
이것은 구조체를 포함한 다른 유형에도 사용될 수 있다.예시
struct A {
int x;
int y;
};
struct B {
double a;
double b;
};
int main(void)
{
struct A AVar = {4, 2};
struct B BVar = {4.2, 5.6};
if (isCompatible(AVar, struct A)) {
printf("Works on user-defined types!\n"); // prints
}
if (isCompatible(BVar, struct A)) {
printf("And can differentiate between them too!\n"); // doesn't print
}
return 0;
}
그리고 타이페이에.
typedef char* string;
string greeting = "Hello world!";
if (isCompatible(greeting, string)) {
printf("Can check typedefs.\n");
}
하지만, 그것이 항상 당신이 기대하는 답을 주는 것은 아니다.예를 들어, 배열과 포인터를 구별할 수 없다.
int intArray[] = {4, -9, 42, 3};
if (isCompatible(intArray, int*)) {
printf("Treats arrays like pointers.\n");
}
// The code below doesn't print, even though you'd think it would
if (isCompatible(intArray, int[4])) {
printf("But at least this works.\n");
}
여기에서 빌린 답변: http://www.robertgamble.net/2012/01/c11-generic-selections.html
/*
* Check at compile time that something is of a particular type.
* Always evaluates to 1 so you may use it easily in comparisons.
*/
#define typecheck(type,x) \
({ type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
1; \
})
여기에서 표준의 문장과 코드 위의 GNU 확장이 사용하는 설명을 찾을 수 있다.
(문제는 유형 불일치에 대한 실패에 관한 것이 아니기 때문에, 아마도 약간은 질문의 범위에 있지 않을 것이다. 그러나 어쨌든, 여기에 남겨두어라.)
다른 사람들이 이미 말했듯이 이것은 C언어에서는 지원되지 않는다.그러나 다음 명령을 사용하여 변수의 크기를 확인할 수 있다.sizeof()
는 두 할 수 하는 데 이 될 수 이렇게 하면 두 변수가 동일한 유형의 데이터를 저장할 수 있는지 여부를 확인하는 데 도움이 될 수 있다.
그러기 전에 아래 댓글을 읽어보십시오.
다른 사람들이 언급했듯이, 당신은 런타임에 변수의 유형을 추출할 수 없다.그러나, 당신은 당신 자신의 "객체"를 구성하고 그것과 함께 유형을 저장할 수 있다.그러면 런타임에 확인할 수 있을 것이다.
typedef struct {
int type; // or this could be an enumeration
union {
double d;
int i;
} u;
} CheesyObject;
그런 다음 코드에서 필요에 따라 유형을 설정하십시오.
CheesyObject o;
o.type = 1; // or better as some define, enum value...
o.u.d = 3.14159;
이건 미친 짓이야 하지만 만약 네가 코드를 사용한다면:
fprintf("%x", variable)
그리고 컴파일할 때 -Wall 플래그를 사용하면 gcc가 '____' 형식의 인수에 '부호화되지 않은 int'의 인수를 예상한다는 경고를 발한다(이 경고가 나타나지 않으면 변수는 '부호화되지 않은 int' 유형임).
행운을 빈다!
편집: 아래에 언급된 바와 같이, 이것은 컴파일 시간에만 적용된다.여러분의 포인터가 왜 작동하지 않는지 알아내려고 할 때 매우 유용하지만, 런타임 동안 필요하다면 그다지 유용하지 않다.
C는 정적으로 입력된 언어다.A형이나 B형에서 동작하는 함수를 선언할 수 없고, A형이나 B형을 가지고 있는 변수를 선언할 수 없다.모든 변수는 명시적으로 선언되고 변경할 수 없는 유형을 가지며, 당신은 이 지식을 사용해야 한다.
그리고 void *가 float 또는 정수의 메모리 표현을 가리키는지 알고 싶을 때는 이 정보를 다른 곳에 저장해야 한다.이 언어는 char *가 int 또는 char로 저장된 것을 가리켜도 상관하지 않도록 특별히 고안되었다.
그 목적으로 나는 그것을 위한 간단한 C 프로그램을 작성했다...그것은 기투브에 있다...깃허브 링크
여기 어떻게 작동하는지...먼저 당신의 더블을 s라는 이름의 char string으로 변환하십시오.
char s[50];
sprintf(s,"%.2f", yo);
그럼 내 것을 써라.dtype
유형 결정 기능...내 기능은 단 하나의 문자를 돌려줄 것이다...이렇게 쓰면 되잖아...
char type=dtype(s);
//Return types are :
//i for integer
//f for float or decimals
//c for character...
그럼 비교해서 확인하면 되겠네...바로 그거야...
가능한 한 가지 방법은 변수 이름이 변수 정의 앞에 유형 정보를 포함하도록 하는 것이다.
Ex: 모든 정수는 i_ 모든 부유물은 f_ 등을 가질 것이다.
변수 이름은 #<variable_name>, This를 통해 가져올 수 있다.
'programing' 카테고리의 다른 글
Nuxt.js의 중첩된 경로에 선택적 파라미터를 생성하는 방법? (0) | 2022.05.06 |
---|---|
공유 호스팅 환경에서 vue 앱을 배포하는 방법? (0) | 2022.05.06 |
Java에서 코어 수 찾기 (0) | 2022.05.06 |
Java에서 동기화되지 않도록 하시겠습니까? (0) | 2022.05.06 |
SID 대신 서비스 이름을 사용하여 Oracle에 연결하는 방법 (0) | 2022.05.06 |