나는 현재 C-structs의 정보 숨김 개념과 관련하여 약간 혼란 스럽습니다.
이 질문의 배경은 OOP에 대한 지식이 거의없는 임베디드 c 프로젝트입니다.
지금까지 나는 항상 해당 모듈의 헤더 파일 내에 typedef 구조체를 선언했습니다. 따라서이 구조체를 사용하려는 모든 모듈은 구조체 유형을 알고 있습니다.
그러나 MISRA-C 검사 후 중간 심각도 경고를 발견했습니다. MISRAC2012-Dir-4.8-구조 구현이 불필요하게 번역 단위에 노출됩니다.
약간의 연구 끝에 구조체 멤버의 가시적 액세스를 비공개 범위로 제한하여 C 구조체의 정보 숨김 개념을 발견했습니다.
나는 즉시 다음과 같은 간단한 예를 시도했습니다.
struct_test.h
//struct _structName;
typedef struct _structName structType_t;
struct_test.c
#include "struct_test.h"
typedef struct _structName
{
int varA;
int varB;
char varC;
}structType_t;
main.c
#include "struct_test.h"
structType_t myTest;
myTest.varA = 0;
myTest.varB = 1;
myTest.varC = 'c';
이로 인해 main.c의 경우 myTest의 크기를 알 수 없다는 컴파일러 오류가 발생합니다. 물론 main.c는 structType_t 유형의 구조체가 존재한다는 사실 만 알고 있으며 다른 것은 없습니다.
그래서 연구를 계속했고 불투명 포인터의 개념을 우연히 발견했습니다.
그래서 두 번째 시도를 시도했습니다.
struct_test.h
typedef struct _structName *myStruct_t;
struct_test.c
#include "struct_test.h"
typedef struct _structName
{
int varA;
int varB;
char varC;
}structType_t;
main.c
#include "struct_test.h"
myStruct_t myTest;
myTest->varA = 1;
그리고 컴파일러 오류가 발생합니다. 불완전한 유형에 대한 포인터 역 참조 struct _structName
이 기술의 기본 개념을 이해하지 못했습니다. 내 혼동의 요점은 구조체 객체의 데이터가 어디에 있습니까?
지금까지 포인터가 일반적으로 데이터 유형의 "물리적"표현을 가리키고 해당 주소의 내용을 읽고 / 씁니다.
그러나 위의 방법을 사용하여 myTest 포인터를 선언하지만 가리키는 주소는 설정하지 않습니다.
이 게시물에서 아이디어를 가져 왔습니다. C에서 불투명 포인터 란 무엇입니까?
게시물에서 액세스는 set / get 인터페이스 메서드로 처리된다는 것이 언급되었으므로 다음과 같은 유사한 방법을 추가해 보았습니다.
void setVarA ( _structName *ptr, int valueA )
{
ptr->varA = valueA;
}
그러나 이것은 또한 작동하지 않습니다. 이제 그가 알 수 없다고 말했기 때문에 _structName
... 그래서 추가 인터페이스 메서드의 도움으로 만 구조체에 액세스 할 수 있습니다. 그렇다면 간단한 예제에서 어떻게이 작업을 수행 할 수 있습니까?
그리고 내 구조체의 객체가 메모리에 어디에 있는지 더 큰 질문이 여전히 남아 있습니다. 포인터 개념 만 알고 있습니다.
varA-주소 : 10-값 : 1
ptrA-주소 : 22-값 : 10
하지만이 예에서는
myTest-주소 : xy-값 : ??
해당 myTest
포인터 의 "물리적"표현이 어디에 있는지 이해하는 데 어려움 이 있습니까?
또한 모듈의 생산자이자 소비자 인 비교적 작은 범위의 임베디드 프로젝트에서 이와 같이 수행하는 이점을 볼 수 없습니다.
누군가 1-2 명의 개발자가 코드로 작업하는 중소 규모의 임베디드 프로젝트에이 방법이 정말 합리적인지 설명해 줄 수 있습니까? 현재는 헤더 파일에서 구조체를 선언하는 것보다이 모든 인터페이스 포인터 메서드를 만드는 것이 더 많은 노력처럼 보입니다.
미리 감사드립니다
추론했듯이 이와 같은 불투명 한 유형을 사용할 때 주 소스 파일은 구조체의 멤버에 액세스 할 수 없으며 실제로 구조체가 얼마나 큰지 알지 못합니다. 이 때문에 구조체의 필드를 읽고 쓰기 위해 접근 자 함수가 필요할뿐만 아니라 라이브러리 소스 만 구조체의 정의와 크기를 알고 있기 때문에 구조체에 대한 메모리를 할당하는 함수도 필요합니다.
따라서 헤더 파일에는 다음이 포함됩니다.
typedef struct _structName structType_t;
structType_t *init();
void setVarA(structType_t *ptr, int valueA );
int getVarA(structType_t *ptr);
void cleanup(structType_t *ptr);
이 인터페이스를 사용하면 사용자가 구조체의 인스턴스를 만들고 값을 가져오고 설정하고 정리할 수 있습니다. 라이브러리 소스는 다음과 같습니다.
#include "struct_test.h"
struct _structName
{
int varA;
int varB;
char varC;
};
structType_t *init()
{
return malloc(sizeof(structType_t ));
}
void setVarA(structType_t *ptr, int valueA )
{
ptr->varA = valueA;
}
int getVarA(structType_t *ptr)
{
return ptr->varA;
}
void cleanup(structType_t *ptr)
{
free(ptr);
}
typedef
한 번만 정의 하면됩니다. 이것은 둘 다 유형 별칭을 정의하고 구조체를 앞으로 선언합니다. 그런 다음 소스 파일에서 실제 구조체 정의가 typedef없이 나타납니다.
이 init
함수는 호출자가 구조체에 대한 공간을 할당하고 포인터를 반환하는 데 사용됩니다. 그런 다음 해당 포인터를 getter / setter 함수에 전달할 수 있습니다.
이제 기본 코드에서 다음과 같은 인터페이스를 사용할 수 있습니다.
#include "struct_test.h"
int main()
{
structType_t *s = init();
setVarA(s, 5);
printf("s->a=%d\n", getVarA(s));
cleanup(s);l
}
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다