malloc의 결과를 캐스트합니까?


2407

에서 이 질문에 , 누군가가에서 제안 코멘트 내가해야 하지 의 결과 캐스트 malloc, 즉

int *sieve = malloc(sizeof(int) * length);

오히려

int *sieve = (int *) malloc(sizeof(int) * length);

왜 이런 경우입니까?


222
또한 sieve = malloc (sizeof * sieve * length);
William Pursell


3
여기에 대한 답변은 일방적 인 지뢰밭입니다. 대답은 "의존"입니다. 프로그램을 작동시키는 데 필요한 것은 아닙니다. 그러나 일부 코딩 표준에는 필요합니다 ... 예를 들어 CERT C 코딩 표준
Dr. Person Person II

이상하게도, 모두가 당신이 캐스팅하지 않는다는 데 동의합니다 NULL. (이것이 아마도 C ++이 도입 한 이유 일 것입니다 nullptr. C ++은 암시 적 포인터 캐스트를 허용하지 않습니다)
Sapphire_Brick

할 수는 있지만 반드시 할 필요는 없습니다. 그러나 C ++로해야합니다.
신체 없음

답변:


2217

아니 ; 다음과 같은 이유로 결과를 캐스트 하지 않습니다 .

  • void *이 경우 다른 포인터 유형으로 자동으로 안전하게 승격 되므로 불필요 합니다.
  • 코드에 혼란을 더하고 캐스트는 읽기가 쉽지 않습니다 (특히 포인터 유형이 긴 경우).
  • 그것은 당신이 자신을 반복하게 만듭니다.
  • 포함하지 않은 경우 오류를 숨길 수 있습니다 <stdlib.h>. 이로 인해 충돌이 발생할 수 있습니다 (또는 코드의 완전히 다른 부분에서 나중에 충돌이 발생 하지 않음 ). 포인터와 정수의 크기가 다른 경우 어떻게되는지 고려하십시오. 전송하면 경고를 숨기고 반환 된 주소의 비트가 손실 될 수 있습니다. 참고 : C99 기준으로 암시 적 함수는 C에서 사라졌으며 선언되지 않은 함수가 반환한다는 자동 가정이 없으므로이 시점은 더 이상 관련이 없습니다 int.

해명으로, 노트 내가 말한 것이 아니라 "당신은하지 않는다"당신은 캐스팅하지 않는다 " 필요 캐스트에". 제 생각에는 캐스트를 올바르게 가져도 캐스트를 포함시키지 못하는 것입니다. 그렇게하는 것에는 이점이 없지만, 잠재적 위험이 많으며 캐스트를 포함하면 위험에 대해 모른다는 것을 나타냅니다.

또한 주석가들이 지적했듯이 위의 내용은 C ++이 아닌 C에 대해 이야기합니다. 나는 C와 C ++를 별도의 언어로 굳게 믿고 있습니다.

더 추가하기 위해 코드는 불필요하게 int오류를 일으킬 수 있는 유형 정보 ( )를 반복합니다 . 반환 값을 저장하는 데 사용되는 포인터를 역 참조하여 둘을 "잠그는"것이 좋습니다.

int *sieve = malloc(length * sizeof *sieve);

또한 length가시성을 높이기 위해를 앞쪽으로 이동 하고 중복 괄호는 sizeof; 그들은 오직 필요한 인수가 유형 이름 인 경우. 많은 사람들이 이것을 알지 못하거나 무시하여 코드를 더 장황하게 만듭니다. 기억하십시오 : sizeof기능이 아닙니다! :)


드문 경우에 length앞쪽으로 이동 하면 가시성 높아질 있지만 일반적인 경우에는 다음과 같이 표현을 작성하는 것이 좋습니다.

int *sieve = malloc(sizeof *sieve * length);

sizeof이 경우 첫 번째를 유지하므로 최소한 size_t수학으로 곱셈을 수행 합니다.

비교 : malloc(sizeof *sieve * length * width)malloc(length * width * sizeof *sieve)번째는 오버 플로우 수 length * widthwidthlength보다 작은 유형입니다 size_t.


21
답변을 업데이트하십시오. 캐스트는 더 이상 위험하지 않으며 자신을 반복하는 것이 반드시 나쁜 것은 아닙니다 (중복성이 오류를 잡는 데 도움이 될 수 있음).
n. '대명사'm.

11
컴파일러가 변경되었습니다. 최신 컴파일러는 malloc의 누락 된 선언에 대해 경고합니다.
n. '대명사'm.

55
@nm 좋아요. 나는 여기에서 읽는 사람이 특정 컴파일러를 가지고 있다고 가정하는 것이 좋지 않다고 생각합니다. 또한 C11의 전체 "암시 적 기능"개념이 사라 졌으므로이를 몰랐습니다. 여전히, 나는 무의미한 캐스트를 추가 할 때 요점이 보이지 않습니다. 당신은 또한 int x = (int) 12;일을 명확하게하기 위해합니까?

22
@nm void 포인터를 명시 적으로 캐스팅하여 버그를 해결하면 정의되지 않은 동작이 발생했을 가능성이 높습니다. 즉, 해당 프로그램에 아직 실행되지 않은 훨씬 더 나쁘고 발견되지 않은 버그가있을 수 있습니다. 어느 날 추운 겨울 저녁에 직장에서 집으로 돌아와 귀신이 날아 다니는 악마에 대해 불평하는 문제 보고서가있는 GitHub 페이지를 찾을 수 있습니다.
Braden Best

12
@unwind 내가 동의하더라도 (int)12비교할 수 없습니다. 12 이다int , 캐스트는 단순히 아무것도하지 않는다. 의 RETVAL malloc()IS가 void *아닌 포인터 타입으로 캐스트. (그렇지 않은 경우 void *. 비유는 그렇게 (int)12될 것이다 (void*)malloc(…)아무도 논의되지 않은 것.)
아민 Negm - 아 와드

376

C에서는의 반환 값을 캐스팅 할 필요가 없습니다 malloc. void에 의해 반환되는 포인터 malloc는 자동으로 올바른 유형으로 변환됩니다. 그러나 코드를 C ++ 컴파일러로 컴파일하려면 캐스트가 필요합니다. 커뮤니티에서 선호하는 대안은 다음을 사용하는 것입니다.

int *sieve = malloc(sizeof *sieve * length);

또한의 유형을 변경하는 경우 표현식의 오른쪽을 변경하는 것에 대해 걱정할 필요가 없습니다 sieve.

