구조체 자체가 아닌 구조체의 첫 번째 요소 주소를 사용하는 이유는 무엇입니까?
개발자가 구조체 자체가 아닌 복사 / 비교 / 설정할 때 구조체의 첫 번째 요소 주소를 일관되게 사용하는 또 다른 코드 기반을 방금 작성했습니다. 여기에 간단한 예가 있습니다.
먼저 구조체 유형이 있습니다.
typedef struct {
int a;
int b;
} foo_t;
그런 다음 이러한 구조체의 복사본을 만드는 함수가 있습니다.
void bar(foo_t *inp)
{
foo_t l;
...
memcpy(&l.a, &inp->a, sizeof(foo_t));
...
}
나는 memcpy
그런 식으로 호출을 작성 하지 않았고 원래 개발자가 단순히 C에서 포인터와 구조체를 잘 이해하지 못했다고 의심하기 시작했습니다. 그러나 이제는 관련없는 두 개의 코드베이스에서 이것을 보았습니다. 일반 개발자이므로 의심하기 시작했습니다.
왜이 스타일을 사용하고 싶습니까?
아무도 그렇게해서는 안됩니다. 구조체 멤버를 재 배열하면 문제가 발생합니다.
그 대신에:
memcpy(&l.a, &inp->a, sizeof(foo_t));
그렇게 할 수 있습니다.
memcpy(&l, inp, sizeof(foo_t));
위험하고 오해의 소지가있을 수 있지만 C가 첫 번째 구조체 멤버 앞에 패딩이 없음을 보장하므로 두 문 모두 실제로 여기서 동일한 작업을 수행합니다.
그러나 가장 좋은 방법은 간단한 할당 연산자를 사용하여 구조 객체를 복사하는 것입니다.
l = *inp;
왜이 스타일을 사용하고 싶습니까?
내 추측으로는 무지 또는 나쁜 징계.
하나는 그렇지 않습니다. a
구조체에서 이동 했거나 이전 에 멤버를 삽입 한 경우 메모리 스매싱 버그가 발생합니다.
이 코드는 구조체 멤버를 재 배열 memcpy
하면 멤버 a
가 더 이상 첫 번째 멤버가 아닌 경우 구조체 경계를 넘어 액세스 할 수 있으므로 안전 하지 않습니다.
그러나 멤버는 의도적으로 구조체 내에서 정렬되고 프로그래머 는 멤버로 시작a
하여 구조체가 끝날 때까지 실행 되는 하위 집합 만 복사하려고 할 수 있습니다 . 이 경우 다음 변경으로 코드를 안전하게 만들 수 있습니다.
memcpy(&l.a, &inp->a, sizeof(foo_t) - offsetof(foo_t, a));
이제 구조체 멤버는 임의의 순서로 재 배열 될 수 있으며 memcpy
절대 범위를 벗어나지 않습니다.
정말 나쁜 습관입니다. 예를 들어 구조체에는 다른 멤버가 추가 될 수 있습니다. 이것은 엄청나게 부주의 한 습관이고 누구든지 이것을 할 것이라는 사실을 읽고 놀랐습니다.
다른 사람들은 이미 이것을 언급했습니다. 나를 괴롭히는 것은 다음과 같습니다.
struct Foo rgFoo [3];
struct Foo *pfoo = &rgFoo [0];
대신에
struct Foo *pfoo = rgfoo;
인덱스로 배열을 역 참조한 다음 주소를 다시 가져 오는 이유는 무엇입니까? 이미 주소입니다. 주목할만한 유일한 차이점은 pfoo가 기술적으로
struct Foo *const,
아니
struct Foo *.
그러나 나는 항상 첫 번째 것을 보곤했다.
실제로 이것에 대한 합법적 인 사용 사례가 하나 있습니다 : 클래스 계층 구조 구축.
구조체를 클래스 인스턴스로 취급 할 때 첫 번째 멤버 (예 : 오프셋 0)는 일반적으로 수퍼 유형 인스턴스입니다. 수퍼 유형이 존재하는 경우. 이를 통해 간단한 캐스트가 하위 유형과 상위 유형 사용 사이를 이동할 수 있습니다. 매우 유용한.
의도에 대한 Darren Stone의 메모 에서 이는 C 언어로 OO를 실행할 때 예상 됩니다.
다른 경우에는 이미 인용 된 이유로이 패턴을 피하고 대신 회원에게 직접 액세스하는 것이 좋습니다.
'IT Share you' 카테고리의 다른 글
Hadoop의 메모리 부족 오류 (0) | 2020.12.06 |
---|---|
css : 처음 깜박일 때 이미지 호버링 방지 (0) | 2020.12.06 |
집계 함수가없는 GROUP BY (0) | 2020.12.06 |
Android Studio : UTF-8 인코딩에 매핑 할 수없는 문자 (0) | 2020.12.06 |
임의 키에 대한 Java Lambda Stream Distinct ()? (0) | 2020.12.06 |