매개 변수로 전송되는 배열의 크기가 main 내에서와 동일하지 않은 이유는 무엇입니까?
#include <stdio.h>
void PrintSize(int p_someArray[10]);
int main () {
int myArray[10];
printf("%d\n", sizeof(myArray)); /* As expected, 40 */
PrintSize(myArray);/* Prints 4, not 40 */
}
void PrintSize(int p_someArray[10]){
printf("%d\n", sizeof(p_someArray));
}
답변
배열 유형은 함수에 전달할 때 암시 적 으로 포인터 유형으로 변환됩니다.
그래서,
void PrintSize(int p_someArray[10]) {
printf("%zu\n", sizeof(p_someArray));
}
과
void PrintSize(int *p_someArray) {
printf("%zu\n", sizeof(p_someArray));
}
동등합니다. 그래서 당신이 얻는 것은sizeof(int*)
답변
포인터이기 때문에 배열의 크기를 함수에 두 번째 매개 변수로 전달하는 것이 일반적인 구현입니다.
답변
다른 사람들이 언급했듯이 배열은 함수 매개 변수로 사용될 때 첫 번째 요소에 대한 포인터로 붕괴됩니다. 또한 sizeof는 표현식을 평가하지 않고 표현식과 함께 사용할 때 괄호가 필요하지 않으므로 매개 변수가 실제로 전혀 사용되지 않으므로 값이 아닌 유형으로 sizeof를 작성하는 것이 좋습니다.
#include <stdio.h>
void PrintSize1 ( int someArray[][10] );
void PrintSize2 ( int someArray[10] );
int main ()
{
int myArray[10];
printf ( "%d\n", sizeof myArray ); /* as expected 40 */
printf ( "%d\n", sizeof ( int[10] ) ); /* requires parens */
PrintSize1 ( 0 ); /* prints 40, does not evaluate 0[0] */
PrintSize2 ( 0 ); /* prints 40, someArray unused */
}
void PrintSize1 ( int someArray[][10] )
{
printf ( "%d\n", sizeof someArray[0] );
}
void PrintSize2 ( int someArray[10] )
{
printf ( "%d\n", sizeof ( int[10] ) );
}
답변
따라서 배열의 길이를 두 번째 매개 변수로 전달해야합니다. 둘 다 상수 크기의 배열을 선언하고 나중에 해당 배열을 함수에 전달하는 코드를 작성할 때 배열 길이 상수가 코드의 여러 위치에 표시되는 것은 고통 스럽습니다.
구조를위한 K & R :
#define N_ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
이제 다음과 같이 할 수 있습니다.
int a[10];
...
myfunction(a, N_ELEMENTS(a));
답변
배열은 매개 변수로 전달 될 때 포인터로 붕괴되기 때문입니다. C ++에서 “배열”을 참조로 전달하고이 문제를 극복 할 수 있지만 이것이 C가 작동하는 방식입니다. 크기가 다른 배열을이 함수에 전달할 수 있습니다.
// 10 is superfluous here! You can pass an array of different size!
void PrintSize(int p_someArray[10]);
답변
당신이 찾은 행동은 실제로 C 언어에서 큰 사마귀입니다. 배열 매개 변수를 사용하는 함수를 선언 할 때마다 컴파일러는 사용자를 무시하고 매개 변수를 포인터로 변경합니다. 따라서 이러한 선언은 모두 첫 번째 선언처럼 작동합니다.
void func(int *a)
void func(int a[])
void func(int a
typedef int array_plz[5];
void func(array_plz a)
a는 네 가지 경우 모두에서 int에 대한 포인터가됩니다. func에 배열을 전달하면 즉시 첫 번째 요소에 대한 포인터로 붕괴됩니다. (64 비트 시스템에서 64 비트 포인터는 32 비트 int의 두 배이므로 크기 비율은 2를 반환합니다.)
이 규칙의 유일한 목적은 집계 값을 함수 인수로 전달하는 것을 지원하지 않는 기록 컴파일러와의 역 호환성을 유지하는 것입니다.
이것은 배열을 함수에 전달할 수 없다는 것을 의미하지 않습니다. 배열을 구조체에 임베딩하여이 사마귀를 피할 수 있습니다 (기본적으로 C ++ 11의 std :: array의 목적입니다).
struct array_rly {
int a[5];
};
void func(struct array_rly a)
{
printf("%zd\n", sizeof(a.a)/sizeof(a.a[0])); /* prints 5 */
}
또는 포인터를 배열에 전달하여 :
void func(const int (*a)[5])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0])); /* prints 5 */
}
배열 크기가 컴파일 시간 상수가 아닌 경우 C99 가변 길이 배열에 포인터-배열 기술을 사용할 수 있습니다.
void func(int n, const int (*a)[n])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0])); /* prints n */
}
답변
C ++에서는 바로이 목적을 위해 참조로 배열을 전달할 수 있습니다.
void foo(int (&array)[10])
{
std::cout << sizeof(array) << "\n";
}
