typedef 고정 길이 배열


210

24 비트 데이터 형식을 정의 char[3]해야합니다. 형식을 나타내는 데 사용 하고 있습니다. 에 typedef char[3]를 입력 할 수 있습니까 type24? 코드 샘플에서 시도했습니다. typedef char[3] type24;헤더 파일에 넣었습니다 . 컴파일러는 그것에 대해 불평하지 않았습니다. 그러나 void foo(type24 val) {}C 파일에 함수 를 정의했을 때 불평했습니다. type24_to_int32(type24 val)대신 과 같은 기능을 정의하고 싶습니다 type24_to_int32(char value[3]).

답변:


320

typedef는

typedef char type24[3];

그러나 결과 유형이 배열 유형이기 때문에 이것은 매우 나쁜 생각 일 수 있지만 사용자에게는 그것이 배열 유형이라는 것을 알 수 없습니다. 함수 인수로 사용되면 값이 아닌 참조로 전달 sizeof되므로 잘못된 것입니다.

더 나은 해결책은

typedef struct type24 { char x[3]; } type24;

후자는 구현 정의 서명을 가지고 있기 때문에 아마 unsigned char대신에 사용하고 싶을 수도 있습니다 char.


10
typedef의 배열을 매개 변수로 전달하는 것과 관련된 코너 케이스를 설명하는 멋진 문서가 있습니까? 함수는 매개 변수를 예를 들어 type24 foo, 어떤 크기, 유형 및 의미 것 foo, *foo, **foo, &foo,와 &&foo? 그러한 표현의 의미와 적법성이 지난 몇 년 동안 바뀌 었습니까?
supercat

4
24 비트 데이터 유형은 RGB 이미지 데이터와 같이 다르게 정의 된 패킹 의미론을 가진 무언가에 매핑되도록 의도 된 구조 패킹주의 사항에 대해 언급 할 가치가 있습니다.
sh1

2
@ sh1 : 내가 알고있는 모든 현대의 실제 ABI에서 (잘못 정렬 된 액세스가 매우 비싼 경우에도) 구조는 멤버가 구조없이 가질 때보 다 더 강력한 정렬 요구 사항을 얻지 못합니다. 물론 OP 또는이 방법을 사용하는 다른 사람은 프로그램의 동작 및 이식성과 관련이 있는지 여부를 확인해야합니다.
R .. GitHub 중지 지원 얼음

4
@R .. 이것의 한 부분은 오해의 소지가 있습니다. C에서 배열은 항상 참조로 전달됩니다. 즉, 함수에 인수로 전달 된 배열을 수정하면 함수의 컨텍스트뿐만 아니라 전역 적으로 수행됩니다. 이 말은 C 배열에서 항상 첫 번째 요소의 주소를 전달하기 때문에 C 배열에서 항상 값으로 전달 된다고 주장 할 수 있습니다.이 요소는 수신자 스택의 스택에 복사됩니다. 그러나 두 경우 모두 대답이 잘못되었습니다.
baibo

1
@bobbogo : 그것은 포장이 아니며, 단지 무료 패딩의 비 삽입입니다. 구조의 정렬은 모든 멤버의 최대 정렬 일 뿐이며, 모두 정렬 1을 갖습니다.
R .. GitHub STOP HELPING ICE

49

당신이 원하는

typedef char type24[3];

C 타입 선언은 그렇게 이상합니다. 해당 유형의 변수를 선언하는 경우 변수 이름의 위치를 ​​정확하게 입력하십시오.


33

에서 R ..의 대답 :

그러나 결과 유형이 배열 유형이기 때문에 이것은 매우 나쁜 생각 일 수 있지만 사용자에게는 그것이 배열 유형이라는 것을 알 수 없습니다. 함수 인수로 사용되면 값이 아닌 참조로 전달되므로 크기가 잘못됩니다.

배열임을 알지 못하는 사용자는 다음과 같이 작성할 것입니다 (실패).

#include <stdio.h>

typedef int twoInts[2];

void print(twoInts *twoIntsPtr);
void intermediate (twoInts twoIntsAppearsByValue);

int main () {
    twoInts a;
    a[0] = 0;
    a[1] = 1;
    print(&a);
    intermediate(a);
    return 0;
}
void intermediate(twoInts b) {
    print(&b);
}

void print(twoInts *c){
    printf("%d\n%d\n", (*c)[0], (*c)[1]);
}

다음 경고와 함께 컴파일됩니다.

In function intermediate’:
warning: passing argument 1 of print from incompatible pointer type [enabled by default]
    print(&b);
     ^
note: expected int (*)[2]’ but argument is of type int **’
    void print(twoInts *twoIntsPtr);
         ^

그리고 다음과 같은 출력을 생성합니다.

0
1
-453308976
32767

13

C에서 값으로 배열을 함수 매개 변수로 전달할 수 없습니다.

배열을 구조체에 넣을 수 있습니다.

typedef struct type24 {
    char byte[3];
} type24;

그런 다음 값으로 전달하지만 물론 다음 x.byte[0]대신 사용하는 것이 편리 하지 않습니다 x[0].

함수는 type24_to_int32(char value[3])실제로 값이 아닌 포인터를 통해 전달됩니다. 정확히와 동일 type24_to_int32(char *value)하고 3는 무시됩니다.

당신이 포인터에 의해 행복 통과를해서, 당신은 할 수 배열을 고수하고 수행

type24_to_int32(const type24 *value);

이것은 포인터에서 첫 번째 요소가 아닌 배열에 대한 포인터를 전달하므로 다음과 같이 사용하십시오.

(*value)[0]

실수로 쓴 value[1]다면 어리석은 일이 발생하기 때문에 그것이 실제로 이득인지 확신 할 수 없습니다 .


2
이 답변은 decay어딘가에 용어를 언급함으로써 개선 될 수 있다고 생각합니다 (아마도 배열 을 반환 하는 경우 상황이 더 나쁘다는 것을 지적하면 전혀 작동하지 않습니다).
Frerich Raabe 님

9

배열 유형을 함수 인수 또는 템플릿 매개 변수로 올바르게 사용하려면 typedef 대신 구조체를 만든 다음 operator[]구조체에 추가 하여 구조체와 같은 기능을 유지할 수 있습니다.

typedef struct type24 {
  char& operator[](int i) { return byte[i]; }
  char byte[3];
} type24;

type24 x;
x[2] = 'r';
char c = x[2];

14
이것은 C ++이 아닌 C 질문입니다. C에도 존재하지 않는 것도 char&없고operator[]
Michael Morris

3

다음은 typedef 배열이 혼동 될 수없는 간단한 예입니다. 다른 답변은 해결 방법을 제공합니다.

#include <stdio.h>
typedef char type24[3];

int func(type24 a) {
        type24 b;
        printf("sizeof(a) is %zu\n",sizeof(a));
        printf("sizeof(b) is %zu\n",sizeof(b));
        return 0;
}

int main(void) {
        type24 a;
        return func(a);
}

이것은 출력을 생성합니다

sizeof(a) is 8
sizeof(b) is 3

매개 변수로서 type24는 포인터이기 때문입니다. (C에서는 배열이 항상 포인터로 전달됩니다.) gcc8 컴파일러는 기본적으로 경고를 발행합니다.

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