programing

지정되지 않은 크기의 배열에 대한 포인터(*p)[]"C++에서는 불법이지만 C에서는 합법입니다.

muds 2023. 9. 14. 00:03
반응형

지정되지 않은 크기의 배열에 대한 포인터(*p)[]"C++에서는 불법이지만 C에서는 합법입니다.

이것이 C++에서는 불법이라는 것을 방금 알았습니다. (그러나 C에서는 합법입니다.)

#include <stdio.h>
#include <stdlib.h>
#define ARRAY_LENGTH(A) (sizeof(A) / sizeof(A[0]))

int accumulate(int n, const int (*array)[])
{
    int i;
    int sum = 0;
    for (i = 0; i < n; ++i) {
        sum += (*array)[i];
    }
    return sum;
}

int main(void)
{
    int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35};
    printf("%d\n", accumulate(ARRAY_LENGTH(a), &a));
    return 0;
}

를 사용하여 문제없이 컴파일합니다.gcc -std=c89 -pedantic를 사용하여 컴파일하지 못합니다.g++. 를 사용하여 컴파일하려고 할 때g++다음 오류 메시지가 나타납니다.

main.cpp:5:37: error: parameter 'array' includes pointer to array of unknown bound 'int []'
 int accumulate(int n, int (*array)[])
                                     ^
main.cpp: In function 'int main()':
main.cpp:18:50: error: cannot convert 'int (*)[9]' to 'int (*)[]' for argument '2' to 'int accumulate(int, int (*)[])'
     printf("%d\n", accumulate(ARRAY_LENGTH(a), &a));

저는 이것을 C 코드에서 오랫동안 사용해왔는데 C++에서 불법인 줄은 몰랐습니다.제가 보기에 이것은 함수가 크기를 미리 알 수 없는 배열을 취한다는 것을 문서화하는 유용한 방법입니다.

이것이 C는 합법인데 C++는 무효인 이유를 알고 싶습니다.C++ 위원회가 (C와의 이러한 호환성을 깨트리고) C++ 위원회가 그것을 제거하기로 결정한 이유가 무엇이었는지도 궁금합니다.

그렇다면 왜 이 합법적인 C 코드인데 불법적인 C++ 코드인 것일까요?

Dan Saks는 1995년 C++ 표준화를 앞두고 이에 대해 다음과 같이 썼습니다.

위원회는 C++에서 알 수 없는 경계, 복잡한 선언 일치 및 오버로드 해결 규칙을 가진 배열에 대한 포인터 또는 참조를 수용하는 이와 같은 기능을 결정했습니다.위원회들은 그러한 기능들이 거의 효용이 없고 꽤 흔하지 않기 때문에, 그것들을 금지하는 것이 가장 간단할 것이라고 동의했습니다.따라서 C++ 초안에는 다음과 같이 명시되어 있습니다.

매개 변수의 유형에 알 수 없는 T의 배열에 대한 폼 포인터 또는 알 수 없는 T의 배열에 대한 참조 유형이 포함되면 프로그램이 잘못 형성됩니다.

C++는 C의 "호환형" 개념을 가지고 있지 않습니다.C에서 이는 변수의 완벽하게 유효한 재선언입니다.

extern int (*a)[];
extern int (*a)[3];

C에서 이는 동일한 함수에 대해 완벽하게 유효한 재선언입니다.

extern void f();
extern void f(int);

C에서 이는 구현별이지만 일반적으로 동일한 변수에 대해 유효한 재선언을 합니다.

enum E { A, B, C };
extern enum E a;
extern unsigned int a;

C++는 그런 게 하나도 없어요.C++에서는 종류가 같거나 다르며, 서로 다를 경우에는 얼마나 다른지에 대한 우려가 거의 없습니다.

유사하게,

int main() {
  const char array[] = "Hello";
  const char (*pointer)[] = &array;
}

는 C에서는 유효하지만 C++에서는 유효하지 않습니다.array, 에도 불구하고[], 길이 6의 배열로 선언됩니다.pointer는 다른 유형인 지정되지 않은 길이의 배열에 대한 포인터로 선언됩니다.에서 암묵적인 변환이 없습니다.const char (*)[6]로.const char (*)[].

이 때문에 C++에서는 특정하지 않은 길이의 배열을 포인터로 표시하는 함수는 거의 쓸모가 없으며 프로그래머의 실수일 가능성이 높습니다.특정 배열 인스턴스에서 시작하는 경우에는 거의 항상 크기가 이미 있기 때문에 유형 불일치가 발생하므로 함수에 전달하기 위해 해당 주소를 사용할 수 없습니다.

예에서 불특정 길이의 배열에 대한 포인터도 필요 없습니다. C에서 쓰는 일반적인 방법은 C++에서도 유효합니다.

int accumulate(int n, int *array)
{
    int i;
    int sum = 0;
    for (i = 0; i < n; ++i) {
        sum += array[i];
    }
    return sum;
}

라고 accumulate(ARRAY_LENGTH(a), a).

언급URL : https://stackoverflow.com/questions/27897646/pointer-to-array-of-unspecified-size-p-illegal-in-c-but-legal-in-c

반응형