C에서 어떤 사람들은 포인터를 해제하기 전에 포인터를 던지는 이유는 무엇입니까? 예를 들어 free((float *)velocity); free((float *)acceleration); free((char *)label); 여기서

나는 오래된 코드베이스에서 일하고 있으며 free ()의 모든 호출은 인수에 캐스트를 사용합니다. 예를 들어

free((float *)velocity);
free((float *)acceleration);
free((char *)label);

여기서 각 포인터는 해당하는 (및 일치하는) 유형입니다. 나는 이것에 전혀 아무런 의미가 없다. 매우 오래된 코드이므로 K & R인지 궁금합니다. 그렇다면 실제로이를 필요로했던 오래된 컴파일러를 지원하고 싶기 때문에 제거하고 싶지 않습니다.

이 캐스트를 사용해야하는 기술적 이유가 있습니까? 나는 그것들을 사용해야 할 실용적인 이유를 많이 보지 못합니다. 데이터 유형을 해제하기 직전에 상기시키는 것이 요점은 무엇입니까?

편집 :이 질문은 다른 질문과 중복 되지 않습니다 . 다른 질문은이 질문의 특별한 경우입니다. 가까운 유권자들이 모든 답을 읽을 것인지는 분명합니다.

Colophon : 이것이 “const answer”에 체크 표시를하는 이유는 이것이 실제적인 이유이기 때문입니다. 그러나 (ANSI C 이전의 관습) (적어도 일부 프로그래머 중 하나)에 대한 대답은 그것이 내 경우에 사용 된 이유 인 것 같습니다. 많은 사람들의 좋은 점이 많습니다. 기부 해 주셔서 감사합니다.



답변

포인터가 인 경우 컴파일러 경고를 해결하기 위해 캐스팅이 필요할 수 있습니다 const. 다음은 free 인수를 캐스트하지 않고 경고를 발생시키는 코드 예제입니다.

const float* velocity = malloc(2*sizeof(float));
free(velocity);

그리고 컴파일러 (gcc 4.8.3)는 말합니다 :

main.c: In function main’:
main.c:9:5: warning: passing argument 1 of free discards const qualifier from pointer target type [enabled by default]
     free(velocity);
     ^
In file included from main.c:2:0:
/usr/include/stdlib.h:482:13: note: expected void *’ but argument is of type const float *’
 extern void free (void *__ptr) __THROW;

free((float*) velocity);컴파일러 를 사용 하면 불평이 중지됩니다.


답변

사전 표준 C는 전혀 없었다 void*하지만 char*당신이 전달 된 모든 매개 변수를 캐스팅했다, 그래서. 고대 C 코드를 발견하면 그러한 캐스트를 찾을 수 있습니다.

참고 자료와 비슷한 질문 .

첫 번째 C 표준이 발표되었을 때, malloc을 무료로 프로토 타입이 가진 변경 char*받는 void*그들은 여전히 오늘이 있는지 확인하십시오.

물론 표준 C에서는 그러한 캐스트가 불필요하고 가독성에 해를 끼칩니다.


답변

다음은 캐스트없이 free가 실패하는 예입니다.

volatile int* p = (volatile int*)malloc(5 * sizeof(int));
free(p);        // fail: warning C4090: 'function' : different 'volatile' qualifiers
free((int*)p);  // success :)
free((void*)p); // success :)

C에서는 경고가 표시 될 수 있습니다 (VS2012에 경고가 표시됨). C ++에서는 오류가 발생합니다.

드문 경우를 제외하고 캐스팅은 코드를 부풀려 버립니다 …

편집 :
나는 실패를 시연 void*하지 않기 int*위해 캐스팅했다 . int*로 변환 되는 것과 동일하게 작동합니다.void*암시 적 . int*코드가 추가되었습니다 .


답변

오래된 이유 : 1.를 사용 free((sometype*) ptr)하면 코드가 포인터가 free()호출의 일부로 간주되어야하는 유형에 대해 명시 적 입니다. 명시 적 캐스트는 free()(do-it-yourself)로 대체 될 때 유용합니다 DIY_free().

