sizeof 스타일 : sizeof (type) 또는 sizeof 변수?


22

sizeof메모리 관련 작업 에 사용 하는 두 가지 스타일 (예 : in memset또는 malloc)을 보았습니다 .

  • sizeof(type),
  • sizeof variable 또는 sizeof(variable)

어떤 스타일을 선호하거나 두 스타일을 혼합하여 사용하고 언제 각 스타일을 사용 하시겠습니까? 각 스타일의 장단점은 무엇입니까?

예를 들어, 한 스타일이 도움이되고 다른 스타일이 도움이되지 않는 다음 상황 쌍을 볼 수 있습니다.

포인터 간접 지정을 얻었을 때 :

type *var;
...
memset(var, 0, sizeof var);    /* oops */

유형이 변경 될 때 :

new_type var;    /* changed from old_type to new_type */
...
memset(&var, 0, sizeof(old_type));    /* oops */

답변:


30

나는 sizeof(variable)이상한다 sizeof(type). 치다:

int a1;
float a2;
memset(&a1,0,sizeof(a1));
memset(&a2,0,sizeof(a2));

vs.

int a1;
float a2;
memset(&a1,0,sizeof(int));
memset(&a2,0,sizeof(float));

첫 번째 경우에는 올바른 크기가로 전달되고 있는지 쉽게 확인할 수 memset있습니다. 두 번째 경우, 상단과 하단을 지속적으로 검토하여 일관성을 유지해야합니다.


4
또한 변수 유형을 변경하면 유형을 가정하는 코드가 변경되어야합니다. 가능한 한 유형에 거의 의존하지 않고 올바른 코드를 작성하는 것이 바람직하다고 생각합니다. (저는 하루에 큰 16 비트에서 32 비트로 변환하는 프로젝트의 영향을받습니다.)
로봇 Gort 로봇

이것은 typedef를 작성하는 것이 일반적이지 않지만 char array [MAX_SIZE]와 같은 것을 사용하는 C 배열 작업에 바람직합니다.
mattnz

@ vy32 : 잘못된 1 : "sizeof (array)는 배열의 크기를 반환하지 않습니다 ... 배열에 대한 포인터의 크기" - array실제로 C 배열 인 sizeof(array)경우 배열 요소를 저장하는 데 필요한 바이트 수 를 반환합니다. . array붕괴 된 C 배열의 첫 번째 요소에 대한 포인터 인 경우 명령문이 유지됩니다. C 배열을 함수 인수로 전달하면 함수에서 포인터처럼 보입니다. 크기와 같은 배열임을 증명하는 모든 정보가 손실됩니다. 그것이 부패한 이유 입니다. 잘못된 2 : "어레이는 실제로 C에는 존재하지 않습니다. ... 포인터에 대한 구문 설탕입니다."
Johann Gerell 2009 년

9

선호는 (항상처럼) 가능한 한 직접적으로 당신의 의도를 반영하는 것입니다.

기존 변수의 메모리에 대해 작동하려는 의도입니까? 그렇다면을 사용 sizeof(variable)하십시오.이 변수는 관심있는 변수 자체의 메모리임을 가능한 한 가깝게 보여줍니다.

예를 들어 새 인스턴스에 할당 할 메모리 양을 결정하기 위해 유형에 대한 계산을 수행 할 의도입니까? 그렇다면을 사용하십시오 sizeof(type).

즉, 나는 선호

struct foo *bar;
bar = (struct foo *) malloc(sizeof(struct foo));

위에

bar = (struct foo *) malloc(sizeof(*bar));

후자의 경우 아직 존재하지 않는 변수에 액세스하려고하는 것처럼 보입니다 .

반면에, 나는 선호

char Buffer[256];
memset(Buffer, 0, sizeof(Buffer));

위에

char Buffer[256];
memset(Buffer, 0, 256 * sizeof(char));

의도적으로 변수의 내용을 0으로 채우는 것이 목적이므로 우리가 조작해야 할 변수입니다. 메타 데이터 형식을 사용하려고하면 혼동을 일으 킵니다.



항상 그렇습니다.하지만 그것은 개인적인 취향의 문제입니다. 의 void *포인터가 다른 포인터 유형으로 자동 캐스팅되어 잘못된 기능이라고 생각합니다.
Aidan Cully

3

나는 훨씬 더 선호 sizeof(type)합니다 sizeof variable. 유형에 대해 더 많이 걱정하고 더 많은 변경을하도록 강요하더라도 C에서 버그의 가장 흔한 원인 중 하나 인 포인터 간접 오류를 피하는 데 도움이됩니다 .

타입 sizeof(type)이 바뀌는 버그에 대해서는 크게 걱정하지 않습니다 . 변수 유형을 변경할 때마다 해당 변수가 사용되는 위치와 sizeof(type)명령문 을 변경해야하는지 확인하기 위해 빠른 스캔을 수행해야 합니다. 이 오류가 항상 발생할 가능성은 있지만 포인터 간접 실수보다 훨씬 낮은 위험이 있습니다.