사람들이 지적한 것처럼 캐스트는 좋지 않습니다. 특히 포인터 캐스트.


71
@MAKZ 나는 malloc(length * sizeof *sieve)그것이 sizeof변수 처럼 보이게 만든다고 주장한다 -그래서 나는 malloc(length * sizeof(*sieve))더 읽기 쉽다고 생각한다 .
Michael Anderson

21
그리고 malloc(length * (sizeof *sieve))더 읽기 쉬운. 이모.
Toby Speight

19
@Michael Anderson ()문제는 제쳐두고, 제안 된 스타일이 순서를 바꿨다는 점에 유의하십시오. 요소 수를 계산하는 시점을 고려 하여이 경우 첫 번째를 length*width유지하면 sizeof적어도 size_t수학적으로 곱셈이 수행됩니다 . 비교 malloc(sizeof( *ptr) * length * width)vs. malloc(length * width * sizeof (*ptr))-2 는 더 작은 유형일 length*width때 오버플로 될 수 있습니다 . width,lengthsize_t
chux-Reinstate Monica

3
@ chux 그것은 분명하지 않지만 대답은 편집되어 내 의견이 덜 적절합니다. 원래 제안은 다음과 같습니다malloc(sizeof *sieve * length)
Michael Anderson

12
C는 C ++이 아닙니다. 그들이 척하는 것은 결국 혼란과 슬픔으로 이어질 것입니다. C ++을 사용하는 경우 C 스타일 캐스트도 좋지 않습니다 (아주 오래된 C ++ 컴파일러를 사용하지 않는 한). 그리고 static_cast>()(또는 reinterpret_cast<>()) C의 어떤 방언과도 호환되지 않습니다
David C.

349

다음 과 같은 이유로 캐스트를 수행합니다 .

  • C와 C ++ 사이에서 코드의 이식성 을 높이고 SO 경험이 보여 주듯이 많은 프로그래머들은 실제로 C ++ (또는 C + 로컬 컴파일러 확장)로 작성할 때 C로 작성한다고 주장합니다.
  • 그렇게하지 않으면 오류를 숨길 수 있습니다 . 쓸 때 type *대 혼란을 일으키는 모든 SO 예제를 주목하십시오 type **.
  • #include적절한 헤더 파일 을 찾지 못했다는 생각 으로 인해 나무의 숲이 사라 집니다. "컴파일러에게 프로토 타입이 보이지 않는다는 불만을 제기하지 않았다는 사실에 대해 걱정하지 마십시오. pesky stdlib.h는 반드시 기억해야 할 중요한 사실입니다."라고 말하는 것과 같습니다.
  • 추가적인인지 검사를 강제합니다 . 해당 변수의 원시 크기에 대해 수행중인 산술 옆에 (알려진) 원하는 유형을 넣습니다. malloc()캐스트가있을 때 버그가 훨씬 빨리 잡히는 것을 보여주는 SO 연구를 할 수 있습니다. 어설 션과 마찬가지로 의도를 나타내는 주석은 버그를 줄입니다.
  • 기계가 점검 할 수있는 방식으로 자신을 반복하는 것이 종종 좋은 생각입니다. 사실, 그것이 어서 트의 정의이고, 캐스트의 사용은 어서 트입니다. 튜링은 수년 전에 아이디어를 생각해 냈기 때문에 어설 션은 코드를 올바르게 얻는 가장 일반적인 기술입니다.

39
@ulidtko 모르는 경우 C와 C ++로 컴파일되는 코드를 작성할 수 있습니다. 실제로 대부분의 헤더 파일은 이와 같으며 종종 코드 (매크로 및 인라인 함수)를 포함합니다. 갖는 .c/의 .cpp모두로 컴파일 할 파일 것은 자주 유용 아니라, 하나의 경우는 C ++ 추가하고 throwC ++ 컴파일러로 컴파일 할 때 지원 (단, return -1;C 컴파일러, 또는 무엇이든 컴파일 할 때).
hyde

37
누군가 헤더에 malloc 호출을 인라인하면 감동하지 않을 것입니다. #ifdef __cplusplus 및 extern "C"{}는 추가 캐스트를 추가하지 않고이 작업에 사용됩니다.
paulm

15
C 1 = C ++이므로 포인트 1은 관련이 없습니다. 다른 변수도malloc 호출에 변수 를 사용 하면 사소 합니다 . char **foo = malloc(3*sizeof(*foo));충분히 증명하는 경우 : char 포인터에 대한 3 포인터. 그런 다음 루프하고 수행하십시오 foo[i] = calloc(101, sizeof(*(foo[i])));. 101 개의 문자 배열을 할당하고 깔끔하게 0으로 초기화합니다. 캐스트가 필요하지 않습니다. unsigned char그 문제에 대한 선언 이나 다른 유형으로
변경해도

34
내가 그것을 힘들 때, 그것은 온다! 환상적인 답변. StackOverflow에서 처음으로 두 가지 정답을 +1했습니다! +1 아니요, 캐스트하지 않으며 +1 예, 캐스트합니다! LOL. 너희들은 훌륭하다. 저와 제 학생들을 위해 저는 생각했습니다. 캐스팅 할 때 학생들이 만드는 오류의 종류가 더 쉽게 발견됩니다.
Dr Beco

15
@Leushenko : 기계 나 로컬 검사로는 검증 할 수없는 방식으로 자신을 반복하는 것은 좋지 않습니다. 그러한 수단으로 검증 될 수있는 방식으로 자신을 반복하는 것은 덜 나쁘다. 을 감안할 때 struct Zebra *p; ... p=malloc(sizeof struct Zebra);, malloc이이 페이지의 유형에 대한 duplciating 정보를 피할 수 있지만, 하나 개의 유형이 변경되면 컴파일러 나 지역 코드 검사도 어떤 문제를 감지 할 것이지만, 다른 하나는하지 않았다. 코드를 변경하면 p=(struct Zebra*)malloc(sizeof struct Zebra);캐스트 유형이 일치하지 않으면 컴파일러가 스 쿼크 p되고 로컬 검사가 수행됩니다.
supercat

170

다른 사람들이 언급했듯이 C에는 필요하지 않지만 C ++에는 필요합니다. 어떤 이유로 든 C ++ 컴파일러로 C 코드를 컴파일한다고 생각되면 다음과 같은 매크로를 대신 사용할 수 있습니다.

