C로만 배열을 포함하는 구조체를 선언하는 이유는 무엇입니까?


131

다음을 포함하는 코드를 발견했습니다.

struct ABC {
    unsigned long array[MAX];
} abc;

이런 선언을 언제 사용하는 것이 합리적입니까?

답변:


184

배열을 값으로 함수에 전달하거나 함수에서 값으로 반환 할 수 있습니다.

이러한 맥락에서 포인터로 붕괴되는 배열과 달리 Structs는 값으로 전달 될 수 있습니다.


1
인라인되지 않은 함수에 대해 16 바이트 또는 32 바이트 이상의 배열로이 작업을 수행하는 것에주의하십시오. 호출자가 이미 tmp 사본을 필요로하지 않는 한 const 참조로 전달하는 것이 더 효율적입니다. 호출 / 반환이 최적화되지 않으면 중간에서 큰 배열 (수천 바이트)이 값을 전달하는 끔찍한 일입니다.
Peter Cordes

85

또 다른 장점은 크기를 추상화 [MAX]하여 객체를 선언 하는 모든 위치에서 코드 전체 를 사용할 필요가 없다는 것 입니다. 이것은 또한 달성 될 수있다

typedef char ABC[MAX];

그러나 훨씬 더 큰 문제가 있습니다 : ABC배열 유형 이라는 것을 알아야합니다 (type 변수를 선언 할 때 이것을 볼 수는 없지만 ABC) 그렇지 않으면 다른 ABC것을 의미한다는 사실에 찔릴 것입니다 함수 인수 목록과 변수 선언 / 정의에서.

또 다른 장점은 구조체를 사용하면 많은 코드를 다시 작성할 필요없이 필요한 경우 나중에 더 많은 요소를 추가 할 수 있다는 것입니다.


45

구조체를 복사하고 함수에서 구조체를 반환 할 수 있습니다.

구조체의 일부가 아닌 한 배열로는 그렇게 할 수 없습니다!


26

이렇게 복사 할 수 있습니다.

struct ABC a, b;
........
a = b;

배열의 경우 memcpy 함수 또는 루프를 사용하여 각 요소를 할당해야합니다.


6
(따라서 깔끔한 코드를 만들 수 있습니다
John Carter

3
유용합니다. 불행히도 (a == b)!?! 얼마나 일관성이 없습니다. C ++의 경우 == 연산자를 찾습니다. C에서는 "이진수 =="에 유효하지 않은 피연산자입니다.
Matt

11

struct를 사용하여 string 과 같은 새로운 유형의 데이터를 만들 수 있습니다 . 당신은 정의 할 수 있습니다 :

struct String {
    char Char[MAX];
};

또는 함수의 인수로 사용하거나 메소드에서 리턴 할 수있는 데이터 목록 을 작성할 수 있습니다. 구조체는 =와 같은 일부 연산자를 지원할 수 있고 배열에 메소드를 정의 할 수 있기 때문에 배열보다 유연합니다.

그것이 당신에게 유용하기를 바랍니다 :)


2
기본적으로 C가 클래스를 만드는 가장 가까운 것입니다. 나는이 대답을 가장 좋아하기 때문에 그것을 좋아합니다.
네이트 CK

1
C의 메소드와 같은 것은 C의 구조체가 평범한 오래된 데이터가 아닙니다. 하지 C. ++는 (다른 답변이 작업을 수행 할 수있는 이유는 보여) 기본 의해 지원 = 연산자를 가지고 있지만, 이것은 오해의 소지가 있으며 대부분은 C에 적용
조나단 스턴 버그

3
@J Sternberg : "방법"은 서브 루틴이 데이터 "객체"와 관련이 있다고 생각하는 방법입니다. C로 동작하는 "객체"와 "방법"의 "클래스"를 확실히 만들 수 있습니다. 언어는 그러한 것들을 공식적으로 정의하지 않습니다. C에서 더 나은 추상화를 만들고 싶다면 구조체에 물건을 채우는 것이 일반적으로 가장 좋은 방법입니다.
네이트 CK

또한 C에서 메소드를 "만들기"를 원한다면 함수 포인터 (예, 예, 까다로운 구문, 데이터 보호 없음 등)를 사용하여 함수를 작동하는 데이터와 연관시킬 수 있습니다. C의 함수 내부 에이 포인터가 자동으로 생성되지 않기 때문에 첫 번째 인수에서 "self"를 전달해야합니다 (원하는 경우 "this"라고도 할 수 있습니다). 물론 체조입니다. C ++에서는 기본적으로 이와 같은 것들이 있지만, 보너스로 숨겨진 오버 헤드가있을 수 있습니다 ...
BenPen

2

그러한 a를 사용하는 또 다른 장점은 그러한 a 가 사용될 때마다 형식 안전성을 강제struct 한다는 것 입니다. 특히 서로 다른 목적으로 사용되는 동일한 크기의 어레이로 구성된 두 가지 유형이있는 경우 이러한 유형을 사용하면 실수로 어레이를 부적절하게 사용하지 않아도됩니다.struct

에서 배열을 래핑하지 않으면 struct여전히 배열을 선언 할 수 있습니다 typedef. 이로 인해 다음과 같은 장점이 있습니다. struct– 유형이 한 번 선언됩니다. • 크기가 자동으로 정확합니다. 코드는 유지 관리가 용이하지만 ◦ 엄격한 형식 안전성, ◦ 형식의 값을 복사 및 반환하는 기능 및 ◦ 나중에 나머지 코드를 손상시키지 않고 멤버를 추가 할 수있는 기능이 손실됩니다. typedef주어진 유형의 베어 배열에 대해 2 는 크기가 다른 경우에만 다른 유형을 생성합니다. 또한 함수 인수에 typedefwithout 를 사용하면 형식 안전성을 크게 줄이는 *것과 같습니다 char *.

요약하면 :

typedef struct A_s_s { char m[113]; } A_s_t; // Full type safey, assignable
typedef char   A_c_t[113];                   // Partial type-safety, not assignable

A_s_t          v_s(void);     // Allowed
A_c_t          v_c(void);     // Forbidden

void           s__v(A_s_t);     // Type-safe, pass by value
void           sP_v(A_s_t *);   // Type-safe
void           c__v(A_c_t);     // UNSAFE, just means char * (GRRR!)
void           cP_v(A_c_t *);   // SEMI-safe, accepts any array of 113

1

구조에는 OOP 메모리 관리 패러다임의 장점 중 일부를 모방 한 배열 초기화, 복사 및 fini 함수가 포함될 수 있습니다. 실제로, 사용자 정의 구조를 관리하기 위해 sizeof () 구조를 사용하여 정확히 얼마나 많은 바이트가 관리되는지 알 수있는) 일반적인 메모리 관리 유틸리티를 작성하도록이 개념을 확장하는 것은 매우 쉽습니다. C로 작성된 많은 현명한 생산 코드 기반은 이것들을 많이 사용하며 일반적으로 범위가 매우 로컬이 아닌 한 배열을 사용하지 않습니다.

실제로 구조에 내장 된 어레이의 경우이 어레이에 액세스하려고 할 때마다 바운드 검사와 같은 다른 "스마트 일"을 수행 할 수 있습니다. 배열 범위가 매우 제한적이지 않으면 배열 범위를 사용하고 프로그램 전체에 정보를 전달하는 것은 좋지 않습니다. 조만간 밤에 깨어 주말을 망치게하는 벌레가 생길 것입니다.


이것은 왜 배열 struct 포함 하는 것을 사용할 수 있는지에 대한 질문에는 대답하지 않습니다 .
PJTraill
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.