문제

이 질문, 누군가가 제안서 comment 캐스트의 결과이 malloc, 즉

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

보다:

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

왜 이러한 경우가?

도움이 되었습니까?

해결책

아니; 너 ~하지 않다 이후 결과를 캐스팅하십시오.

  • 불필요합니다 void * 이 경우 다른 포인터 유형으로 자동이고 안전하게 홍보됩니다.
  • 코드에 혼란을 더하고 캐스트는 읽기가 쉽지 않습니다 (특히 포인터 유형이 길면).
  • 그것은 당신을 자신을 반복하게 만듭니다. 일반적으로 나쁘다.
  • 포함하는 것을 잊어 버린 경우 오류를 숨길 수 있습니다. <stdlib.h>. 이로 인해 충돌이 발생할 수 있습니다 (또는 더 나쁘게 ~ 아니다 코드의 완전히 다른 부분에서 나중에 진행될 때까지 충돌이 발생합니다). 포인터와 정수의 크기가 다르면 어떻게되는지 고려하십시오. 그런 다음 캐스팅하여 경고를 숨기고 반환 된 주소의 비트를 잃을 수 있습니다. 참고 : C11의 암시 적 함수는 C에서 사라졌으며, 노출되지 않은 함수가 반환된다는 자동 가정이 없기 때문에이 시점은 더 이상 관련이 없습니다. int.

설명으로, 나는 "당신은 캐스팅하지 않는다"고 말했지만 "당신은"당신은 필요 캐스트 ". 내 생각에, 캐스트를 포함시키지 못하는 것은, 당신이 그것을 제대로 얻었더라도 캐스트를 포함시키는 것은 실패입니다. 위험에 대해.

또한 주석가들이 지적한 바와 같이, 위의 내용은 C ++가 아닌 직선 C에 대해 이야기한다는 점에 유의하십시오. 나는 C와 C ++를 별도의 언어로 매우 굳게 믿습니다.

추가로 코드가 불필요하게 유형 정보를 반복합니다 (int) 오류가 발생할 수 있습니다. 리턴 값을 저장하는 데 사용되는 포인터를 반복하는 것이 좋습니다.

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

이것은 또한 움직입니다 length 가시성을 높이기 위해 앞면으로, 중복 괄호를 떨어 뜨립니다. sizeof; 그들 필요합니다 인수가 유형 이름 일 때. 많은 사람들이 이것을 알지 못하거나 무시하지 않는 것 같습니다. 기억하다: sizeof 기능이 아닙니다! :)


움직이는 동안 length 전면으로 5월 가시성 증가 일부 드문 경우에는 일반적으로 표현을 다음과 같이 표현하는 것이 더 나을 것이라는 점도주의를 기울여야합니다.

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

유지 한 이후 sizeof 먼저,이 경우 적어도 곱셈이 이루어 지도록합니다. size_t 수학.

비교하다: malloc(sizeof *sieve * length * width) vs. malloc(length * width * sizeof *sieve) 두 번째는 넘어 질 수 있습니다 length * width 언제 width 그리고 length 보다 작은 유형입니다 size_t.

다른 팁

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

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

추가로 표현의 오른쪽을 바꾸는 것에 대해 걱정하지 않아도됩니다. sieve.

사람들이 지적한 것처럼 캐스트는 나쁘다. 특별히 포인터 캐스트.

당신 주기 때문에:

  • 그것은 당신의 코드 휴대용 C 및 C++,그리고 그 경험은 훌륭한 많은 프로그래머는 주장들에서 쓰 C 때 그들은 정말에 쓰는 C++(또는 C 컴파일러 확장자).
  • 그렇지 않을 경우 숨길 수 있습니다류:참고 모든 그래서 예의 혼란 때 쓰 type *type **.
  • 아이디어는 그것이 당신을 유지 못신 #include 적절한 헤더 파일을 그리워 나무의 숲.그것은 동일한으로 말하는"걱정하지 않는 사실에 대해 당신은 실패를 요청한 컴파일러에 대해 불평하지 않고 프로토 타입-그 성가신 stdlib.서 진짜 중요한 것은 기억하십시오!"
  • 그것은 강제 추가 인식 교 확인.그것은(주)원하는 형식 바로 옆에는 연산 당신이 일을 위해 원의 크기는 변수입니다.내가 할 수 있는 그래서 연구하는 것을 보여줍 malloc() 벌레 잡힐 때 훨씬 더 빨리가 있다.과 같이션,주석을 계시하는 의도는 감소 버그가 있습니다.
  • 자신을 반복하는 방식으로 기계를 확인할 수 있습은 종종 생각이 아니다.사실,이는 주장이고,사용이의 캐스팅은 주장하고 있습니다.션은 여전히 대부분의 일반적인 기술을 우리가 얻기를 위해 올바른 코드,이후 Turing 아이디어를 내놓았다 그래서 많은 년 전입니다.

