programing

C에서 강력한 유형 검사 적용(유형 정의에 대한 유형 엄격성)

muds 2023. 7. 5. 21:04
반응형

C에서 강력한 유형 검사 적용(유형 정의에 대한 유형 엄격성)

같은 유형의 형식 정의에 명시적 캐스트를 적용할 수 있는 방법이 있습니까?나는 utf8을 처리해야 하고 가끔 문자 수와 바이트 수에 대한 색인과 혼동이 있습니다.따라서 다음과 같은 유형의 정의를 갖는 것이 좋습니다.

typedef unsigned int char_idx_t;
typedef unsigned int byte_idx_t;

이들 사이에 명시적인 캐스팅이 필요하다는 점을 추가로 들 수 있습니다.

char_idx_t a = 0;
byte_idx_t b;

b = a; // compile warning
b = (byte_idx_t) a; // ok

C에는 그런 기능이 없다는 것을 알지만, 아마도 당신은 그것을 하는 트릭이나 컴파일러 확장자(우선적인 gcc)를 알고 있을 것입니다.


편집 나는 여전히 일반적으로 헝가리 표기법을 별로 좋아하지 않습니다.프로젝트 코딩 규칙 때문에 이 문제에 사용할 수 없었지만, 유형도 같고 의미도 매우 유사한 다른 유사한 경우에 사용했습니다.그리고 저는 인정해야 합니다: 도움이 됩니다.저는 모든 정수를 "i"로 시작하는 것을 절대 선언하지 않을 것입니다. 하지만 Joel의 중복 유형 예에서처럼, 그것은 생명을 구하는 것이 될 수 있습니다.

"핸들" 유형(불투명 포인터)의 경우 Microsoft는 구조를 선언한 다음 구조에 대한 포인터를 입력하는 트릭을 사용합니다.

#define DECLARE_HANDLE(name) struct name##__ { int unused; }; \
                             typedef struct name##__ *name

그럼 대신에

typedef void* FOOHANDLE;
typedef void* BARHANDLE;

그들은 합니다.

DECLARE_HANDLE(FOOHANDLE);
DECLARE_HANDLE(BARHANDLE);

이제, 이것은 작동합니다.

FOOHANDLE make_foo();
BARHANDLE make_bar();
void do_bar(BARHANDLE);

FOOHANDLE foo = make_foo();  /* ok */
BARHANDLE bar = foo;         /* won't work! */
do_bar(foo);                 /* won't work! */   

다음과 같은 작업을 수행할 수 있습니다.

typedef struct {
    unsigned int c_idx;
} char_idx;

typedef struct {
    unsigned int b_idx;
} byte_idx;

그런 다음 각 항목을 사용할 때 확인할 수 있습니다.

char_idx a;
byte_idx b;

b.b_idx = a.c_idx;  

이제 다른 유형이지만 컴파일된다는 것이 더 명확해졌습니다.

원하는 것은 "strong typeef" 또는 "strict typeef"입니다.

일부 프로그래밍 언어(Rust, D, Haskell, Ada, ...)는 언어 수준에서 이를 지원하지만 C[++]는 지원하지 않습니다."불투명 typeef"라는 이름으로 언어에 포함시키자는 제안이 있었지만 받아들여지지 않았습니다.

하지만 언어 지원의 부족은 문제가 되지 않습니다.앨리어싱할 형식을 T형 데이터 멤버가 정확히 1개인 새 클래스로 래핑하면 됩니다.반복의 대부분은 템플릿과 매크로로 해결할 수 있습니다.이 간단한 기술은 직접적인 지원을 받는 프로그래밍 언어에서와 마찬가지로 편리합니다.

보풀을 사용합니다.스플린트 참조:유형강력한 유형 검사.

강력한 유형 검사는 종종 프로그래밍 오류를 나타냅니다.스플린트는 일반 컴파일러(4.1)보다 더 엄격하고 유연하게 원시 C 유형을 검사할 수 있으며 부울 유형(4.2)을 지원합니다.또한 사용자는 정보 숨기기(0)를 제공하는 추상적인 유형을 정의할 수 있습니다.

C에서 컴파일러에 의해 시행되는 사용자 정의 유형 간의 유일한 구별구조체 간의 구별입니다.고유 구조를 포함하는 모든 형식 정의가 작동합니다.당신의 주요 설계 질문은 다른 구조 유형이 동일한 멤버 이름을 사용해야 하는가 하는 것입니다.그렇다면 매크로 및 기타 괴혈병 트릭을 사용하여 일부 다형성 코드를 시뮬레이션할 수 있습니다.그렇지 않다면, 당신은 정말로 두 가지 다른 표현에 전념할 것입니다.예를 들어, 당신은 할 수 있기를 원합니까?

#define INCREMENT(s, k) ((s).n += (k))

및사를 합니다.INCREMENTbyte_idx그리고.char_idx그런 다음 필드의 이름을 동일하게 지정합니다.

당신은 내선 번호에 대해 물었습니다.Jeff Foster의 CQual은 매우 좋고, 저는 그것이 당신이 원하는 일을 할 수 있다고 생각합니다.

C++11을 사용하면 열거형 클래스를 사용할 수 있습니다.

enum class char_idx_t : unsigned int {};
enum class byte_idx_t : unsigned int {};

컴파일러는 두 유형 사이에 명시적 캐스트를 적용합니다. 이는 얇은 래퍼 클래스와 같습니다.불행히도 연산자 오버로드가 발생하지 않습니다. 예를 들어 두 개의 char_idx_t를 함께 추가하려면 서명되지 않은 int에 캐스팅해야 합니다.

만약 당신이 C++를 쓰고 있다면, 당신은 서명되지 않은 int 주위에 랩퍼였던 서로 다른 이름으로 동일하게 정의된 두 개의 클래스를 만들 수 있습니다.저는 C에서 당신이 원하는 것을 할 수 있는 요령을 모릅니다.

BOOST_STRONG_TYPEF에 정의된 대로 strongtypedef 사용

언급URL : https://stackoverflow.com/questions/376452/enforce-strong-type-checking-in-c-type-strictness-for-typedefs

반응형