#ifdef __cplusplus
# define NEW(type, count) ((type *)calloc(count, sizeof(type)))
#else
# define NEW(type, count) (calloc(count, sizeof(type)))
#endif

그렇게하면 여전히 매우 간단한 방법으로 작성할 수 있습니다.

int *sieve = NEW(int, 1);

C 및 C ++를 위해 컴파일됩니다.


17
어쨌든 매크로를 사용 new하고 있으므로 C ++의 정의에 사용하지 않는 이유는 무엇입니까?
Hosam Aly

63
그렇게 할 이유가 없기 때문입니다. 주로 C ++ 컴파일러로 컴파일 된 C 프로그램 용입니다. '신규'를 사용하려는 경우 얻는 유일한 것은 문제입니다. 그런 다음 무료 매크로도 필요합니다. 그리고 배열을
비우려면

8
메모리를 비우는 사람이 아니라 사용중인 C 라이브러리 등을 언급하는 것은 말할 것도 없습니다. 얻을 수있는 많은 가능한 문제.
quinmars

86
@Hosam : 그렇습니다. 당신이 사용하는 경우 new사용해야 delete하고 사용하는 경우 당신 malloc()이해야합니다 free(). 혼합하지 마십시오.
Graeme Perrow

17
이 방법을 사용하려는 경우 (또는 )를 NEW사용하여 리소스가 반환되지 않으므로 매크로를 호출하는 것이 좋지 않을 수 있습니다. 대신, 이름을 지정 하거나 오히려 이 경우에는 더 의미가있다. deleteDELETEMALLOCCALLOC
mah

139

보내는 사람 위키 백과 :

주조의 장점

  • 캐스트를 포함하면 C 프로그램 또는 함수가 C ++로 컴파일 될 수 있습니다.

  • 캐스트는 원래 char *를 리턴 한 1989 년 이전 버전의 malloc을 허용합니다.

  • 캐스팅은 포인터가 malloc () 호출에서 멀리 선언 된 경우 대상 포인터 유형이 변경되면 개발자가 유형 크기의 불일치를 식별하는 데 도움이 될 수 있습니다 (현대 컴파일러 및 정적 분석기는 캐스트를 요구하지 않고 이러한 동작에 대해 경고 할 수 있음).

캐스팅의 단점

  • ANSI C 표준에서는 캐스트가 중복됩니다.

  • 캐스트를 추가하면 헤더 stdlib.h 를 포함하지 못하도록 마스크 될 수 있습니다.malloc의 프로토 타입을 찾을 수 있습니다. malloc에 ​​대한 프로토 타입이없는 경우, 표준에서는 C 컴파일러가 malloc이 int를 리턴한다고 가정해야합니다. 캐스트가 없으면이 정수가 포인터에 지정 될 때 경고가 발행됩니다. 그러나 캐스트에서는 버그를 숨기고이 경고가 생성되지 않습니다. 특정 아키텍처 및 데이터 모델 (예 : 64 비트 시스템의 LP64, 길고 포인터가 64 비트이고 int가 32 비트 인 경우)에서이 오류는 암시 적으로 선언 된 malloc이 32를 반환하므로 실제로 정의되지 않은 동작이 발생할 수 있습니다. 실제로 정의 된 함수가 64 비트 값을 반환하는 반면 비트 값. 호출 규칙 및 메모리 레이아웃에 따라 스택 스매싱이 발생할 수 있습니다. 이 문제는 최신 컴파일러에서 눈에 띄지 않을 가능성이 높습니다. 선언되지 않은 함수가 사용되었다는 경고를 균일하게 생성하므로 경고가 계속 나타납니다. 예를 들어 GCC의 기본 동작은 캐스트가 있는지 여부에 관계없이 "내장 함수의 암시 적 선언이 호환되지 않는다"는 경고를 표시하는 것입니다.

  • 선언에서 포인터의 유형이 변경되면 malloc이 호출되고 캐스트되는 모든 행을 변경해야 할 수도 있습니다.

하지만 캐스팅이없는 malloc에이 선호되는 방법이며, 가장 경험이 풍부한 프로그래머를 선택 , 당신은 문제에 대해 알고있는 같이 쪽을 사용해야합니다.

즉, C 프로그램을 C ++로 컴파일해야하는 경우 (별도의 언어 임) 사용 결과를 캐스트해야합니다 malloc.


1
" 캐스팅은 특히 포인터가 malloc()호출 에서 멀리 선언 된 경우 대상 포인터 유형이 변경되어야하는 경우 개발자가 유형 크기의 불일치를 식별하는 데 도움이 될 수 있습니까?" 예를 들어 주시겠습니까?
Spikatrix

3
@CoolGuy : 다른 답변에 대한 이전 의견을보십시오 . 그러나 p = malloc(sizeof(*p) * count)관용구가 유형의 변경 사항을 자동으로 선택하므로 경고를 받고 아무것도 변경할 필요가 없습니다. 따라서 이것은 비 캐스팅에 대한 최상의 대안과 실제 이점이 아닙니다.
Peter Cordes

7
이것은 정답입니다. 장단점이 있으며, 코드가 C ++로 컴파일되어야하는 경우가 아니라면 캐스트는 필수입니다.
피터-모니 티 복원

3
포인터의 유형이 선언에서 변경되면 malloc, realloc 및 해당 유형에 영향을 미치지 않는 모든 인스턴스를 확인해야하기 때문에 포인트 3은 문제가됩니다. 캐스팅은 당신이 그렇게 할 것을 강요합니다.
Michaël Roy

104

C에서는 void포인터를 암시 적으로 다른 종류의 포인터 로 변환 할 수 있으므로 캐스트가 필요하지 않습니다. 하나를 사용하면 캐주얼 관찰자에게 하나의 이유가 있다고 오해의 소지가있을 수 있습니다.


100

malloc의 결과를 캐스트하지 마십시오. 그렇게하면 코드에 무의미한 혼란이 추가됩니다.

사람들이 malloc의 결과를 캐스팅하는 가장 일반적인 이유는 C 언어의 작동 방식에 대해 확신이 없기 때문입니다. 경고 표시입니다. 특정 언어 메커니즘이 어떻게 작동하는지 모르는 경우 경우 추측 . 그것을 보거나 스택 오버플로를 요청하십시오.