다른 언급 한 바와 같이, 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 ++를 위해 컴파일됩니다.

Wikipedia:

이점을 캐스팅

  • 을 포함하여 캐스팅을 허용할 수 있습 C 프로그램 또는 기능을 컴파일로 C++.

  • 캐스트할 수 있습에 대한 전 1989 년 버전의 malloc 는 원래 반 char*.

  • 주물을 도울 수 있는 개발자를 식별하는 모순에는 유형의 크기 조정해야할 대상 포인터 형식을 변경하는 경우 포인터 선언에서 멀리 malloc()호출이 있지만(현대 컴파일러와 정적 해석기 경고 할 수 있에서 이러한 행동을 요구하지 않고 캐스팅).

단점이 캐스팅

  • 아래에 ANSI C 표준,캐스트 중복되어 있습니다.

  • 추가 캐스트 마스크 수 있습니다 실패 헤더를 포함 stdlib.h, 에 는 프로토타입을 위해 malloc 발견된다.의 부재에서 프로토 타입을 위해 malloc,표준이 요구하는 C 컴파일러 가정 malloc int 를 반환합니다.이 없는 경우 캐스트,경고 발행할 때 이 정수 포인터가 할당된;그러나, 캐스트,이 경고가 생성,숨기는 버그입니다.정 아키텍처 및 데이터 모형(예:LP64 에는 64-bit 시스템 길고 포인터는 64 비트와 int 은 32 비트),이 오류가 있습 실제 결과에서 정의되지 않은 행동,암시적으로 선언 malloc 반 32 비트 값이는 반면 실제로 정의된 기능 반 64 비트 값이다.에 따라 부르는 규칙 및 메모리 레이아웃이 발생할 수 있습택합니다.이 문제를 가능성이 적 을 주목에서 현대적인 컴파일러,그들이 균일하게 생산 는 경고를 선언되지 않은 기능을 사용되었다,그래서 경고 는 여전히 나타납니다.예를 들어,GCC 의 기본 행동을 보여주는 것입 경고를 읽는"호환되지 않는 암시적 선언의 내장 기능"는지 여부에 관계없이 캐스팅은 현재 또는하지 않습니다.

  • 는 경우에는 유형의 포인터 변경에서의 선언을 하나 있습니다 또한,를 변경해야 할 모든 라인 malloc 라고 캐스팅.

malloc 없이 주물이 선호하는 방법과 가장 경험이 풍부한 프로그래머가 선택, 를 사용해야 합 어느 당신이 좋아하는 알고 있습니다.

i.e:필요할 경우를 컴파일하는 C 프로그램으로 C++(지만 사람들은 별도의 언어)에 사용해야 합니다 malloc 으로 캐스팅.

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

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 세의 컴파일러를 사용하겠습니까?

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

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

고대에는, 즉 이전입니다 ansi c 제공 void * 일반적인 유형의 포인터로 char * 그러한 사용법의 유형입니다. 이 경우 캐스트는 컴파일러 경고를 종료 할 수 있습니다.

참조: C FAQ

결과를 캐스팅 해야하는 것은 필수가 아닙니다 malloc, 그것이 돌아 오기 때문에 void* , a void* 모든 데이터 유형을 가리킬 수 있습니다.

