C에서 두 함수의 차이점은 무엇입니까? 배열과 배열 포인터를 C에서 함수로 전달할 때의 차이점
void f1(double a[]) {
//...
}
void f2(double *a) {
//...
}
내가 실질적으로 긴 배열에있는 함수를 호출한다면
,이 두 가지 기능은 스택에 더 많은 공간을 것, 다르게 행동 것인가?C에서 두 함수의 차이점은 무엇입니까? 배열과 배열 포인터를 C에서 함수로 전달할 때의 차이점
void f1(double a[]) {
//...
}
void f2(double *a) {
//...
}
내가 실질적으로 긴 배열에있는 함수를 호출한다면
,이 두 가지 기능은 스택에 더 많은 공간을 것, 다르게 행동 것인가?첫째, 일부 standardese (원형 포함)
6.7.5.3 함수 선언자
... ' 형 배열'과 같은 파라미터
7 선언 '한다 '한정형 포인터가 유형' '으로 조정 된 경우 형식 한정자 (있는 경우)는 배열 형식 deriva의 및]
내에 지정된 것입니다. .static
이 배열 유형 유도의 및]
에도 나타나는 경우 해당 함수를 호출 할 때마다 해당 실제 인수 값은 적어도 만큼 배열의 첫 번째 요소에 대한 액세스를 제공해야합니다 크기 표현식에 의해 지정된 요소. 이T *a
을 선언했다 것처럼 그래서, 짧은에, 어떤 함수 매개 변수가T a[]
또는T a[N]
로 선언
는 처리됩니다.
그래서 배열 매개 변수가 포인터로 선언 된 것처럼 취급되는 이유는 무엇입니까? 여기에 이유 :
6.3.2.1 Lvalues, 배열, 기능 지정자는sizeof
운영자 또는 단항&
연산자의 피연산자, 또는 문자열 리터럴 인 경우를 제외하고
...
3 배열을 초기화하는 데 사용되는 배열의 형식이 ' 유형'인 표현식이 배열 객체 의 초기 요소를 가리키는 포인터 유형이 ' 유형'인 표현식으로 변환 된 인 경우 lvalue가 아닙니다. 배열 객체에 레지스터 저장 클래스가 있으면 동작이 정의되지 않습니다.
다음 코드 감안할 : 해당 유형은 암시 적으로 "10 요소의 배열로 변환되도록
int main(void)
{
int arr[10];
foo(arr);
...
}
호출에 foo
행을 배열 식 arr
는 어느 sizeof
또는 &
의 피연산자 아니다 int
"부터"int
에 대한 포인터 "까지의 값은 6.2.3.1/3에 따릅니다. 따라서 foo
은 배열 값이 아닌 포인터 값을받습니다.
6.7.5.3/7의 때문에 foo
void foo(int a[]) // or int a[10]
{
...
}
을 쓸 수 있지만,
void foo(int *a)
{
...
}
이 따라서, 두 가지 형태가 동일로 해석됩니다.
6.7.5.3/7의 마지막 문장은 C99 도입, 기본적으로 당신이
void foo(int a[static 10])
{
...
}
같은 매개 변수 선언이있는 경우 a
에 해당하는 실제 매개 변수가 적어도 와 배열해야한다는 것을 의미했다 요소가 10 개 있습니다.
차이점은 순전히 구문입니다. C에서는 배열 표기법이 함수 매개 변수에 사용될 때 자동으로 포인터 선언으로 변환됩니다.
@ Kaushik :이 경우에도 동일하지만 일반적으로는 동일하지 않습니다 (http://stackoverflow.com/questions/2096448/do-these-statements-about). -pointers-have-the-effect) –
@BlueRaja : 예, C의 함정 중 하나입니다. 함수 매개 변수의 선언은 지역 변수의 선언과 매우 유사하지만 약간의 차이점이 있습니다 (예 : 이 배열 - 포인터 자동 변환과 같이) 부주의 한 프로그래머를 물들이는 경향이있다. –
아니요, 차이는 없습니다. 나는 IDA의 바이너리 파일을 모두 호출 버전의 .exe로 주요 기능을 분해 할 때
#include <stdio.h>
void function(int* array) {
int a =5;
}
void main() {
int array[]={2,4};
function(array);
getch();
}
내가 정확히 같은 어셈블리 코드를 아래와 같이 얻을 : (와 Mingw) 컴파일러 ++ 내가 데브 C이 C 코드를 작성 테스트하려면 :
push ebp
mov ebp, esp
sub esp, 18h
and esp, 0FFFFFFF0h
mov eax, 0
add eax, 0Fh
add eax, 0Fh
shr eax, 4
shl eax, 4
mov [ebp+var_C], eax
mov eax, [ebp+var_C]
call sub_401730
call sub_4013D0
mov [ebp+var_8], 2
mov [ebp+var_4], 4
lea eax, [ebp+var_8]
mov [esp+18h+var_18], eax
call sub_401290
call _getch
leave
retn
그래서이 호출의 두 버전 사이의 차이, 적어도 컴파일러 위협을 똑같이이 없습니다.
죄송합니다. 그러나 이것은 gcc의 일부 버전이 둘 다 x86에서 동일한 어셈블리를 생성한다는 것을 증명합니다. 정답, 잘못된 설명. – lambdapower
컴파일러가 두 가지 경우에서 다르게 함수 이름을 잘못 mangling하기 때문에 (적어도 이전 버전의 MSVC C++ 컴파일러를 사용하는 경우에는 차이점이 있음) 링크 문제가 발생합니다. 버그 리포트는 http://connect.microsoft.com/VisualStudio/feedback/details/326874/inconsistent-name-mangling-for-functions-accepting-array-and-pointer-parameters에서 "수정 안 함"을 참조하십시오. – greggo