한 가지 장점은 sizeof variable배열에 대한 것이지만 실제로는 배열을 first / len 쌍으로 전달하는 것이 훨씬 일반적이며 (이 경우 길이를 사용하는 것) 또한 크기 때문에 잘못된 크기를 얻는 것이 매우 쉽다는 것을 알았습니다 이 예제에서와 같이 배열 / 포인터 붕괴 :

ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) {
  memcpy( mat, src, sizeof( src ) );    /* NOT the same as 3*3*sizeof(float) */
}

2
"그 변수가 사용되는 곳을 확인하기위한 빠른 스캔 .... 항상 잘못 될 가능성이있다"-나에게 이것은 sizeof (type)을하는 가장 큰 위험이다. 이 위험의 최종 결과는 모든 것이 여전히 컴파일 될 수 있고 실수를 저 지르더라도 1 년 이상이 걸리거나이를 발견하기 전에 임의의 충돌 및 버퍼 손상이 발생할 수 있다는 것입니다. 그리고이 질문과 "포인터 간접 실수"사이에 연결을 만들 수 없었습니다 (물론 내 질문 시간은 약 30 초입니다).
DXM

@DXM sizeof 피연산자의 경우 값이면 다음과 같습니다 sizeof var. 포인터 인 경우 sizeof *var입니다. 이것은 사람들이 잘못 할 수있는 것이기도하며 컴파일러는 불만없이 행복하게 그것을 취할 것입니다. 나는 이러한 실수들이 sizeof(type)형태의 실수들보다 발견하기가 훨씬 더 어렵고 더 일반적이라고 주장한다 .
congusbongus

1
당신의 권리-C 유형과 sizeof 연산자는 근본적으로 손상되어 신뢰할 수 없으며 프로그래머가 할 수있는 일은 없습니다.
mattnz

게시물에 태그가 지정 C되면 C 코드를 게시하는 것이 C ++ 코드와 같은 정보를 제공합니다 mat3_t::mat3_t(...).
chux-복원 Monica Monica

0

목표는 중복성을 제거하는 것입니다. 변수와 관련된 연산에 sizeof를 사용한다면 분명히 sizeof에이를 반영해야합니다. 예, 첫 번째 예와 같이 엉망이 될 수 있지만 치료법은 type이 아니라 * var이며 목표와 정확하게 일치합니다.

이러한 문제를 완화하기 위해 매크로, 템플릿 및 유사한 도구를 사용하지 않고 사용 사례에 맞게 훈련하는 것이 일반적입니다.

벌거 벗은 memset 대신 독점적으로 사용되는 CLEAR 매크로 를 참조하십시오 . 간접 오타의 경우 또는 구조체 내용이 벡터 또는 문자열을 선택했을 때 내 엉덩이를 여러 번 저장했습니다 ...


그와 같은 매크로는 C의 매크로 프로그래밍에 나쁜 이름을주었습니다 ...
mattnz

@ mattnz : 더 나은 대안을 보여주십시오. 실제로 작동하는 프로그램을 만드는 것보다 추상적 인 내용을 말하는 것이 더 쉽습니다.
Balog Pal

1
링크 된 매크로는 C ++ 이며이 게시물에는 'C'(다른 언어 임)라는 태그가 붙어 있습니다. Ada가 제 제안입니다.
mattnz

@mattnz : 그리고 같은 주제는 C에 대해 비슷한 방법으로 시행하는 방법을 보여줍니다. 요점을 완전히 놓친 것 같습니다. 실제 콘텐츠 구현이 아니라 원시에 비해 더 안전한 사용법입니다. Btw도 읽을 수 있습니다.
Balog Pal

0

비즈니스 로직은 선택을 정의합니다.

  1. 코드가 특정 변수를 참조하고이 변수가 없으면 코드가 의미가 없습니다. sizeof(var)

  2. 코드가 특정 유형의 변수 세트를 처리하는 경우 선택하십시오 sizeof(type). 일반적으로 typedef유형에 따라 다르게 처리하는 많은 변수를 정의 하는 경우 (예 : 직렬화)이를 필요로합니다. 향후 코드 버전에서 어떤 변수가 남아 있는지 알지 못할 수 있으므로 유형을 인수로 선택하면 논리적으로 정확합니다. 이러한 변경이라도 typedef라인 크기에는 영향을 미치지 않습니다.


-1

목적에 따라 sizeof (variable)가 최선의 해결책이 될 수 있습니다. 그런 식으로 필요한 경우 유형의 모든 항목을 수정하지 않고 변수 유형을 변경할 수 있습니다. 그러나 다시, 그것은 당신의 목표에 달려 있습니다.

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