programing

C 복합 리터럴, 배열 포인터

stoneblock 2023. 9. 26. 21:57

C 복합 리터럴, 배열 포인터

복합 리터럴을 변수에 할당하려고 하는데 작동하지 않는 것 같습니다.

  int *p[] = (int *[]) {{1,2,3},{4,5,6}};

gcc에서 오류가 났습니다.

이 글만 쓴다면,

  int p[] = (int []) {1,2,3,4,5,6};

그럼 괜찮아요.

하지만 제가 원하는 것은 아닙니다.

오류가 발생하는 이유를 이해할 수 없습니다. 배열처럼 초기화하거나 문자 배열 포인터와 함께 사용해도 괜찮기 때문입니다.

  int *p[] = (int *[]) {{1,2,3},{4,5,6}}; //I got a error
  int p[][3] = {{1,2,3},{4,5,6}}; //it's okay
  char *p[] = (char *[]) {"one", "two"...}; // it's okay!

참고 첫 번째 양식에서 오류가 발생한 이유를 이해할 수 없습니다. 그렇지 않으면 복합 리터럴이어야 하기 때문에 두 번째 양식처럼 쓰고 싶지 않습니다. 컴파일러에 배열 크기가 얼마나 되는지도 말하고 싶지 않습니다.저는 두 번째 것과 같은 것을 원하지만, int 값을 원합니다.

미리 감사드립니다.

첫째, 모든 예제에서 깁스가 중복되므로 제거할 수 있습니다.두 번째로, 다차원 배열을 초기화하기 위해 구문을 사용하고 있으며, 순차적인 메모리 블록을 할당하기 위해 두 번째 차원을 정의해야 합니다.대신 아래 두 가지 방법 중 하나를 사용해 보십시오.

  • 다차원 배열:

    int p[][3] = {{1,2,3},{4,5,6}};
    
  • 1차원 배열에 대한 포인터 배열:

    int p1[] = {1,2,3};
    int p2[] = {4,5,6};
    int *p[] = {p1,p2};
    

후자의 방법은 다양한 길이의 서브 어레이를 허용하는 장점이 있습니다.반면, 전자의 방법은 메모리가 연속적으로 배치되도록 보장합니다.

사용하지 않는 다른 방법은 문자열 리터럴의 정수를 인코딩하는 것입니다.이건 휴대용이 아닌 해킹입니다.또한 문자열 리터럴의 데이터는 일정해야 합니다.어레이를 변경할 필요가 있습니까?

int *p[] = (int *[]) {
    "\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00",
    "\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00"
};

이 예는 32비트 리틀 엔디언 기계에서 작동할 수 있지만, 아이패드에서 이 예를 타이핑하고 있어서 현재 확인할 수 없습니다.다시 한 번 말씀드리지만 그것은 사용하지 말아주세요. 그 얘기를 꺼내는 것조차 불쾌합니다.

발견한 캐스팅 방법은 포인터에 대한 포인터에서도 작동하는 것으로 보입니다.그것은 다차원 배열처럼 색인화될 수도 있습니다.

int **p = (int *[]) { (int[]) {1,2,3}, (int[]) {4,5,6} };

먼저 "배열은 포인터가 아닙니다."라고 이해합니다.

int p[] = (int []) {1,2,3,4,5,6};

p는 정수들의 배열입니다.를 복사하는 중입니다.{1,2,3,4,5,6}.p와 둘 다 캐스트가 하지 않습니다.rvalue그리고.lvalue유형은 정수 배열과 일치하므로 오류가 없습니다.

int *p[] = (int *[]) {{1,2,3},{4,5,6}};

"참고로 첫 번째 오류에서 왜 오류가 났는지 이해할 수 없습니다."

에는,p정수의 포인터들의 배열하지만.{{1,2,3},{4,5,6}}는 2차원 배열(즉, [[]])이며 포인터 배열에 타입 캐스트할 수 없습니다.-.

int p[][3] = { {1,2,3},{4,5,6} };
  // ^^ First index of array is optional because with each column having 3 elements
  // it is obvious that array has two rows which compiler can figure out.

그런데 왜 이 진술서가 작성되었을까요?

char *p[] = {"one", "two"...};

문자열 리터럴은 정수 리터럴과 다릅니다.에도 역시에도.p는 문자 포인터의 배열입니다. 것은."one", 배열에 복사하거나 읽기 전용으로 간주하여 해당 위치를 가리킬있습니다.

char cpy[] = "one" ;
cpy[0] = 't' ;  // Not a problem