일부 의견 :

  • 빈 포인터는 명시 적 캐스트 (C11 6.3.2.3 및 6.5.16.1)없이 다른 포인터 유형과 변환 할 수 있습니다.

  • 그러나 C ++은 void*다른 포인터 유형과 암시 적 캐스트를 허용하지 않습니다 . 따라서 C ++에서는 캐스트가 정확했을 것입니다. 그러나 C ++로 프로그래밍한다면new malloc ()이 아니라 . 그리고 C ++ 컴파일러를 사용하여 C 코드를 컴파일해서는 안됩니다.

    동일한 소스 코드로 C 및 C ++를 모두 지원해야하는 경우 컴파일러 스위치를 사용하여 차이점을 표시하십시오. 호환되지 않기 때문에 두 언어 표준을 동일한 코드로 작성하려고하지 마십시오.

  • 헤더를 포함하는 것을 잊었 기 때문에 C 컴파일러가 함수를 찾을 수 없으면 그것에 대한 컴파일러 / 링커 오류가 발생합니다. 따라서 큰 <stdlib.h>문제가 아니라는 것을 잊어 버린 경우 프로그램을 빌드 할 수 없습니다.

  • 25 년이 지난 표준 버전을 따르는 고대 컴파일러에서는 포함을 잊어 버리면 <stdlib.h>위험한 행동을하게됩니다. 고대 표준에서 보이는 프로토 타입이없는 함수는 암시 적으로 리턴 유형을int . malloc에서 결과를 명시 적으로 캐스팅하면이 버그가 사라집니다.

    그러나 그것은 실제로 문제가 아닙니다. 25 년 된 컴퓨터를 사용하지 않는 이유는 무엇입니까? 25 년 된 컴파일러를 사용하는 이유는 무엇입니까?


9
"무의미한 혼란"은 당신에게 이미 동의하지 않은 사람을 설득 할 수있는 가능성을 잃어 버리는 무시할만한 과장입니다. 캐스트는 확실히 의미가 없습니다. Ron Burk와 Kaz의 대답은 내가 매우 동의하는 캐스팅에 찬성하여 논쟁을합니다. 이러한 우려가 귀하가 언급 한 우려보다 더 중요한지 여부는 합리적인 질문입니다. 나에게 당신의 우려는 그들의 것에 비해 상대적으로 작게 보입니다.
돈 해치

"명시 적 캐스트없이 다른 포인터 유형으로 /에서 void 포인터를 변환 할 수 있습니다"는 6.3.2.3에서 지원되지 않습니다. 아마도 "어떤 객체 유형에 대한 포인터"를 생각하고 있습니까? "void pointer"와 "function에 대한 포인터"는 쉽게 변환 할 수 없습니다.
chux-복원 Monica Monica

실제로 참조가 불완전했습니다. "내 재성"과 관련된 부분은 간단한 할당 규칙이다. 6.5.16.1. "한 피연산자는 오브젝트 유형에 대한 포인터이고 다른 피연산자는 규정 된 또는 규정되지 않은 void 버전의 포인터입니다." 완성도에 대한 답에이 참조를 추가했습니다.
Lundin

91

C에서는 void *다른 (데이터) 포인터로 의 암시 적 변환을 얻습니다 .


6
@Jens : 좋습니다. 아마도 더 적절한 표현은 "암시 적 변환"입니다. 부동 소수점 식에서 정수 변수를 사용하는 것과 같습니다.
EFraim

@EFraim 실제로 캐스트가 발생하고 암시 적 결과가 발생합니다.
Mad Physicist

71

에 의해 반환 된 값을 캐스팅하는 malloc()것은 현재 필요하지 않지만 아무도 지적하지 않은 것으로 보이는 점을 하나 추가하고 싶습니다.

고대에, 즉 ANSI Cvoid * 가 포인터를 일반적인 유형으로 제공 하기 전에 char *그러한 사용법을위한 유형입니다. 이 경우 캐스트는 컴파일러 경고를 종료 할 수 있습니다.

참조 : C FAQ


2
컴파일러 경고를 종료하는 것은 좋지 않습니다.
Albert van der Horst

8
@AlbertvanderHorst 정확한 문제를 해결하여 경고를 표시하는 경우 경고가 표시되지 않습니다.
Dan Bechard

@ 댄. 정확한 문제를 해결함으로써 char * 대신 현대 ANSI C 유형을 반환하기 위해 서브 루틴을 다시 작성한다는 의미라면 동의합니다. 나는 컴파일러를 종료한다고 부르지 않을 것이다. 문제를 찾기 위해 각 재 컴파일에서 컴파일러 경고를 사용하는 대신 컴파일러 경고가 없다고 주장하는 관리자에게 제공하지 마십시오. Groetjes 앨버트
앨버트 반 데르 호스트

53

내 경험을 추가하고 컴퓨터 공학을 공부하면서 C로 작문 한 두세 명의 교수가 항상 malloc을 캐스팅 한 것을 보았지만 (큰 이력서와 C에 대한 이해를 가지고) 요청한 사람은 그것이 절대적으로 불필요하다고 말했지만 예전에는 절대적으로 구체적이었고 학생들이 절대적으로 구체적이라는 마음가짐을 갖기 위해서였습니다. 본질적으로 캐스팅은 작동 방식에서 아무것도 변경하지 않으며 정확히 말하고 메모리를 할당하며 캐스팅에 영향을 미치지 않으며 동일한 메모리를 얻거나 실수로 다른 것으로 캐스팅하더라도 컴파일러를 회피합니다. C) 같은 방식으로 액세스합니다.

편집 : 캐스팅에는 특정 포인트가 있습니다. 배열 표기법을 사용할 때 생성 된 코드는 다음 요소의 시작 부분에 도달하기 위해 얼마나 많은 메모리 위치를 가져와야하는지 알아야합니다. 이는 캐스팅을 통해 달성됩니다. 이 방법을 사용하면 double의 경우 8 바이트가 앞당겨지고 int의 경우 4가됩니다. 따라서 포인터 표기법을 사용하면 효과가 없으며 배열 표기법에서는 필요합니다.


3
이미 언급 한 경우를 제외하고, 캐스트는 버그를 숨기고 컴파일러 또는 정적 분석기에 대한 코드 분석을 더 어렵게 만들 수 있습니다.
Lundin

2
"실제로 캐스팅하면 작동 방식이 변경되지 않습니다." 일치하는 유형으로 캐스트하면 아무것도 바뀌지 않아야하지만 var의 유형이 변경되고 캐스트가 더 이상 일치하지 않으면 문제가 발생할 수 있습니까? IWO, 캐스트 및 var 유형은 유지 보수 작업의 두 배인 동기화 상태로 유지되어야합니다.
chux-복원 Monica Monica

