C의 구조체 및 포인터에 대한 malloc


84

벡터의 길이와 그 값을 나타내는 구조를 다음과 같이 정의한다고 가정합니다.

이제 벡터 y를 정의하고 여기에 메모리를 할당한다고 가정합니다.

인터넷을 통한 검색 결과 x에 대한 메모리를 별도로 할당해야한다는 것을 알 수 있습니다.

하지만 y-> x에 메모리를 두 번 할당하는 것 같습니다. 하나는 y에 메모리를 할당하고 다른 하나는 y-> x에 메모리를 할당하면서 메모리 낭비로 보입니다. 컴파일러가 실제로하는 일과 y와 y-> x를 모두 초기화하는 올바른 방법이 무엇인지 알려 주시면 대단히 감사하겠습니다.

미리 감사드립니다.


5
paxdiablo가 저명하게 지적했듯이 malloc()C에서 의 반환 값을 캐스팅하지 마십시오 . 왜 모든 사람이 그렇게해야한다고 느끼는지 이해하지 못할 것입니다. :(
2013

14
@unwind, 아마도 그들은 C로 업그레이드하는 오래된 C ++ 프로그래머
paxdiablo

@unwind C 코드에서 Nvidia의 nvcc 컴파일러를 사용할 때 malloc의 결과를 캐스트하지 않으면 오류가 발생합니다.
Nubcake

@Nubcake 이 링크 에 따르면 nvcc는 CUDA 인터페이스가 C ++이기 때문에 C ++ 모드에서 기본 컴파일러를 실행하기 때문일 수 있습니다. C에서는 이에 대한 오류가 발생하지 않습니다. C ++ void *에서는 다른 포인터로 자동으로 변환되지 않으며 캐스트가 필요합니다 ( malloc()물론 C ++에서는 사용하지 마십시오 ).
언 와인드

@unwind 네, 나중에 이것에 대해 발견했습니다. :) 결과를 캐스팅하지 않으면 오류가 발생하는 상황을 말하고 싶었습니다.
Nubcake 17

답변:


156

아니요, 메모리를 두 번 할당 하지 않습니다y->x .

대신 (포인터 포함) 구조에 대한 메모리를 할당하고 플러스 를 차례로 그 포인터를 위해 무언가를.

다음과 같이 생각하십시오.

따라서 실제로 모든 것을 저장 하려면 두 개의 할당 ( 12)이 필요합니다 .

추가적으로, 당신의 타입은 struct Vector *y포인터이기 때문에 절대로 mallocC 에서 반환 값을 캐스트해서는 안됩니다. 숨기고 싶지 않은 특정 문제를 숨길 수 있기 때문입니다. C는 void*반환 값을 다른 포인터로 암시 적으로 변환 할 수 있습니다.

물론 다음과 같이 벡터를보다 쉽게 ​​관리 할 수 ​​있도록 이러한 벡터 생성을 캡슐화하고 싶을 것입니다.

이와 같이 창조물을 캡슐화함으로써 벡터가 완전히 빌드되었는지 또는 전혀 빌드되지 않았는지 확인합니다. 벡터가 절반으로 빌드 될 가능성이 없습니다. 또한 클라이언트에 영향을주지 않고 향후 기본 데이터 구조를 완전히 변경할 수 있습니다 (예를 들어, 속도를 위해 공간을 절충하기 위해 희소 배열로 만들려는 경우).


28
내 ASCII 아트 skillage :-)에 떨게
paxdiablo의

매우 감사합니다. 정말 도움이됩니다.
Pouya 2013

1
경우에 (RETVAL == NULL) RETVAL는 RETVAL되어야
부대 Daeth

5

처음에는에 대한 메모리를 할당합니다 Vector. 이는 변수 x, 를 의미합니다 n.

그러나 x 아직 유용한 것은 없습니다 .

그래서 두 번째 할당도 필요합니다 .


3

몇 가지 포인트

struct Vector y = (struct Vector*)malloc(sizeof(struct Vector)); 틀렸다

에 대한 포인터를 보유하고 있기 struct Vector *y = (struct Vector*)malloc(sizeof(struct Vector));때문에 .ystruct Vector

1st malloc()는 Vector 구조 (double + int에 대한 포인터)를 보유하기에 충분한 메모리 만 할당합니다.

두 번째는 malloc()실제로 메모리를 할당하여 10을 두 배로 유지합니다.


2

실제로 벡터와 배열을 동시에 할당하여 단일 malloc에서이를 수행 할 수 있습니다. 예 :

