문제

내부 버퍼에 대한 포인터를 반환하는 액세스 함수를 작성하고 있으며 내 기능을 사용자에게 지적한 객체를 업데이트해서는 안된다는 것을 힌트하고 싶습니다. 매우 고안된 예는 다음과 같습니다.

void myAccessFunc(bool string, void* p, size_t* len)
{
  static const char* s = "aha!";
  static const int i = 123;

  if (string) {
     *(char**)p = &s;
     *len = strlen(s);
  }
  else {
     *(int**)p = &i;
     *len = sizeof(i);
  }
}

char* s;
size_t bytes;
myAccessFunc(true,&s, &bytes);
printf("Got '%s'\n", s);

그렇습니다.

내가 예방하고 싶은 것은 다음과 같습니다.

char* s;
size_t bytes;
myAccessFunc(true,&s,&bytes);
s[4] = '?';

나는 그것을 완전히 막을 수 없다는 것을 알고 있지만 적어도 컴파일러 경고가 사용자에게 그렇게해서는 안된다는 것을 암시하는 것을 좋아합니다. 그들이 내 포인터를 던지면 그것이 그들의 문제입니다. const와 void와 *의 조합이 있습니까? 나는 다음과 같은 것을 시도했다.

void myAccessFunc(bool string, const void** p, size_t* len);

그러나 그것은 포인터의 공허함을 없애는 것처럼 보였으므로 발신자는해야합니다.

const void* p;
size_t bytes;
myAccessFunc(true, &p, &bytes);

또는

const char* s;
size_t bytes;
myAccessFunc(true, (const void**)&s, &bytes);

그리고 할 수 없었습니다 :

const int * ip;
const char* s;
size_t bytes;
myAccessFunc(true, &s, &bytes);
myAccessFunc(false, &i, &bytes);

나는 마침내 주변에왔다 :

const void* myAccessFunc(bool string, size_t* len);

그리고 사용자가하는 경우 :

char* p = myAcccessFunc(true,&bytes);

컴파일러 (적어도 GCC)는 예선을 버리는 것에 대해 불평합니다.

도움이 되었습니까?

해결책

다음과 같은 일을하는 것이 가장 좋습니다.

const void * myAccessFunc();

포인터를 내부에 반환하는 경우, 이것은 아웃 매개 변수로 전달하는 것보다 조금 더 자연 스럽습니다.

Out 매개 변수로 전달하려면 다음을 원할 것입니다.

void myAccessFunc(const void **p);

우연히이 작업을 수행하지 못하게합니다.

void *p;  /* error: must be 'const void *p;' */
myAccessFunc(&p);

다른 팁

당신은 당신이 할 수있는 두 가지 일이 있습니다 :

  • const void* 반환*
  • 반환 된 값을 수정하지 말라고 사용자에게 알리는 API에 대한 문서 작성

그렇게 말하면, 포인터로 시도하고 뭉치려고 결정한 API 사용자는 그들이 얻는 것을받을 자격이 있습니다. p.

콘트로스를 던질 수 있기 때문에 예방은 불가능합니다. 함수 매개 변수를 const로 만들면 기능 안에 직접 캐스트해야합니다. 당신은 또한 당신의 기능을 사용하는 사람에게 거짓말을하고 있으며 모든 종류의 재미 버그를 유발할 수 있습니다.

대신 포인터를 반환 할 수 있습니다. 그런 다음 적어도 자신의 Const를 위반하지 않을 것입니다. 그러나이 경우에는 적합하지 않을 수 있습니다.

포인터를 반환하는 것이 가장 좋지만 물론 아웃 매개 변수를 만들어야합니다. 구조물을 중개자로 사용할 수 있습니다.

typedef struct _ptr_holder {
   const void* ptr;
} ptr_holder;

void myAccessFunc( bool string, ptr_holder* ptr ) {
...
}

ptr_holder s;
myAccessFunc(true,&s);
printf("Got '%s'\n", s.ptr);

호키이지만 트릭을해야합니다

그렇다면 반환 포인터를 통해 수정을 방지하고 싶습니까? 이 시도:

const void* myAccessFunc(bool string);

이것에 무슨 문제가 있습니까? 유효한 답변에 투표하려면 의견을 남겨주세요.

내부 데이터 구조를 노출시키고 싶지 않은 C 라이브러리를 작성하는 경우 추가로 이동하는 것이 좋습니다. 노선 지정되지 않은 구조물 typedef로 구현을 숨기십시오. 이것을 an이라고도합니다 불투명 한 유형

예시:

~ 안에 my_interface.h

 #ifndef __MYINTERFACE_H__
 #define __MYINTERFACE_H__

 /* The unspecified struct statement */
 typedef struct s_my_data t_my_data;

 t_my_data  *new_my_data(int someInitializer);
 void        free_my_data(t_my_data *data);
 int         enter_my_data(t_my_data *data, int someDataToEnter);

 const char *return_str_my_data(t_my_data *data);

 #endif /* __MYINTERFACE_H__ */



~ 안에 my_interface.c

 #include <my_interface.h>

 /* Keep struct in .c file */
 struct s_my_data {
     int    length;
     char  *string;
 };

 t_my_data *new_my_data(int someInitializer)
 {
     /* the exercise */
 }

 void free_my_data(t_my_data *data)
 {
     /* the exercise */
 }

 int enter_my_data(t_my_data *data, int someDataToEnter)
 {
     /* the exercise */
 }

 const char *return_str_my_data(t_my_data *data)
 {
     /* the exercise */
 }

이것은 C 또는 C ++입니까? int 케이스에서 포인터를 정적 Const에 전달하는 이유는 무엇입니까? 인터페이스는 용의자입니다.

인터페이스에서 과부하 및 부울을 제거하십시오.

void myAccessFunc( const char* * const p, size_t* len){
   *p = "blahblahblah";
   *len = 12;
}

void myAccessFunc( const int* * const ppI, size_t* len){
   static const int i = 123;
   *ppI = &i;
   *len = 4;
}

테스트도 제거합니다. 사용자는 원래 기능에 대해 True 또는 False를 알고 있으므로 어느 기능을 사용할 것인지 알고 있습니다. 강력한 타이핑은 당신의 친구입니다. 유형과 포인터가 일치하지 않는 오류 클래스를 제거합니다 ...

BTW는 이러한 제어 플래그와 과부하를 통과하는 것이 바람직하지 않으며, 특히 작은 방법으로는 바람직하지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top