2012-02-17 5 views
13

비 C/C++ 전문가로서 저는 항상 대괄호와 포인터 배열을 동등한 것으로 간주했습니다.대괄호 배열과 포인터 배열의 차이점은 무엇입니까?

예 :

char *my_array_star; 
char my_array_square[]; 

하지만주의 그 구조/클래스의 사용은 그들이 동일하게 동작하지 않을 때 : 1 바이트 소요

typedef struct { 
    char whatever; 
    char *my_array_star; 
} my_struct_star; 

typedef struct { 
    char whatever; 
    char my_array_square[]; 
} my_struct_square; 

표시 (16) 아래의 라인, whatever

, my_array_pointer은 8 바이트를 사용합니다. 패딩으로 전체 구조의 크기는 16

printf("my_struct_star: %li\n",sizeof(my_struct_star)); 

표시 한 아래 라인 whatever 1 바이트 소요 인해 , my_array_pointer 계정에서 촬영되지 않는다.

printf("i[0]=%c\n",((char*)i)[0]); 

라인 타격 표시 B :

장난으로

printf("my_struct_square: %li\n",sizeof(my_struct_square)); 

나는 대괄호가 선 타격이 표시

my_struct_square *i=malloc(2); 

i->whatever='A'; 
i->my_array_square[0]='B'; 

구조에 여분의 공간으로 사용되는 것으로 나타났습니다

printf("i[1]=%c\n",((char*)i)[1]); 

그래서 더 이상 대괄호가 포인터와 같다고 말할 수 없습니다. 그러나 그 행동의 이유를 이해하고 싶습니다. 나는 그 언어의 핵심 개념을 놓치지 않을까 두려워합니다.

+0

C에서는'something []'을 선언 할 수 없으며 배열의 크기를 정의해야합니다. 둘 사이를 선택하십시오. – Eregrith

+1

@Eregrith : 구조체의 끝에서 배열을 선언 할 수 있습니다. 그래서 컴파일됩니다. –

+0

동적으로 생성 된 배열에 포인터를 사용하는 것에 신경을 쓰지 않고 신경 써야합니다. 나는 다른 문법을 좋아하지 않으며, 나에게 모욕적 인 것처럼 보인다. – evanmcdonnal

답변

23

이 아니기 때문에 배열과 포인터가 동일하게 동작하지 않습니다.은 전혀 같지 않습니다. 포인터는 ... 음 ... 하나의 항목에 대한 포인터 동안

배열은 연속 된 항목 그룹이다.

가리키는 단일 항목이 배열의 첫 번째 항목 일 수 있으므로 다른 항목에도 액세스 할 수 있지만 포인터 자체는 해당 항목을 인식하거나 신경 쓰지 않습니다.

배열과 포인터가 종종 동일하게 보이는 이유는 대부분의 경우 배열이 해당 배열의 첫 번째 요소에 대한 포인터로 부패한다는 것입니다.

이런 일이 발생하는 곳 중 하나는 함수 호출입니다. 함수에 배열을 전달하면 포인터로 붕괴됩니다. 그래서 배열의 크기와 같은 것들은 함수에 명시 적으로 전달되지 않습니다. 그함으로써 내 말은 : 당신이 찾을 수

#include <stdio.h> 

static void fn (char plugh[]) { 
    printf ("size = %d\n", sizeof(plugh)); // will give char* size (4 for me). 
} 

int main (void) { 
    char xyzzy[10]; 
    printf ("size = %d\n", sizeof(xyzzy)); // will give 10. 
    fn (xyzzy); 

    return 0; 
} 

다른 것은이고, 당신이 할 수있는 plugh++plugh-- 마음 콘텐츠 (만큼 당신이 배열의 외부 역 참조하지 않는 한), 당신은 '할 수있는 동안 배열 xyzzy을 사용하면됩니다.

두 가지 구조에는 큰 차이가 있습니다. 포인터 버전에서는 고정 크기 포인터 안에 구조가 있으며 외부의 항목을 가리 킵니다. 이 공간을 차지 왜

그입니다 - 다음과 같이 8 바이트 포인터는 8 바이트 경계에 정렬 :은 "무제한의"배열로

+----------------+ 
| 1 char variable| 
+----------------+ 
| 7 char padding | 
+----------------+ 
| 8 char pointer | 
+----------------+ 

, 당신은 구조와 내부에 그것을 이 원하는만큼 크게 만들 수 있습니다. 변수를 만들 때 충분한 메모리를 할당하면됩니다.

+----------------+ 
| 1 char variable| 
+----------------+ 
| 0 char array | 
+----------------+ 

하지만 당신은 예를 들어, 더 많은 공간, 할당 할 수 있습니다 : : 기본적으로 (즉, sizeof에 따라), 크기가 0입니다

typedef struct { 
    char whatever; 
    char my_array_square[]; 
} my_struct_square; 

my_struct_square twisty = malloc (sizeof (my_struct_square) + 10); 

당신에게 whatever 문자가 변수 twisty를 제공을 my_array_square이라는 10 개의 문자 배열이 있습니다.

이러한 제한되지 않은 배열은 구조체 끝에 만 나타날 수 있으며 단 하나만 존재할 수 있습니다. 그렇지 않으면 컴파일러는 이러한 가변 길이 섹션이 시작되고 끝난 위치를 알 수 없으며 특히 임의 크기의 배열을 구조의 끝.

+0

최고 품질의 답변 주셔서 감사합니다, 축하해! – Raphael

+0

+1 우수 설명. 크기가 지정되지 않은 멤버 배열이 표준에서도 허용되는지 확실하지 않습니다. 이 작업을 수행하는 경우 일반적으로 비표준 확장 프로그램 사용에 대한 경고 메시지가 표시됩니다. – Kevin

+0

"함수에 전달할 때 단순 포인터로 배열이 사라집니다.": 배열 구문에 대해 void fn (char * foobar)'void fn (char foobar [])'함수에 포인터 구문을 사용하는 것이 더 좋습니다. – Flimm

5

my_array_square 구성원은 "유연한"배열 구성원입니다. 지정된 크기가없는 이러한 배열은 구조체의 끝 부분에만 나타날 수 있으며 크기에 영향을주지 않습니다. 의도는 필요한만큼 많은 요소에 대해 수동으로 나머지 공간을 할당하는 것입니다. 그렇지 않으면 배열의 크기가 컴파일 타임에 결정됩니다.

my_struct_square *s = malloc(sizeof(my_struct_square) + 5 * sizeof(char)); 
... 
s->my_array_square[4]; // the last element of the array 

다른 모든 경우에 배열의 크기는 컴파일 시간에 알고 있어야 다음과 같이

이러한 구조체의 사용 패턴이 될 것입니다. 배열의 유형조차도 크기와 함께 사용됩니다. 즉, int a[20]은 이 아닌 int[20] 유형입니다.

또한 배열과 포인터의 차이를 이해하는 것이 중요합니다. @ paxdiablo가이를 잘 설명해주었습니다.

+0

완벽한 답변을 주셔서 감사합니다. – Raphael

+0

유연한 배열 구성원은 C 언어 버전 C99 이상에서만 사용할 수 있습니다. 이런 식의 코드를 C90 ("ANSI C")에서 시도하면 구조체의 끝에 저장할 수있는 패딩 바이트에 데이터를 쓸 때 충돌이 발생할 수 있다고 생각합니다. 쓰여진 데이터가 "트랩 대표". 내가 틀렸다면 나를 바로 잡아주세요. – Lundin

+0

@Lunding : C90 컴파일러로 컴파일하면 안된다. –

관련 문제