이것은 Vector 'y'를 할당 한 다음, y-> x가 Vector 구조체 바로 뒤에 할당 된 추가 데이터를 가리 키도록합니다 (그러나 동일한 메모리 블록에 있음).

벡터의 크기를 조정해야하는 경우 권장되는 두 가지 할당으로 수행해야합니다. 내부 y-> x 배열은 벡터 구조체 'y'를 그대로 유지하면서 크기를 조정할 수 있습니다.


왜 char에 cast y를 입력 했습니까? (double *) y + sizeof (struct Vector)가 아닌 이유는 무엇입니까?
Vishnu Prasath 2014

sizeof는 구조체 크기를 바이트 단위로 반환하고 포인터 산술 '+'연산자는 'y'포인터에 sizeof ( y)의 배수를 추가합니다 . 위와 같이했다면 y는 sizeof (double) * sizeof (struct)만큼 증가 할 것입니다. 문자 Y를 주조 는 sizeof (문자) *는 sizeof (구조체) = 1 *를 sizeof (구조체)에 의해 우리에게 증가 Y를 할 수 있습니다
PQuinn

2

원칙적으로 이미 올바르게하고 있습니다. 당신이 원하는 것을 위해 두 개의 malloc()s 가 필요합니다 .

몇 가지 의견 :

해야한다

첫 번째 줄에서는 Vector 객체에 대한 메모리를 할당합니다. malloc()할당 된 메모리에 대한 포인터를 반환하므로 y는 벡터 포인터 여야합니다. 두 번째 줄에서는 10 개의 double 배열에 메모리를 할당합니다.

C에서는 명시 적 캐스트가 필요하지 않으며, sizeof *y대신 쓰는 것이 sizeof(struct Vector)유형 안전성에 더 좋으며 입력 비용을 절약합니다.

구조체를 재정렬하고 다음과 malloc()같이 단일 작업을 수행 할 수 있습니다 .


"입력시 절약"은 프로그래밍 결정에 유효한 인수가 아닙니다. * y를 취하는 진짜 이유는 안전상의 이유로 해당 변수에 필요한만큼의 공간을 할당하도록합니다.
Lundin 2013

내 대답을 업데이 트했습니다 @Lundin하지만 나에게 "형 안전"인수는 거의 쓰기와 같은 리그if(NULL == foo)
Wernsey

당신은 사용하는 설교자 sizeof *y입니다. 다른 인수없이 5 자 이하 (sizeof * y 대 sizeof (Vector))를 입력하기 위해서만 수행한다면 키보드에 5 자 문자를 입력하는 작업이 큰 장애물임을 발견했기 때문일 것입니다. 프로그램은 키보드 입력의 전체 많이 포함하기 때문에 그리고 만약 그렇다면, 아마도 ..., 경력의 또 다른 선택을 고려
룬딘

@Lundin Writing sizeof *ysizeof(Vector)의도했을 때 쓰기와 같은 오류를 방지하는 데 도움이됩니다 sizeof(Matrix). 그런 실수를 얼마나 자주 하시나요? 그렇게 할 때 얼마나 빨리 찾아서 수정합니까? 나는 그것이 유형의 안전을 증가 동의, 나는 쓰기를 할 sizeof *y내 자신의 코드에 있지만은 거의 쓰기로 편집증 환자로 if(NULL == foo)온 오타를 방지하기 위해 ==.
Wernsey 2013

1
@ShmuelKamensky 그들은 기능적으로 동일합니다. y인에 대한 포인터 struct Vector너무 sizeof *y너무, "무엇을 Y 점의 크기"를 말하고있다 sizeof struct Vector.
Wernsey

1

메모리를 할당 할 때 struct Vector포인터 x, 즉 주소를 포함하는 값이 배치되는 공간에 대한 메모리를 할당하면 됩니다. 따라서 y.x참조 할 블록에 메모리를 할당하지 않습니다 .


1

첫 번째 malloc은 x (double에 대한 포인터)에 대한 메모리를 포함하여 struct에 대한 메모리를 할당합니다. 두 번째 malloc은 x가 가리키는 double 값에 대한 메모리를 할당합니다.


0

malloc(sizeof(struct_name))구조체의 전체 크기에 대해 자동으로 메모리를 할당 할 때 내부의 각 요소를 malloc 할 필요가 없습니다.

-fsanitize=address프로그램 메모리를 어떻게 사용했는지 확인 하려면 플래그를 사용하십시오.


잘못된. x는 포인터 일 뿐이며 x가 가리키는 값에 대한 메모리를 할당해야합니다. 자세한 내용은 다른 답변을 읽으십시오. (예 : stackoverflow.com/a/14768280/5441253 )
Maxime Ashurov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.