char *readOnly = "one" ;
readOnly[0] = 't' ;  // Error because of copy of it is not made but pointing
                     // to a read only location.

문자열 리터럴을 사용하면 위의 경우 중 어느 하나라도 가능합니다.그래서 그것이 성명서를 작성한 이유입니다.근데..

char *p[] = {"one", "two"...}; // All the string literals are stored in 
                               // read only locations and at each of the array index 
                               // stores the starting index of each string literal.

저는 컴파일러에 배열이 얼마나 큰지 말하고 싶지 않습니다.

malloc해결책입니다.

도움이 되길 바랍니다!

아무도 말하지 않았기 때문에: 포인터 투 2D 어레이를 사용하고 싶다면 다음과 같은 작업을 수행할 수 있습니다.

int (*p)[][3] = &(int[][3]) {{1,2,3},{4,5,6}};

편집: 또는 다음을 통해 첫 번째 요소에 대한 포인터를 가질 수 있습니다.

int (*p)[3] = (int[][3]) {{1,2,3},{4,5,6}};

의 예제가{{1,2,3},{4,5,6}}다에 .int*[] 면){1,2,3}다에 .int*(). 주의:int[2][3]— 단지 잘못된 표현일 뿐입니다.

가 있는 "one"입니다.char[]그리고.char[N](일부 N>3의 경우).표현상으로는 대략 다음과 같습니다.(const char[]){'o','n','e','\0'}컴파일러가 일관성을 잃어도 크게 불평하지 않는 것만 빼면요.

네,식가 있습니다 , .를 확신합니다.char s[] = (char[]){3,2,1,0};는 C99의 컴파일 오류입니다.만,T foo = ...;는 변수 초기화이며, assignment가 아닙니다. (assignment 연산자가 호출되지 않기 때문에 C++에서는 특히 다릅니다.)

그리고 포인터를 혼동한 이유:

  • T[](는) 암묵적으로 됩니다.T*필요한 경우 (첫 번째 요소에 대한 포인터).
  • T arg1[]합니다를 합니다.T * arg1할 수 다양한 이유로 배열을 함수에 전달할 수 없습니다.불가능합니다.시도하면 실제로 포인터를 배열로 전달하는 것입니다. (그러나 고정 크기 배열을 포함하는 구조물을 함수로 전달할 수 있습니다.)
  • 둘 다 동일한 의미론으로 참조되고 구독될 수 있습니다.

편집: 관찰자는 제 첫 번째 예가 대략 구문적으로 다음과 같다는 것을 알아차릴 수 있습니다.int * p = &1;, 그것은 무효입니다.이것은 C99에서 작동하는데 함수 내부의 복합 리터럴이 "인클로저 블록과 연관된 자동 저장 기간"을 갖기 때문입니다(ISO/IEC 9899:TC3).

사용 중인 것은 int 포인터의 배열입니다.배열에 포인터를 사용해야 합니다.

int (*p)[] = (int *) {{1,2,3}, {4,5,6}}

자세한 내용은 이 답변을 보세요.

당신은 포인터와 배열을 혼동하고 있는 것 같습니다.그들은 같은 것이 아닙니다!배열은 목록 자체인 반면 포인터는 주소에 불과합니다.그런 다음 포인터 산술을 사용하면 포인터가 배열인 것처럼 간주할 수 있으며 배열의 이름이 첫 번째 요소에 대한 포인터라는 사실로 모든 것이 엉망진창으로 요약됩니다. ;)

int *p[] = (int *[]) {{1,2,3},{4,5,6}};      //I got a error

여기서 p는 포인터의 배열이므로 주소가 1, 2, 3인 요소를 첫 번째 배열에, 4, 5, 6인 요소를 두 번째 배열에 할당하려고 합니다.세그먼트 오류는 해당 메모리 위치에 액세스할 수 없기 때문에 발생합니다.

int p[][3] = {{1,2,3},{4,5,6}};              //it's okay

이것은 어레이의 어레이이므로 이번에는 1, 2, 3, 4, 5, 6은 주소가 아니라 요소 자체이기 때문에 괜찮습니다.

char *p[] = (char *[]) {"one", "two"...};    // it's okay!

문자열 리터럴("one", "two", "...")은 실제로 문자열이 아니라 해당 문자열을 가리키는 포인터이므로 문자열 리터럴 "one"의 주소를 p[1]에 할당하는 것입니다.
그렇고,고를 야,다.char abc[]; abc = "abc";수 할 수 없습니다.char *def; def = "def";문제를 해결합니다.

언급URL : https://stackoverflow.com/questions/5495983/c-compound-literals-pointer-to-arrays