교수진이 왜 캐스팅을 선호하는지 알 수 있습니다. 캐스팅은 강사 정보를 전달하고 학생 코드를 유지할 필요가없는 교육적 관점에서 유용 할 수 있습니다. 그러나 코딩, 동료 검토 및 유지 관리 측면에서 볼 때 p = malloc(sizeof *p * n);매우 간단하고 좋습니다.
chux-복원 Monica Monica

53

이 결과를 캐스팅 할 의무되지 malloc는 반환 이후 void*, a는 void*어떤 데이터 타입을 지적 할 수있다.


34

void 포인터는 일반적인 객체 포인터이며 C는 void 포인터 형식에서 다른 형식으로의 암시 적 변환을 지원하므로 명시 적으로 형식을 변환 할 필요가 없습니다.

그러나 암시 적 변환을 지원하지 않는 C ++ 플랫폼에서 동일한 코드가 완벽하게 호환되도록하려면 형식 캐스팅을 수행해야하므로 사용성에 따라 달라집니다.


2
단일 소스를 C와 C ++로 컴파일하는 것은 일반적인 사용 사례가 아닙니다 (예를 들어, 선언이 포함 된 헤더 파일을 사용하여 C와 C ++ 코드를 연결하는 것과는 반대). mallocC ++에서 사용 하고 친구라는 것은 특별한주의가 필요하거나 C로 다시 작성해야한다는 좋은 경고 신호입니다.
Toby Speight

1
"공백 포인터는 일반 포인터입니다"-> "공백 포인터는 일반 개체 포인터입니다." 함수 포인터 크기가을 (를) 초과 할 수 void *있으므로 void *함수 포인터를 잘 저장하기에 충분하지 않습니다.
chux-복원 Monica Monica

내 라인의 의도는 동일하지만 어쨌든 제안에 대해 @chux에게 감사드립니다.
노력 노력

33

이것은 무엇인가 는 GNU C 라이브러리 참조 설명서를 말한다 :

mallocISO C는 필요에 따라 유형 void *을 다른 유형의 포인터 로 자동 변환하기 때문에 캐스트없이 포인터 변수에 결과를 저장할 수 있습니다 . 그러나 캐스트는 할당 연산자 이외의 컨텍스트에서 또는 코드를 전통적인 C에서 실행하려는 경우에 필요합니다.

실제로 ISO C11 표준 (p347)은 다음과 같이 말합니다.

할당이 성공하면 반환되는 포인터는 기본 정렬 요구 사항을 가진 모든 유형의 객체에 대한 포인터에 할당 된 다음 할당 된 공간에서 해당 객체 또는 이러한 객체의 배열에 액세스하는 데 사용할 수 있도록 적절하게 정렬됩니다 ( 공간이 명시 적으로 할당 해제되었습니다)


31

리턴 된 유형은 void *이며, 이는 참조 불가능하도록 원하는 유형의 데이터 포인터로 캐스트 될 수 있습니다.


1
void* 원하는 유형으로 캐스트 수 있지만 자동으로 변환 될 필요는 없습니다. 따라서 캐스트는 필요하지 않으며, 높은 점수의 답변에 언급 된 이유로 바람직하지 않습니다.
Toby Speight

그러나 변수를 "즉시"역 참조해야하는 경우에만 대신 변수를 만들면 캐스팅없이 (C에서) 변수의 유효 유형으로 안전하고 자동으로 변환됩니다.
페라 레지

28

C 언어에서는 빈 포인터를 모든 포인터에 할당 할 수 있으므로 타입 캐스트를 사용하지 않아야합니다. "유형 안전"할당을 원한다면 항상 C 프로젝트에서 사용하는 다음 매크로 함수를 추천 할 수 있습니다.

#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof *(ptr))
#define NEW(ptr) NEW_ARRAY((ptr), 1)

이것들을 사용하면 간단히 말할 수 있습니다.

NEW_ARRAY(sieve, length);

비 동적 배열의 경우 세 번째 필수 기능 매크로는

#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])

배열 루프를보다 안전하고 편리하게 만듭니다.

int i, a[100];

for (i = 0; i < LEN(a); i++) {
   ...
}

"공백 포인터는 모든 객체 포인터에 할당 될 수 있습니다 "함수 포인터는 하나는 아니지만 다른 문제 malloc()입니다.
chux-복원 Monica Monica

void*함수 포인터에 대해 /에서 함수 포인터를 지정하면 정보가 손실 될 수 있으므로 "포인터에 void 포인터를 지정할 수 있습니다"는 문제가됩니다. 할당 void*에서, malloc() 어느 객체 포인터 것은 비록 문제가되지 않습니다.
chux-Reinstate Monica

do멀리 제목 질문에서 궁금해 아직 루프를 포함하는 매크로와 관련된 루프 코멘트. 그 의견을 제거합니다. 이것도 나중에 쓰러 뜨릴 것입니다.
chux-Reinstate Monica

27

프로그래밍 언어와 컴파일러에 따라 다릅니다. mallocC에서 사용하는 경우 캐스트를 자동으로 입력하므로 캐스트를 입력 할 필요가 없습니다. 그러나 C ++를 사용 malloc하는 경우 void*유형 을 리턴 하므로 유형 변환을 수행해야 합니다.


1
malloc 함수 는 C에서도 void 포인터를 반환하지만 언어 규칙은 C ++과 다릅니다.
August Karlstrom

16

GCC와 Clang에 익숙한 사람들은 망치고 있습니다. 그다지 좋은 것은 아닙니다.

몇 년 동안 내가 사용해야했던 엄청나게 오래된 컴파일러들에 의해 꽤 끔찍했습니다. 종종 회사와 관리자는 변화하는 컴파일러에 대해 매우 보수적 인 접근 방식을 채택하며 테스트 조차하지 않습니다. 더 나은 표준 준수 및 코드 최적화 기능을 갖춘 새 컴파일러가 시스템에서 작동하는지 . 실무 개발자에게 실제 현실은 코딩 할 때베이스를 다루어야하지만 불행히도 malloc을 캐스팅하는 것은 코드에 적용 할 컴파일러를 제어 할 수없는 경우 좋은 습관입니다.

많은 조직들이 자신의 코딩 표준을 적용하는 것이 또한 제안 것을 가 정의되어있는 경우 방법 사람들이 수행해야합니다. 명백한 지침이 없다면 나는 표준에 대한 노예의 준수보다는 모든 곳에서 컴파일 할 가능성이 가장 높다.