단지 내 경험을 추가하고 컴퓨터 공학을 공부하는 것만으로도 C에서 글을 쓰는 두세 교수는 항상 Malloc을 캐스팅했지만 (엄청난 CV와 C에 대한 이해와 함께) 요청한 것은 절대적으로 불필요하다고 말했습니다. 예전에는 절대적으로 구체적이었고 학생들이 절대적으로 구체적이라는 정신을 갖도록했습니다. 본질적으로 캐스팅은 작동 방식에서 아무것도 바뀌지 않으며, 그것이 말하는 것을 정확하게 수행하고, 메모리를 할당하며, 캐스팅이 영향을 미치지 않으며, 같은 메모리를 얻지 못하며 실수로 다른 것에 던져권에도 불구하고 (어떻게 든 컴파일러를 피하십시오. 오류) C도 같은 방식으로 액세스합니다.

편집하다: 캐스팅에는 특정 지점이 있습니다. 배열 표기법을 사용하면 생성 된 코드는 다음 요소의 시작에 도달하기 위해 전진해야 할 메모리 위치를 알아야합니다. 이는 캐스팅을 통해 달성됩니다. 이런 식으로 당신은 두 배의 경우 int 4를 위해 8 바이트를 앞두고 4 등을 가고 있음을 알고 있습니다. 따라서 포인터 표기법을 사용하면 배열 표기법으로 필요한 경우에는 영향을 미치지 않습니다.

이것이 무엇입니다 GNU C 라이브러리 참조 매뉴얼의 말 :

결과를 저장할 수 있습니다 malloc ISO C가 자동으로 유형을 변환하기 때문에 캐스트가없는 포인터 변수로 void * 필요한 경우 다른 유형의 포인터에. 그러나 캐스트는 과제 연산자 이외의 상황에서 또는 Code가 전통적인 C에서 실행되기를 원하는 경우에 필요합니다.

그리고 참으로 ISO C11 표준 (p347)은 그렇게 말합니다.

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

빈 공간 포인터는 일반적인 포인터이며 C는 무효 포인터 유형에서 다른 유형으로 암시 적 변환을 지원하므로 명시 적으로 타입 할 필요가 없습니다.

그러나 암시 적 변환을 지원하지 않는 C ++ 플랫폼에서 동일한 코드가 완벽하게 호환되는 경우 타입 캐스팅을 수행해야하므로 모두 유용성에 따라 다릅니다.

반환 된 유형은 무효*이며, 이는 비 수정 가능한 데이터 포인터로 캐스트 할 수 있습니다.

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 C에서는 캐스트를 입력 할 필요가 없습니다. 자동으로 캐스트를 입력하므로 C ++를 사용하는 경우 CAST를 입력해야합니다. malloc 반환합니다 void* 유형.

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

나는 몇 년 동안 내가 사용해야했던 엄청나게 숙성 된 컴파일러에 의해 꽤 끔찍했습니다. 종종 회사와 관리자는 변화하는 컴파일러에 대한 매우 보수적 인 접근 방식을 채택하며조차도 테스트 새로운 컴파일러 (더 나은 표준 준수 및 코드 최적화)가 시스템에서 작동하는 경우. 작업 개발자를위한 실질적인 현실은 코딩 할 때베이스를 덮어야하며 불행히도 Mallocs 캐스팅은 코드에 어떤 컴파일러를 적용 할 수 있는지 제어 할 수 없다면 좋은 습관이라는 것입니다.

또한 많은 조직이 자신의 코딩 표준을 적용 할 것을 제안합니다. 저것 사람들이 정의 된 경우 사람들이 따르는 방법이어야합니다. 명백한 지침이 없으면 나는 표준에 대한 노예 준수보다는 어디서나 수집 할 가능성이 높다.

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

ymmv.

나는 Malloc을 방어 작전으로 캐스팅하는 경향이 있습니다. 예쁘지 않고 완벽하지는 않지만 일반적으로 안전합니다. (솔직히, 당신이 stdlib.h를 포함시키지 않았다면 당신은 방법 Malloc을 캐스팅하는 것보다 더 많은 문제! ).

