함수 인수의 배열 길이
이것은 C에서 배열 길이를 계산하는 잘 알려진 코드입니다.
sizeof(array)/sizeof(type)
하지만 함수에 인수로 전달 된 배열의 길이를 찾을 수없는 것 같습니다.
#include <stdio.h>
int length(const char* array[]) {
return sizeof(array)/sizeof(char*);
}
int main() {
const char* friends[] = { "John", "Jack", "Jim" };
printf("%d %d", sizeof(friends)/sizeof(char*), length(friends)); // 3 1
}
배열이 상수 포인터로 함수 인수에 값으로 복사되고 이에 대한 참조가이 문제를 해결해야한다고 가정하지만이 선언은 유효하지 않습니다.
int length(const char**& array);
중복 정보가 될 두 번째 인수로 배열 길이를 전달하는 것을 찾았지만 main
다음과 같은 표준 선언은 왜 다음과 같습니다.
int main(int argc, char** argv);
함수 인수에서 배열 길이를 찾을 수 있는지, 그렇다면 왜 중복성이 있는지 설명하십시오 main
.
sizeof
원래 배열에 적용하는 경우에만 배열의 길이를 찾습니다.
int a[5]; //real array. NOT a pointer
sizeof(a); // :)
그러나 배열이 포인터로 붕괴 될 때까지 sizeof는 배열이 아닌 포인터의 크기를 제공합니다.
int a[5];
int * p = a;
sizeof(p); // :(
이미 현명하게 지적했듯이 main은 배열의 길이를 인수 (argc)로받습니다. 예, 이것은 불필요하며 중복되지 않습니다 . (음, argv가 널 포인터로 편리하게 종료되기 때문에 일종의 중복이지만 나는 빠져 나갑니다)
이것이 왜 일어나는지에 대한 몇 가지 이유가 있습니다. C 배열도 길이를 알 수 있도록 어떻게 만들 수 있습니까?
첫 번째 아이디어는 배열이 함수에 전달 될 때 포인터로 붕괴되지 않고 유형 시스템에서 배열 길이를 계속 유지하는 것입니다. 이것에 대한 나쁜 점은 가능한 모든 배열 길이에 대해 별도의 함수가 필요하고 그렇게하는 것은 좋은 생각이 아니라는 것입니다. (Pascal이이 작업을 수행했으며 일부 사람들은 이것이 C에게 "잃어버린"이유 중 하나라고 생각합니다.)
두 번째 아이디어는 최신 프로그래밍 언어와 마찬가지로 배열 옆에 배열 길이를 저장하는 것입니다.
a -> [5];[0,0,0,0,0]
그러나 당신은 struct
이면에서 보이지 않는 것을 만들고 있으며 C 철학은 이런 종류의 오버 헤드를 승인하지 않습니다. 즉, 이러한 구조체를 직접 만드는 것은 종종 어떤 종류의 문제에 대해 좋은 생각입니다.
struct {
size_t length;
int * elements;
}
또 다른 생각은 C의 문자열이 길이를 저장하는 대신 null로 끝나는 방식입니다 (파스칼 에서처럼). 제한에 대해 걱정하지 않고 길이를 저장하려면 무려 4 바이트 가 필요 합니다. 이는 상상할 수 없을 정도로 비싼 양입니다 (적어도 그 당시에는). 배열이 null로 종료 될 수도 있는지 궁금 할 수 있지만 배열이 null을 저장하도록 허용하는 방법은 무엇입니까?
배열 은 전달되면 포인터로 사라 집니다.
C FAQ의 섹션 6.4 는이를 잘 다루고 K & R 참조 등을 제공합니다.
그 외에도 함수가 포인터에 할당 된 메모리의 크기를 알 수 있다고 상상해보십시오. 잠재적으로 길이가 다른 다른 입력 배열을 사용하여 매번 함수를 두 번 이상 호출 할 수 있습니다. 따라서 길이는 어떻게 든 비밀 숨겨진 변수로 전달되어야합니다. 그런 다음 오프셋을 다른 배열 또는 힙에 할당 된 배열로 전달했는지 고려하십시오 ( malloc
그리고 모두 라이브러리 함수-컴파일러가 본문에 대한 이유를보고 이유를 확인하지 않고 연결하는 것).
비하인드 스토리 슬라이스 오브젝트없이 이것이 어떻게 작동 할 수 있는지 상상하기 어렵습니다.
Symbian AllocSize()
에는 할당 크기를 반환 하는 함수 가 있습니다 malloc()
. 이것은 malloc에 의해 반환 된 리터럴 포인터에 대해서만 작동했으며 유효하지 않은 포인터의 크기 나 포인터 오프셋의 크기를 물어 보면 충돌이 발생하거나 충돌이 발생합니다.
가능하지 않다고 믿고 싶지는 않지만 진정으로 그렇지 않습니다. 함수에 전달 된 길이를 아는 유일한 방법은 길이를 직접 추적하여 별도의 명시 적 매개 변수로 전달하는 것입니다.
@Will에서 언급했듯이 매개 변수 전달 중에 감쇠가 발생합니다. 이를 우회하는 한 가지 방법은 요소 수를 전달하는 것입니다. 여기에 추가하려면 _countof()
매크로가 유용하다는 것을 알게 될 것입니다. 이것은 여러분이했던 것과 동일합니다.)
첫째, 실제 배열 선언이 범위 내에있을 때 요소 수를 계산하는 더 나은 사용법은 다음과 같습니다.
sizeof array / sizeof array[0]
이렇게하면 형식 이름을 반복하지 않습니다. 물론 선언에서 변경되어 잘못된 길이 계산으로 끝날 수 있습니다. 이것은 자신을 반복하지 않는 전형적인 경우입니다 .
둘째, 사소한 점으로, sizeof
함수가 아니므로 위의 표현식은 인수 주위에 괄호가 필요하지 않습니다 sizeof
.
셋째, C에는 참조가 없으므로 &
선언에서 사용이 작동하지 않습니다.
적절한 C 솔루션은 길이 ( size_t
유형 사용)를 별도의 인수로 전달 sizeof
하고 인수가 "실제"배열 인 경우 호출이 이루어지는 장소에서 사용하는 것에 동의합니다 .
예를 들어 반환 된 메모리로 작업 malloc()
하는 경우가 많으며이 경우 크기를 계산할 "진정한"배열이 없으므로 요소 수를 사용하도록 함수를 설계하는 것이 더 유연합니다.
int main ()과 관련하여 :
표준에 따르면 argv
널로 끝나는 배열 (널로 끝나는 문자열에 대한 포인터)을 가리 킵니다 . (5.1.2.2.1 : 1).
즉, argv = (char **){ argv[0], ..., argv[argc - 1], 0 };
.
따라서 크기 계산은의 사소한 수정 인 함수에 의해 수행됩니다 strlen()
.
argc
argv
길이 계산 O (1) 을하기 위해서만 존재합니다 .
count-until-NULL 메서드는 일반 배열 입력에 대해 작동 하지 않습니다 . 두 번째 인수로 크기를 수동으로 지정해야합니다.
This is a old question, and the OP seems to mix C++ and C in his intends/examples. In C, when you pass a array to a function, it's decayed to pointer. So, there is no way to pass the array size except by using a second argument in your function that stores the array size:
void func(int A[])
// should be instead: void func(int * A, const size_t elemCountInA)
They are very few cases, where you don't need this, like when you're using multidimensional arrays:
void func(int A[3][whatever here]) // That's almost as if read "int* A[3]"
Using the array notation in a function signature is still useful, for the developer, as it might be an help to tell how many elements your functions expects. For example:
void vec_add(float out[3], float in0[3], float in1[3])
is easier to understand than this one (although, nothing prevent accessing the 4th element in the function in both functions):
void vec_add(float * out, float * in0, float * in1)
If you were to use C++, then you can actually capture the array size and get what you expect:
template <size_t N>
void vec_add(float (&out)[N], float (&in0)[N], float (&in1)[N])
{
for (size_t i = 0; i < N; i++)
out[i] = in0[i] + in1[i];
}
In that case, the compiler will ensure that you're not adding a 4D vector with a 2D vector (which is not possible in C without passing the dimension of each dimension as arguments of the function). There will be as many instance of the vec_add function as the number of dimensions used for your vectors.
int arsize(int st1[]) {
int i = 0;
for (i; !(st1[i] & (1 << 30)); i++);
return i;
}
This works for me :)
Best example is here
thanks #define SIZE 10
void size(int arr[SIZE])
{
printf("size of array is:%d\n",sizeof(arr));
}
int main()
{
int arr[SIZE];
size(arr);
return 0;
}
참고URL : https://stackoverflow.com/questions/8269048/length-of-array-in-function-argument
'development' 카테고리의 다른 글
Entity Framework 무 신임 투표-.NET 4와 관련이 있습니까? (0) | 2020.12.05 |
---|---|
불완전한 유형에 대한 역 참조 포인터 (0) | 2020.12.05 |
arm-linux-gcc와 arm-none-linux-gnueabi의 차이점은 무엇입니까? (0) | 2020.12.05 |
Uint8Array와 Uint8ClampedArray의 차이점 (0) | 2020.12.05 |
babel-loader를 사용할 때 Object.assign ()에 polyfill이 필요한 이유는 무엇입니까? (0) | 2020.12.05 |