문제
이 예제는 잘 작동합니다.
static char *daytab[] = {
"hello",
"world"
};
이것은 다음과 같습니다.
static char *daytab[] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
내가 보는 방식은 첫 번째 예제가 두 개의 문자열 리터럴 (배열)에 포인터로 채워진 배열을 만듭니다. 두 번째 예제 인 IMO는 동일해야합니다. 배열을 만들고 두 숯 배열로 포인터로 채 웁니다.
누군가 나에게 두 번째 예가 왜 잘못되었는지 설명 할 수 있습니까?
추신 : 아마도 이것처럼 쓸 수있을 것입니다 (테스트하지 않았습니다).
static char a[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static char b[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static char *daytab[] = {
a,
b
};
그러나 그것은 너무 많은 일처럼 보인다 :).
해결책
이것:
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
배열 이니셜 라이저 일뿐입니다. 자체가 배열을 만들지 않습니다. 첫 번째 예, 문자열 리터럴을 포인터에 할당했을 때 정적 저장소에 문자열을 만들었고 (숨겨진) 포인터를 할당했습니다.
따라서 기본적으로 배열 이니셜 라이저로 Char*를 초기화 할 방법이 없습니다. 실제 배열을 만들고 해당 숫자를 할당해야합니다. 당신은 다음과 같은 일을해야합니다.
char a[][] = { {32, 30, 0}, {34, 32, 33, 0} }; // illegal
그러나 그것은 불법입니다.
배열을 별도로 빌드하고 마지막 예제와 같은 배열에 할당해야합니다.
다른 팁
노력하다:
static char daytab[][13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
그것들은 char*의 것이 아닙니다. 그들은 또한 문자가 아닙니다. 당신은 아마 원할 것입니다 :
static int daytab[][13] ...
글쎄,이 스레드는 이미 조금 낡았지만 같은 문제를 다루고 있었고 다음과 같이 배열로 다양한 포인터를 초기화하는 방법을 찾았습니다.
#include <iostream>
using namespace std;
int *a[] = {
(int[]) { 0 } ,
(int[]) { 1 , 2 } ,
(int[]) { 3 , 4 , 5 } ,
(int[]) { 6 , 7 , 8 , 9 }
};
main()
{
cout
<< a[0][0] << endl
<< a[1][0] << " " << a[1][1] << endl
<< a[2][0] << " " << a[2][1] << " " << a[2][2] << endl
<< a[3][0] << " " << a[3][1] << " " << a[3][2] << " " << a[3][3] << endl;
}
그리고 GNU G ++로 컴파일하는 출력을 얻습니다.
0
1 2
3 4 5
6 7 8 9
및 Intel ICPC로 컴파일
0
1 1
40896 32767 -961756724
0 32767 4198878 0
따라서 구문은 원칙적으로 올바른 것 같습니다. 인텔 컴파일러는 아마도이 스타일의 일반적인 사용이 없기 때문에 그것을 지원하지 않습니다.
--- 편집하다 ---
다음은 C 버전도 있습니다 (요구대로).
#include <stdio.h>
int *a[] = {
(int[]) { 0 } ,
(int[]) { 1 , 2 } ,
(int[]) { 3 , 4 , 5 } ,
(int[]) { 6 , 7 , 8 , 9 }
};
int main()
{
printf( "%d\n" , a[0][0] );
printf( "%d %d\n" , a[1][0] , a[1][1] );
printf( "%d %d %d\n" , a[2][0] , a[2][1] , a[2][2] );
printf( "%d %d %d %d\n" , a[3][0] , a[3][1] , a[3][2] , a[3][3] );
}
GCC와 Clang으로 테스트했으며 올바른 결과를 인쇄했습니다. BTW. 인텔 컴파일러의 잘못된 출력은 컴파일러 버그였습니다.
static char **daytab;
daytab=(char**)malloc(2*sizeof(char*));
daytab[0]=(char*)(char[]){0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
daytab[1]=(char*)(char[]){0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
두 번째 예제의 구문은 다차원 배열 리터럴의 구문입니다.
다차원 배열은 배열에 대한 다양한 포인터가 아닙니다.
한 가지에 대한 구문이 선언 된 유형에 따라 다른 것에 대한 구문이라면 놀랍습니다.
첫 번째 예에서, 문자열 문자가 배열 값이 아닌 포인터로 평가되기 때문에 값은 포인터의 배열로 평가됩니다. 배열 문자가 포인터가 아닌 배열 값으로 평가되기 때문에 두 번째 예제는 다차원 배열입니다. 요소가 배열 값인 배열이 아닌 배열은 배열 값에 대한 배열이 아닙니다.
다음 코드는 다차원 배열, 배열 포인터, 포인터 배열 및 포인터의 포인터 조합을 보여줍니다. 이 세 가지 중 포인터에 대한 포인터와 포인터만이 서로 호환됩니다.
void multi_array (int x[][4], size_t len) // multidimensional array
{
for (size_t i = 0; i < len; ++i)
for (size_t j = 0; j < 4; ++j)
putchar( 'a' + x[i][j] );
putchar('\n');
}
void ptr_array (int (*x)[4], size_t len) // pointer to an array
{ ... as multi_array }
void array_ptr (int *x[], size_t len) // array of pointers
{ ... as multi_array }
void ptr_ptr (int **x, size_t len) // pointer to pointer
{ ... as multi_array }
int main() {
int a[][4] = { { 1,2,3,4 } };
int b[] = { 1,2,3,4 };
int* c[] = { b };
multi_array( a, 1 );
multi_array( (int[][4]) { { 1,2,3,4} }, 1 ); // literal syntax as value
ptr_array( &b, 1 );
array_ptr( c, 1 );
ptr_ptr( c, 1 ); // only last two are the same
return 0;
}
첫 번째 예제도 작동하지 않습니다. 그것은 다음과 같아야합니다.
static const char *daytab[] = {
"hello",
"world"
};
참고 Const.
편집 : 그리고 "작동하지 않는다"에 의해, 나는 나쁜 연습과 오류가 발생하기 쉬운 것을 의미합니다.