나는 유형 시스템의 못생긴 구멍의 비 승인을 보여주기 위해 단순히 캐스트를 넣었습니다.이 시스템은 캐스트가 잘못된 변환을 가져 오는 데 사용되지 않더라도 다음 스 니펫과 같은 코드가 진단없이 컴파일 할 수 있습니다.

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

나는 그것이 존재하지 않았 으면 좋겠다 (그리고 C ++에 있지 않음). 그래서 나는 캐스팅했다. 그것은 내 취향과 프로그래밍 정치를 나타냅니다. 나는 포인터를 캐스팅 할뿐만 아니라 효과적으로 투표 용지를 캐스팅하고 어리 석음의 악마를 캐스팅합니다. 내가 할 수 없다면 실제로 어리 석음을 배치하십시오, 그런 다음 적어도 항의 제스처로 그렇게하려는 소원을 표현하게하십시오.

실제로, 좋은 관행은 포장하는 것입니다 malloc (및 친구)는 반환하는 기능을 갖습니다 unsigned char *, 기본적으로 사용하지 않습니다 void * 코드에서. 일반적인 포인터 간 중수기가 필요한 경우 a를 사용하십시오 char * 또는 unsigned char *, 양방향으로 캐스트를했습니다. 방종 할 수있는 이완은 아마도 다음과 같은 기능을 사용하는 것입니다. memset 그리고 memcpy 캐스트없이.

캐스팅 및 C ++ 호환성 주제에 대해 C 및 C ++로 컴파일되도록 코드를 작성하는 경우 해야합니다 반환 값을 시전하십시오 malloc 다른 것에 할당 할 때 void *), 당신은 스스로 도움이되는 일을 할 수 있습니다. c ++로 컴파일 할 때 C ++ 스타일 캐스트로 번역되는 캐스트에 매크로를 사용할 수 있지만 c : c로 컴파일 할 때 C 캐스트로 줄입니다.

