배열과 함수를 다룰 때 패턴이 있습니다. 처음에는 조금보기 힘들다.
배열을 다룰 때 다음을 기억하는 것이 유용합니다. 대부분의 상황에서 배열식이 나타날 때 식의 유형은 암시 적으로 "T의 N- 요소 배열"에서 "포인터에서 T"로 변환되고 그 값이 설정됩니다 배열의 첫 번째 요소를 가리 킵니다. 이 규칙의 예외는 배열 표현식이 &
또는 sizeof
연산자 의 피연산자로 표시되거나 선언에서 초기화 자로 사용되는 문자열 리터럴 인 경우입니다.
따라서 배열 식을 인수로 사용하여 함수를 호출하면 함수가 배열이 아닌 포인터를받습니다.
int arr[10];
...
foo(arr);
...
void foo(int *arr) { ... }
따라서 "% s"에 해당하는 인수에 연산자를 사용 하지 않는 이유는 다음 &
과 scanf()
같습니다.
char str[STRING_LENGTH];
...
scanf("%s", str);
암시 적 변환 으로 인해 배열 의 시작을 가리키는 값을 scanf()
받습니다 . 이는 배열 표현식을 인수로 호출 한 함수 ( 함수 및 함수 등)에 해당됩니다. char *
str
str*
*scanf
*printf
실제로 다음과 같이 &
연산자를 사용하여 배열 표현식으로 함수를 호출하지 않을 것입니다 .
int arr[N];
...
foo(&arr);
void foo(int (*p)[N]) {...}
이러한 코드는 흔하지 않습니다. 함수 선언에서 배열의 크기를 알아야하며 함수는 특정 크기의 배열에 대한 포인터에서만 작동합니다 (T의 10 요소 배열에 대한 포인터는 11 요소 배열에 대한 포인터와 다른 유형입니다) T).
배열 표현식이 &
연산자 의 피연산자로 나타나는 경우 결과 표현식의 유형은 "T의 N- 요소 배열에 대한 포인터"또는 T (*)[N]
이며, 이는 포인터 배열 ( T *[N]
) 및 기본 유형에 대한 포인터 ( T *
).
함수와 포인터를 다룰 때 기억해야 할 규칙은 다음과 같습니다. 인수 값을 변경하고 호출 코드에 반영하려면 수정하려는 항목에 포인터를 전달해야합니다. 다시 말하지만, 배열은 약간의 멍키 렌치를 작동에 넣지 만 일반적인 경우를 먼저 처리합니다.
C는 모든 함수 인수를 값으로 전달 합니다 . 공식 매개 변수는 실제 매개 변수의 값 사본을 수신하며 공식 매개 변수의 변경 사항은 실제 매개 변수에 반영되지 않습니다. 일반적인 예는 스왑 함수입니다.
void swap(int x, int y) { int tmp = x; x = y; y = tmp; }
...
int a = 1, b = 2;
printf("before swap: a = %d, b = %d\n", a, b);
swap(a, b);
printf("after swap: a = %d, b = %d\n", a, b);
다음과 같은 결과가 나타납니다.
스왑 전 : a = 1, b = 2
스왑 후 : a = 1, b = 2
형식 매개 변수 x
와는 y
별개의 개체 a
및 b
변경 있도록, x
그리고이 y
에 반영되지 않습니다 a
및 b
. a
and 의 값을 수정하고자하므로 스왑 함수에 대한 포인터 를 b
전달해야합니다 .
void swap(int *x, int *y) {int tmp = *x; *x = *y; *y = tmp; }
...
int a = 1, b = 2;
printf("before swap: a = %d, b = %d\n", a, b);
swap(&a, &b);
printf("after swap: a = %d, b = %d\n", a, b);
이제 출력은
스왑 전 : a = 1, b = 2
스왑 후 : a = 2, b = 1
swap 함수에서 x
and 의 값을 변경하지 않고 y
what x
과 y
point 의 값을 변경합니다 . 글을 *x
쓰는 것은 글을 쓰는 것과 다릅니다 x
. 우리는 값 x
자체를 업데이트하지 않고 위치를 가져와 해당 위치 x
의 값을 업데이트합니다.
포인터 값을 수정하려는 경우에도 마찬가지입니다. 우리가 쓰면
int myFopen(FILE *stream) {stream = fopen("myfile.dat", "r"); }
...
FILE *in;
myFopen(in);
우리는 입력 매개 변수의 값을 수정하고 stream
,하지 무엇을 stream
가리키는 때문에 변경 stream
의 값에 영향을주지 않습니다 in
; 이것이 작동하려면 포인터에 대한 포인터를 전달해야합니다.
int myFopen(FILE **stream) {*stream = fopen("myFile.dat", "r"); }
...
FILE *in;
myFopen(&in);
다시 말하지만, 배열은 약간의 원숭이 렌치를 작품에 넣습니다. 배열 표현식을 함수에 전달할 때 함수가받는 것은 포인터입니다. 배열 첨자 정의 방법에 따라 배열에서 첨자 연산자를 사용하는 것과 같은 방식으로 포인터에 첨자 연산자를 사용할 수 있습니다.
int arr[N];
init(arr, N);
...
void init(int *arr, int N) {size_t i; for (i = 0; i < N; i++) arr[i] = i*i;}
배열 객체는 할당되지 않을 수 있습니다. 즉, 당신은 같은 것을 할 수 없습니다
int a[10], b[10];
...
a = b;
따라서 배열에 대한 포인터를 다룰 때주의해야합니다. 같은
void (int (*foo)[N])
{
...
*foo = ...;
}
작동하지 않습니다.