#define free(ptr) DIY_free(ptr, sizeof (*ptr))

A DIY_free()는 (특히) 디버그 모드에서 해제되는 포인터의 런타임 분석을 수행하는 방법입니다. 이것은 종종DIY_malloc() 문장과 전체 메모리 사용 횟수 등을 추가 위해 . 우리 그룹은 더 현대적인 도구가 나타나기 전에이 기술을 몇 년 동안 사용했습니다. free’d 된 아이템이 타입으로 캐스팅 된 것은 원래 할당 된 것입니다.

  1. 메모리 문제 등을 추적하는 데 많은 시간이 소요되었으므로 free typed 캐스팅과 같은 작은 트릭은 디버깅을 검색하고 좁히는 데 도움이됩니다.

최신 : Manos Nikolaidis @@egur가 해결 한 경고 constvolatile경고 . 나는 3 개의 효과에 유의 것이라고 생각 예선 : , , 및constvolatilerestrict .

[편집] @R .. 코멘트char * restrict *rp2 당 추가

void free_test(const char *cp, volatile char *vp, char * restrict rp,
    char * restrict *rp2) {
  free(cp);  // warning
  free(vp);  // warning
  free(rp);  // OK
  free(rp2);  // warning
}

int main(void) {
  free_test(0,0,0,0);
  return 0;
}


답변

또 다른 대안 가설이 있습니다.

우리는 프로그램이 그것의 프로토 타입 불일치의 어떤 종류의 주위에 작동하지 않을 수 있다는 것을 의미 사전 C89, 기록 된 것으로 전해지고 있습니다 free만 아니었다 때문에를,이 같은 것은 없기 때문에 constvoid *, 같은 것은 거기 없었다 이전 C89에 C89 이전 의 함수 프로토 타입 stdlib.h그 자체가위원회의 발명이었다. 시스템 헤더 free가 전혀 선언 하지 않으면 다음과 같이했을 것입니다.

extern free();  /* no `void` return type either! */

여기서 핵심은 함수 프로토 타입이 없다는 것은 컴파일러가 인자 타입 검사를 하지 않았다는 것을 의미합니다 . 기본 인수 프로모션 (Variadic 함수 호출에 여전히 적용되는 것과 동일한 프로모션)을 적용했으며 그 결과였습니다. 각 호출 사이트에서 인수를 작성하는 책임은 수신자의 기대 와 일치하며 전적으로 프로그래머에게 있습니다.

그러나 이것이 여전히 free대부분의 K & R 컴파일러 에서 인수를 제출해야한다는 의미는 아닙니다 . 같은 기능

free_stuff(a, b, c)
    float *a;
    char *b;
    int *c;
{
    free(a);
    free(b);
    free(c);
}

올바르게 컴파일되었습니다. 그래서 우리가 여기에 가지고있는 것은 비정상적인 환경, 예를 들어 sizeof(float *) > sizeof(int)컴파일러 가 그렇지 않은 환경에 대한 버그가있는 컴파일러에 대처하기 위해 작성된 프로그램이라고 생각합니다. 당신이 시점에서 그들을 캐스팅하지 않는 포인터에 대한 적절한 호출 규칙을 사용합니다 전화

나는 그러한 환경을 알고 있지 않지만 그것이 존재하지 않았다는 것을 의미하지는 않습니다. 가장 유망한 후보는 1980 년대 초 8 비트 및 16 비트 마이크로를위한 “작은 C”컴파일러입니다. 또한 초기 크레이 (Crays) 초기에 이와 같은 문제가 있다는 것을 알고 놀랄 일이 아닙니다.


답변

free는 비 const 포인터 만 매개 변수로 사용합니다. 따라서 const 포인터의 경우 비 const 포인터에 대한 명시 적 캐스트가 필요합니다.

C에서 const 포인터를 해제 할 수 없습니다


답변