/* 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 그냥 제거하기 위해 const 또는 volatile, 그러나 프로그램은 이제 유형 변환이 관련된 방식으로 변경되며 진단을 받고 원하는 변환을 얻으려면 캐스트 조합을 사용해야합니다.

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

     -Wold-style-cast (C++ and Objective-C++ only)
         Warn if an old-style (C-style) cast to a non-void type is used
         within a C++ program.  The new-style casts (dynamic_cast,
         static_cast, reinterpret_cast, and const_cast) are less vulnerable
         to unintended effects and much easier to search for.

C 코드가 C ++로 컴파일되는 경우이를 사용할 수 있습니다. -Wold-style-cast 모든 사건을 찾는 옵션 (type) 코드에 들어갈 수있는 구문을 주조하고 위의 매크로 중에서 적절한 선택으로 대체하여 이러한 진단을 후속 조치합니다 (또는 필요한 경우 조합).

이 전환 처리는 "Clean C"에서 작업하기위한 단일 최대의 독립형 기술적 정당화입니다. 결합 된 C와 C ++ 방언은 기술적으로 반환 값을 제시하는 것을 정당화합니다. malloc.

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

  1. 모든 경고가 켜진 상태에서 C 컴파일러를 통해 프로그램을 컴파일하십시오. -Wall 모든 오류와 경고를 수정하십시오
  2. 선언 된 변수가 없는지 확인하십시오 auto
  3. 그런 다음 C ++ 컴파일러를 사용하여 컴파일하십시오 -Wall 그리고 -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...

아니, 당신은 결과를 캐스팅하지 않습니다 malloc().

일반적으로, 당신 캐스트하지 마십시오 void *.

그렇게하지 않는 전형적인 이유는 #include <stdlib.h> 눈에 띄지 않을 수 있습니다. C99가 만든 것처럼 지금은 더 이상 문제가되지 않습니다. 암시 적 기능 선언 불법이므로 컴파일러가 C99 이상을 준수하면 진단 메시지가 표시됩니다.

그러나 거기가 있습니다 훨씬 더 강한 이유 불필요한 포인터 캐스트를 소개하지 마십시오.

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

물체는 다음 유형 중 하나를 갖는 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에서 어느 A의 발생 포인터 캐스트 특별한주의가 필요한 코드에 대한 적기를 제기해야합니다. 불필요한 포인터 캐스트.


사이드 메모 :

  • 실제로 당신이 사례가 있습니다 필요 캐스트 void *, 예 : 포인터를 인쇄하려면 :

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

    캐스트는 여기서 필요합니다 printf() 다양한 기능이므로 암시 적 변환이 작동하지 않습니다.

  • C ++에서는 상황이 다릅니다. 파생 클래스의 객체를 다룰 때는 포인터 유형이 다소 일반적이며 정확합니다. 따라서 C ++에서 void * ~이다 ~ 아니다 절대적인. C ++는 다른 맛의 전체 세트를 가지고 있습니다.

나는 캐스트를 선호하지만 수동으로는 그렇지 않습니다. 내가 가장 좋아하는 것은 사용입니다 g_new 그리고 g_new0 glib의 매크로. glib가 사용되지 않으면 비슷한 매크로를 추가합니다. 이러한 매크로는 유형 안전성을 손상시키지 않고 코드 복제를 줄입니다. 유형이 잘못되면 비 전환 포인터 사이에 암시 적 캐스트가 발생하여 경고가 발생합니다 (C ++의 오류). 정의하는 헤더를 포함하는 것을 잊어 버린 경우 g_new 그리고 g_new0, 당신은 오류가 발생합니다. g_new 그리고 g_new0 둘 다 같은 주장과 달리 동일한 주장을합니다 malloc 그것은 논쟁보다 적은 인수를 취합니다 calloc. 그냥 추가하십시오 0 초기화 된 메모리를 얻기 위해. 코드는 변경없이 C ++ 컴파일러로 컴파일 될 수 있습니다.

캐스팅은 C ++에만 해당됩니다. C ++ 컴파일러를 사용하는 경우 C 컴파일러로 더 잘 변경합니다.

Void Pointer의 개념은 Malloc이 void를 반환하는 모든 데이터 유형에 시전 할 수 있다는 것입니다. 또한 자동 타입 캐스팅을 알고 있어야합니다. 따라서 포인터를 캐스팅해야하지만 필수적이지 않습니다. 코드를 깨끗하게 유지하는 데 도움이되고 디버깅에 도움이됩니다.

  1. 다른 언급 한 바와 같이, C에는 필요하지 않고 C ++에 필요합니다.

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

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

  4. 그러나 캐스트되면 포함을 잊어 버린 경우 오류를 숨길 수 있습니다.stdlib.h. 이로 인해 충돌이 발생할 수 있습니다 (또는 더 나쁘게 코드의 완전히 다른 부분에서 나중에 충돌이 발생하지 않습니다).

    왜냐하면 stdlib.h Malloc의 프로토 타입이 포함되어 있습니다. Malloc의 프로토 타입이없는 경우 표준은 C 컴파일러가 Malloc이 int를 반환한다고 가정해야합니다. 캐스트가 없으면이 정수가 포인터에 할당 될 때 경고가 발행됩니다. 그러나 캐스트를 사용하면이 경고가 생성되지 않아 버그를 숨 깁니다.

빈 공간 포인터는 일반적인 포인터이며 C는 무효 포인터 유형에서 다른 유형으로 암시 적 변환을 지원하므로 명시 적으로 타입 할 필요가 없습니다.

그러나 암시 적 변환을 지원하지 않는 C ++ 플랫폼에서 동일한 코드가 완벽하게 호환되는 경우 타입 캐스팅을 수행해야하므로 모두 유용성에 따라 다릅니다.

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

캐스팅은 C에서 불필요합니다.

  • void * C의 경우 다른 포인터 유형으로 자동으로 안전하게 홍보됩니다.
  • 포함하는 것을 잊어 버린 경우 오류를 숨길 수 있습니다. <stdlib.h>. 이로 인해 충돌이 발생할 수 있습니다.
  • 포인터와 정수의 크기가 다르면 캐스트로 경고를 숨기고 반환 된 주소의 비트를 잃을 수 있습니다.
  • 선언에서 포인터 유형이 변경되면 모든 줄을 변경해야 할 수도 있습니다. malloc 호출되고 캐스트됩니다.

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

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