현재 표준에서 필요하지 않다는 주장은 상당히 유효합니다. 그러나 그 주장은 실제 세계의 실용성을 생략합니다. 우리는 오늘의 표준에 의해 독점적으로 지배되는 세계에서 코드를 작성하는 것이 아니라 내가 "지역 경영의 현실 분야"라고 부르는 것의 실용성에 의해 코딩됩니다. 그리고 그것은 시공간보다 더 구부러지고 뒤틀 렸습니다. :-)

YMMV.

나는 malloc을 방어 작전이라고 생각하는 경향이 있습니다. 예쁘지 않고 완벽하지는 않지만 일반적으로 안전합니다. (당신이 그 다음 인 stdlib.h 포함되지 않은 한 경우 솔직히, 당신은했습니다 방법 malloc에 캐스팅보다 더 많은 문제를!).


15

나는 형 변환 시스템에서 못생긴 구멍의 비 승인을 보여주기 위해 단순히 캐스트를 넣었습니다.

double d;
void *p = &d;
int *q = p;

나는 그것이 존재하지 않기를 바란다. (그리고 C ++에는 없다.) 그것은 내 취향과 프로그래밍 정치를 나타냅니다. 나는 포인터를 던질뿐만 아니라 효과적으로 투표 용지를 캐스팅하고 바보 같은 악마를 캐스팅합니다 . 내가 실제로 어리 석음을 낼 수 없다면 , 적어도 항의의 몸짓으로 그렇게하고 싶은 소망을 표현하도록하자.

실제로 좋은 습관은을 malloc반환 unsigned char *하고 기본적으로 void *코드에서 사용하지 않는 함수 로 랩하는 것 입니다. 당신이 일반적인 포인터 - 투 - 어떤 객체를 필요로한다면,를 사용 char *하거나 unsigned char *, 두 방향으로 캐스트를 가지고있다. 아마도 탐닉 할 수있는 휴식은 캐스트 memset와 같은 함수와 memcpy캐스트없는 함수를 사용하는 것 입니다.

캐스팅 및 C ++ 호환성 주제에서 코드를 C와 C ++로 컴파일하도록 코드를 작성하는 경우 (이 경우에 다른 값을 할당 할 때 의 반환 값 캐스팅 해야 함 ) 매우 도움이 될 수 있습니다. 스스로 할 것 : C ++로 컴파일 할 때 C ++ 스타일 캐스트로 변환하는 캐스팅에 매크로를 사용할 수 있지만 C로 컴파일 할 때 C 캐스트로 줄입니다.mallocvoid *

/* In a header somewhere */
#ifdef __cplusplus
#define strip_qual(TYPE, EXPR) (const_cast<TYPE>(EXPR))
#define convert(TYPE, EXPR) (static_cast<TYPE>(EXPR))
#define coerce(TYPE, EXPR) (reinterpret_cast<TYPE>(EXPR))
#else
#define strip_qual(TYPE, EXPR) ((TYPE) (EXPR))
#define convert(TYPE, EXPR) ((TYPE) (EXPR))
#define coerce(TYPE, EXPR) ((TYPE) (EXPR))
#endif

이러한 매크로를 준수하는 경우 grep이러한 식별자에 대한 코드 기반을 간단하게 검색하면 모든 캐스트가 어디에 있는지 보여 주므로 해당 매크로 가 잘못되었는지 검토 할 수 있습니다.

그런 다음 C ++로 코드를 정기적으로 컴파일하면 적절한 캐스트를 사용해야합니다. 예를 들어, 또는 strip_qual을 제거하는 데만 사용 하지만 유형 변환이 수행되는 방식으로 프로그램이 변경되면 진단을 받고 원하는 변환을 얻으려면 캐스트 조합을 사용해야합니다.constvolatile

이러한 매크로를 고수하는 데 도움이되도록 GNU C ++ (C! 아님) 컴파일러에는 아름다운 C 기능 캐스트에 대해 생성되는 선택적 진단 기능이 있습니다.

     -Wold-style-cast (C ++ 및 Objective-C ++ 만 해당)
         보이드가 아닌 유형으로 캐스트 된 이전 스타일 (C 스타일)을 사용하는 경우 경고
         C ++ 프로그램 내에서. 새로운 스타일의 캐스트 (dynamic_cast,
         static_cast, reinterpret_cast 및 const_cast)는 덜 취약합니다.
         의도하지 않은 효과와 검색하기가 훨씬 쉽습니다.

C 코드가 C ++로 컴파일되는 경우이 -Wold-style-cast옵션을 사용하여 코드에 영향을 줄 수있는 모든 (type)캐스팅 구문 을 찾아 위의 매크로 중에서 적절한 선택으로 대체하여 이러한 진단을 수행 할 수 있습니다. 필요한 경우 조합).

이러한 변환 처리는 "Clean C"에서 작업하기위한 가장 큰 독립 실행 형 기술 정당성입니다. C와 C ++의 결합 된 방언은 차례로 반환 값의 캐스팅을 기술적으로 정당화합니다 malloc.


다른 지적한 바와 같이, 나는 일반적으로 C와 C ++ 코드를 혼합하지 않는 것이 좋습니다. 그러나 그럴만한 이유가 있다면 매크로가 유용 할 수 있습니다.
Phil1970

@ Phil1970 C와 C ++ 컴파일러로 이식 가능하며 C ++의 일부 기능을 활용하는 하나의 응집 된 방언으로 작성되었습니다. 모두 C ++ 또는 C로 컴파일해야합니다.
Kaz

즉, 이전 의견에서 말하려고했던 것은 C와 C ++의 혼합이 없다는 것입니다. 코드는 모두 C로 컴파일되거나 모두 C ++로 컴파일됩니다.
Kaz

15

가능할 때마다 C로 프로그래밍 할 때 가장 좋은 방법 :

  1. 모든 경고가 설정된 상태에서 프로그램을 C 컴파일러를 통해 컴파일 -Wall하고 모든 오류 및 경고를 수정하십시오.
  2. 로 선언 된 변수가 없는지 확인하십시오 auto
  3. 그런 다음 -Walland를 사용하여 C ++ 컴파일러를 사용하여 컴파일하십시오 -std=c++11. 모든 오류 및 경고를 수정하십시오.
  4. 이제 C 컴파일러를 사용하여 다시 컴파일하십시오. 이제 프로그램이 경고없이 컴파일되고 버그가 줄어 듭니다.

