C에서 배열을 함수 인수로 전달할 수없는 이유는 무엇입니까?


12

이 의견에 이어 , 나는 왜 구글을 시도했지만 내 구글 푸는 실패했습니다.

링크에서 의견 :

[...] 그러나 중요한 것은 배열과 포인터가 C에서 다른 것입니다.

컴파일러 확장을 사용하지 않는다고 가정하면 일반적으로 배열 자체를 함수에 전달할 수 없지만 포인터를 전달하고 포인터를 배열처럼 인덱싱 할 수 있습니다.

포인터에 길이가 붙어 있지 않다고 효과적으로 불평하고 있습니다. 배열을 함수 인수로 전달할 수 없거나 배열이 암시 적으로 포인터로 성능이 저하된다고 불평해야합니다.


나는 그것이 대답인지 확실하지 않지만 배열 유형의 일부는 크기이므로 수용하려는 모든 크기에 대해 함수를 정의해야한다고 생각합니다.
clcto

함수 포인터 를 의미 합니까? 질문을 명확히하십시오.
user949300

2
@ user949300 아니오, 의견의 맥락에서 보면 그것은 분명합니다. 포인터가되기 때문에 함수에 배열을 전달할 수 없으며, 이것이 왜 그런지 알고 싶어합니다.
Doval

@DocBrown rlemon은 이에 대한 편집을 제안했습니다.
Florian Margaine 2014 년

답변:


18

그 이유에 대한 첫 번째 추측은 단순히 성능 및 메모리 절약 이유와 컴파일러 구현의 용이성 (특히 C가 발명되었을 당시의 컴퓨터 종류) 때문이었습니다. 거대한 값의 배열을 "값으로"전달하는 것은 스택에 큰 영향을 미치는 것으로 보였으며, 각 함수 호출에 대해 전체 배열 복사 작업이 필요하며 컴파일러는 올바른 어셈블리 코드를 출력하기 위해 더 똑똑해야합니다 (마지막 지점은 논란의 여지가 있습니다) . 또한 동적으로 할당 된 배열을 정적으로 할당 된 배열과 같은 방식으로 처리하는 것이 더 어렵습니다 (언어 구문의 관점에서).

편집 : 이 링크에서 일부 부분 읽은 후 실제 이유 (및 구조체의 배열이 값 유형으로 처리되는 반면 단독 배열은 그렇지 않은 이유)는 C의 이전 B와의 하위 호환성이라고 생각합니다 . Dennis Ritchie의 인용은 다음과 같습니다.

[...}이 솔루션은 유형이없는 BCPL과 유형 C 사이의 진화 체인에서 결정적인 점프를 구성했습니다. 저장에서 포인터의 구체화를 제거하고 대신 배열 이름이 표현식에 언급 될 때 포인터를 작성했습니다. 오늘날 C에서 유지되는 규칙은 배열 유형의 값이 표현식에 나타날 때 배열을 구성하는 첫 번째 객체에 대한 포인터로 변환된다는 것입니다.

이 발명은 언어 의미의 근본적인 변화에도 불구하고 대부분의 기존 B 코드가 계속 작동 할 수있게했습니다. [..]


5
값으로 A struct Foo { int array[N]; } 전달할 있습니다. 그리고 동적 및 정적 할당을 치료에 대한 마지막 비트는 같은 비린내 (엄격한 의미에서 배열은 항상 크기, 배열 인덱싱과 같은 것들이 있습니다에 대한 통합 개념이 포함되어 보인다 포인터는 당신이 정교한 수, 배열에 대한 포인터 붕괴와 결합)을?

@ delnan : 여기에 언급 된 일반적인 원칙이 적절하다고 생각합니다. 분명히 배열을 구조체로 감싸면 의도를 지정하는 것입니다. 일반적으로 거의 항상 참조로 전달됩니다.
Robert Harvey

또한 OP에서 불필요하게 pedantic으로 언급 된 의견을 발견했습니다. 분명히 값으로 배열이 아닌 포인터를 전달합니다. 그러나 똑같이 사실은 참조로 효과적으로 배열을 전달 한다는 것 입니다. 반대 의견이 첨부 된 길이가 아니라면이를 통과하기도 쉽습니다.
Robert Harvey

@RobertHarvey 유형 시스템에서 여전히 비대칭입니다. 구조 유형의 일부인 배열이 값으로 전달되는 경우에도 배열 유형을 제외하고는 모든 것이 값 으로 전달되며 호출 사이트에서 정확히 동일한 표기법을 사용합니다. 그리고 기능 서명에서).

@delnan : 기억해야하는 것 이외의 다른 이유는 무엇입니까?
Robert Harvey

9

메모리가 8kB 인 PDP 미니 컴퓨터는 매우 큰 스택을 할당 할 수 없습니다. 따라서 이러한 시스템에서는 예상되는 공통 서브 루틴 호출 사용을 위해 스택에서 수행해야 할 사항을 최소화 할 수 있도록 언어 설계 (또는 진화)에주의를 기울여야합니다. C는 오늘날에도 메모리 제한이있는 (몇 kB) 임베디드 시스템을 프로그래밍하는 데 여전히 사용되므로 일반적으로 절충이 좋습니다.

레지스터가 매우 적은 프로세서 아키텍처에서 값이 아닌 포인터로 배열을 전달하면 레지스터를 서브 루틴 호출 최적화로 더 자주 사용할 수 있습니다.


2
데이터에는 256 바이트의 RAM이 있고 코드에는 2K EEPROM이있는 보드가 있습니다. 거기에 배열의 사본을 만들고 싶지 않습니다.
Jerry Jeremiah
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.