이 절차를 통해 C ++ 엄격한 유형 검사를 이용하여 버그 수를 줄일 수 있습니다. 특히,이 절차는 강제로 포함 stdlib.h시키거나

malloc 이 범위 내에서 선언되지 않았습니다

또한 결과를 캐스트하도록 강요 malloc받거나

에서 유효하지 않은 변환 void*T*

또는 대상 유형이 무엇이든.

내가 찾을 수있는 C ++ 대신 C로 작성하면 얻을 수있는 유일한 이점은 다음과 같습니다.

  1. C는 잘 지정된 ABI를 가지고 있습니다
  2. C ++는 더 많은 코드를 생성 할 수 있습니다 [예외, RTTI, 템플릿, 런타임 다형성]

정적 다형성 피처 와 함께 C에 공통적 인 부분 집합을 사용하는 경우 이상적인 경우 두 번째 단점이 사라집니다 .

C ++ 엄격한 규칙이 불편한 사람들을 위해 유추 유형과 함께 C ++ 11 기능을 사용할 수 있습니다

auto memblock=static_cast<T*>(malloc(n*sizeof(T))); //Mult may overflow...

18
C 코드에 C 컴파일러를 사용하십시오. C ++ 코드에는 C ++ 컴파일러를 사용하십시오. 경우도없고 엉덩이도 없습니다. C ++로 C 코드를 다시 작성하는 것은 시간과 위험을 감수 할 가치가 있거나 전혀 없을 수도 있습니다.
Toby Speight

2
나는 @TobySpeight 조언에 추가 할 : 당신이 C ++ 프로젝트에서 C 코드를 사용해야하는 경우, 일반적으로 (예를 들어 C와 C 코드를 컴파일 할 수 있습니다 gcc -c c_code.c), C ++ (예 :로 C ++ 코드 g++ -c cpp_code.cpp), 그리고 그들을 함께 연결 (예 : gcc c_code.o cpp_code.o프로젝트 의존성에 따라 또는 그 반대로). 이제 어느 언어의 멋진 기능을 모두 빼앗을 이유가 없어야합니다.
자폐증

1
@ user877329 "C ++ 호환"을 위해서만 코드의 가독성을 감소시키는 코드에 캐스트를 힘들게 추가하는 것이 더 현명한 대안입니다.
자폐증

1
이 맥락에서 아마도 가장 큰 장점은 C가 쓸 수 있다는 것 입니다. 다른 유형 이름으로 변경 p = malloc(sizeof(*p));되면 처음부터 변경할 필요가 없습니다 p. 제안 된 캐스팅의 "이점"은 p잘못된 유형 인 경우 컴파일 오류가 발생 하지만 그냥 작동하면 더 나은 것입니다.
Peter Cordes

1
적절한 C ++ 컴파일러가없는 플랫폼을 대상으로 할 때 C로 작성해야 할 수도 있습니다. 예외 및 템플릿은 일반적으로 c ++가 더 작거나 효율적인 코드를 생성하는 데 도움이되는 기능이지만 C ++의 런타임 다형성은 대부분 C와 같습니다.
user7860670

15

아니요,의 결과는 전송하지 않습니다 malloc().

일반적으로 (으)로 전송 하지 않습니다void * .

그렇게하지 않는 일반적인 이유는 실패가 #include <stdlib.h>눈에 띄지 않을 수 있기 때문입니다. C99가 암시 적 함수 선언을 불법으로 만들었 으므로 이제는 더 이상 문제가되지 않으므로 컴파일러가 C99 이상을 준수하면 진단 메시지가 표시됩니다.

그러나 불필요한 포인터 캐스트를 도입하지 않는 훨씬 더 강력한 이유가 있습니다 .

C에서 포인터 캐스트는 거의 항상 오류 입니다. 이는 다음 규칙 때문입니다 ( C11의 최신 초안 N1570의 §6.5 p7 ).

객체는 다음 유형 중 하나를 갖는 lvalue 표현식에 의해서만 저장된 값에 액세스해야합니다.
— 객체
의 유효 유형과 호환되는 유형
— 객체의 유효 유형과 호환되는 유형의 정규화 된 버전 — 오브젝트의 유효 유형에 해당하는 부호있는 유형 또는 부호없는 유형 인 유형 (유효한 오브젝트
유형의 규정 된 버전에 해당하는 부호있는 유형 또는 부호없는 유형 인 유형)
-하나를 포함하는 집합 또는 공용체 유형 재귀 적으로 하위 집합 또는 포함 된 공용체의 구성원을 포함하여 전술 한 유형 중 하나 또는
문자 유형.

이것은 엄격한 앨리어싱 규칙 이라고도합니다 . 따라서 다음 코드는 정의되지 않은 동작입니다 .

long x = 5;
double *p = (double *)&x;
double y = *p;

때로는 놀랍게도 다음 사항도 있습니다.

struct foo { int x; };
struct bar { int x; int y; };
struct bar b = { 1, 2};
struct foo *p = (struct foo *)&b;
int z = p->x;

때때로, 당신은 캐스트 포인터에 필요하지만, 주어진 엄격한 앨리어싱 규칙을 , 당신은 매우 신중해야합니다. 따라서 코드에서 포인터 캐스트가 발생하면 유효성을 다시 확인해야합니다 . 따라서 불필요한 포인터 캐스트를 작성하지 마십시오.

tl; dr

한마디로 : C에서, 때문에 어떤 의 발생 포인터 캐스트는 특별한주의를 필요로하는 코드에 대한 붉은 깃발을 제기해야합니다, 당신은 쓸 안 불필요한 포인터 캐스트를.


사이드 노트 :

  • 예를 들어 포인터를 인쇄하려는 경우 실제로 캐스트가 필요한 경우가 있습니다 void *.

    int x = 5;
    printf("%p\n", (void *)&x);

    여기에는 캐스트 printf()함수 가 필요하기 때문에 캐스트가 필요 하므로 암시 적 변환은 작동하지 않습니다.

  • C ++에서는 상황이 다릅니다. 파생 클래스의 객체를 처리 할 때 포인터 유형을 캐스팅하는 것이 다소 일반적이며 정확합니다. 따라서 C ++에서는 변환 void *이 암시 적이 지 않습니다 . C ++에는 다양한 종류의 캐스팅이 있습니다.


1
귀하의 예에서는 void *를 피하십시오. double *에서 int *로 캐스트하는 것과 그 반대의 차이가 있습니다. malloc은 가장 큰 표준 유형으로 정렬 된 pointel을 리턴하므로 누군가가이 정렬 된 포인터를 다른 유형으로 캐스트하더라도 앨리어싱 규칙이 깨지지 않습니다.
P__J__

앨리어싱은 정렬 및 나머지 의견과 전혀 관련없습니다 . 분명히 요점을 얻지 못했습니다.

@ PetetJ : 경우에 따라 요점은 불필요한 포인터 캐스트 를 피하는 것이므로 특별한주의를 기울여야하는 코드 조각 처럼 보이지 않습니다 .

엄격한 앨리어싱 문제는 실제로 void 포인터와 관련이 없습니다. 엄격한 앨리어싱 위반으로 인한 버그를 얻으려면 지정된 데이터를 참조 해제해야합니다. 그리고 void 포인터를 역 참조 할 수 없기 때문에 그러한 버그는 정의에 따라 void 포인터와 관련이 없지만 다른 것입니다.
Lundin

오히려 모든 포인터 캐스트를 금지하는 규칙을 만들어야합니다. 그러나 직렬화 루틴 및 하드웨어 관련 프로그래밍과 같은 것을 어떻게 작성 하시겠습니까? C의 힘인 것들. 당신이하는 일을 알고 있다면 그러한 캐스트는 괜찮습니다.
Lundin

15

나는 캐스트를 선호하지만 수동으로하지는 않습니다. 내가 제일 좋아하는 사용 g_newg_new0입심에서 매크로. glib를 사용하지 않으면 비슷한 매크로를 추가합니다. 이러한 매크로는 형식 안전성을 손상시키지 않으면 서 코드 중복을 줄입니다. 유형이 잘못되면 무효가 아닌 포인터 사이에 암시 적 캐스트가 발생하여 경고가 발생합니다 (C ++의 오류). 당신이 정의하는 헤더를 포함하는 것을 잊지 경우 g_newg_new0, 오류를 얻을 것입니다. g_newg_new0는 달리 모두 동일한 인수를 malloc그보다 적은 수의 인수를 취합니다 calloc. 00으로 초기화 된 메모리를 얻으려면 추가하십시오 . 코드는 변경없이 C ++ 컴파일러로 컴파일 할 수 있습니다.


12

캐스팅은 C가 아닌 C ++ 전용입니다. C ++ 컴파일러를 사용하는 경우 C 컴파일러로 변경하는 것이 좋습니다.


9

void 포인터의 개념은 malloc이 void를 리턴하는 이유는 모든 데이터 유형으로 캐스트 될 수 있다는 것입니다. 또한 자동 유형 변환에 대해서도 알고 있어야합니다. 따라서 반드시 포인터를 캐스트해야하는 것은 아닙니다. 코드를 깨끗하게 유지하고 디버깅을 도와줍니다.


11
" 필수 사항은 아니지만 반드시해야합니다 "-모순이 있다고 생각합니다!
Toby Speight

5
나는 당신이 누군가에게이 게시물을 읽고 그들이 당신이 말하려는 것을 이해하는지 확인해야한다고 생각합니다. 그런 다음 다시 작성하여 원하는 말을 분명히하십시오. 나는 당신의 대답이 무엇인지 이해할 수 없습니다.
Bill Woodger

9

void 포인터는 일반 포인터이며 C는 void 포인터 형식에서 다른 형식으로의 암시 적 변환을 지원하므로 명시 적으로 형식을 변환 할 필요가 없습니다.

그러나 암시 적 변환을 지원하지 않는 C ++ 플랫폼에서 동일한 코드가 완벽하게 호환되도록하려면 형식 캐스팅을 수행해야하므로 사용성에 따라 달라집니다.


9
  1. 다른 언급했듯이 C에는 필요하지 않지만 C ++에는 필요합니다.

  2. 캐스트를 포함하면 C 프로그램 또는 함수가 C ++로 컴파일 될 수 있습니다.

  3. C에서는 void *가 다른 포인터 유형으로 자동으로 안전하게 승격되므로 불필요합니다.

  4. 그러나 캐스팅하면 stdlib.h 포함을 잊어 버린 경우 오류를 숨길 수 있습니다 . 이로 인해 충돌이 발생할 수 있습니다.

    stdlib.h 에 malloc의 프로토 타입이 포함되어 있기 때문에 찾을 수 있습니다. malloc에 ​​대한 프로토 타입이없는 경우, 표준은 C 컴파일러가 malloc이 int를 리턴한다고 가정해야합니다. 캐스트가 없으면이 정수가 포인터에 지정 될 때 경고가 발행됩니다. 그러나 캐스트에서는 버그를 숨기고이 경고가 생성되지 않습니다.


7

malloc의 캐스팅은 C에서는 필요하지 않지만 C ++에서는 필수입니다.

C에서는 다음과 같은 이유로 캐스팅이 필요하지 않습니다.

  • void * C의 경우 다른 포인터 유형으로 자동으로 안전하게 승격됩니다.
  • 포함하지 않은 경우 오류를 숨길 수 있습니다 <stdlib.h>. 충돌이 발생할 수 있습니다.
  • 포인터와 정수의 크기가 다른 경우 캐스팅하여 경고를 숨기고 반환 된 주소의 비트가 손실 될 수 있습니다.
  • 선언에서 포인터의 유형이 변경되면 malloc호출 및 캐스트 되는 모든 행을 변경해야 할 수도 있습니다 .

반면, 캐스팅은 프로그램의 이식성을 증가시킬 수 있습니다. 즉, C 프로그램 또는 함수를 C ++로 컴파일 할 수 있습니다.


0

나를 위해, 테이크 홈 여기 결론은 캐스팅이다 mallocC에서 것은 완전히 필요는 없지만 당신은 그러나 캐스팅 경우, 그 영향을 실 거예요 malloc으로 malloc여전히 당신에게 요청한 축복 메모리 공간을 할당합니다. 사람들이 캐스팅하는 이유 또는 이유 중 하나는 C 또는 C ++에서 동일한 프로그램을 컴파일 할 수 있도록하는 것입니다.

다른 이유가있을 수 있지만, 거의 확실하게 다른 이유는 조만간 심각한 문제에 빠질 것입니다.


0

C로 캐스트 할 필요는 없지만 C로 캐스트 할 필요는 없습니다. 해당 코드가 C ++로 컴파일 된 경우 캐스트해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.