나는 단지 C를 배우고 있으며 주요 방법으로 사용해야하는 것이 무엇인지 궁금합니다. 차이점이 있습니까? 어느 것이 더 흔합니까?
답변
C를 배우는 동안 일반적인 것 대신 배열과 포인터 의 차이점 을 먼저 이해하는 것이 좋습니다 .
매개 변수 및 배열 영역에는 몇 가지 혼란스러운 규칙이 있으므로 계속 진행해야합니다. 먼저 매개 변수 목록에서 선언 한 내용은 특별하게 취급됩니다. C에서 함수 매개 변수로 이해가되지 않는 상황이 있습니다.
- 매개 변수로서의 기능
- 매개 변수로서의 배열
매개 변수로서의 배열
두 번째는 즉시 명확하지 않을 수 있습니다. 그러나 배열 차원의 크기가 C의 유형의 일부라고 생각할 때 명확합니다 (차원 크기가 주어지지 않은 배열은 불완전한 유형을 가짐). 따라서 값으로 배열을 가져 오는 함수 (복사본을받는 함수)를 만들면 한 가지 크기로만 수행 할 수 있습니다! 또한 배열이 커질 수 있으며 C는 가능한 한 빨리 노력합니다.
C에서는 이러한 이유로 배열 값 이 존재하지 않습니다. 배열의 값을 얻으려면 대신 배열의 첫 번째 요소에 대한 포인터입니다. 그리고 여기에 실제로 해결책이 있습니다. C 컴파일러는 유효하지 않은 배열 매개 변수를 그리는 대신 각 매개 변수의 유형을 포인터로 변환 합니다. 이것을 기억하십시오, 그것은 매우 중요합니다. 매개 변수는 배열이 아니라 대신 해당 요소 유형에 대한 포인터입니다.
이제 배열을 전달하려고하면 대신 전달되는 것은 배열의 첫 번째 요소에 대한 포인터입니다.
소풍 : 매개 변수로 기능
완성을 위해, 이것이 문제를 더 잘 이해하는 데 도움이 될 것이라고 생각하기 때문에 매개 변수로 함수를 사용하려고 할 때 업무 상태가 무엇인지 살펴 보겠습니다. 실제로, 먼저 이해가되지 않습니다. 매개 변수는 어떻게 함수가 될 수 있습니까? 물론, 우리는 그 장소에서 변수를 원합니다! 따라서 컴파일러가 발생할 때 수행하는 작업은 다시 함수를 함수 포인터 로 변환 하는 것 입니다. 함수를 전달하려고하면 해당 함수에 대한 포인터가 대신 전달됩니다. 따라서 다음은 동일합니다 (배열 예제와 유사).
void f(void g(void));
void f(void (*g)(void));
괄호 *g
가 필요합니다. 그렇지 않으면 반환하는 함수 void*
에 대한 포인터 대신 반환하는 함수를 지정합니다 void
.
배열로 돌아 가기
이제 처음에는 배열에 불완전한 유형이있을 수 있다고 말했습니다. 아직 크기를 지정하지 않으면 발생합니다. 우리는 이미 배열 매개 변수가 존재하지 않지만 대신 배열 매개 변수가 포인터라는 것을 알았으므로 배열의 크기는 중요하지 않습니다. 즉, 컴파일러는 다음을 모두 번역하며 모두 동일합니다.
int main(int c, char **argv);
int main(int c, char *argv[]);
int main(int c, char *argv[1]);
int main(int c, char *argv[42]);
물론 크기를 넣을 수있는 것은 이치에 맞지 않으며 그냥 버려집니다. 이런 이유로 C99는 그 숫자에 새로운 의미를 부여했으며 대괄호 사이에 다른 것들이 나타날 수 있습니다.
// says: argv is a non-null pointer pointing to at least 5 char*'s
// allows CPU to pre-load some memory.
int main(int c, char *argv[static 5]);
// says: argv is a constant pointer pointing to a char*
int main(int c, char *argv[const]);
// says the same as the previous one
int main(int c, char ** const argv);
마지막 두 줄은 함수 내에서 “argv”를 변경할 수 없다고 말합니다. const 포인터가되었습니다. 그래도 C99 기능을 지원하는 C 컴파일러는 거의 없습니다. 그러나 이러한 기능을 통해 “배열”이 실제로는 아니라는 것을 알 수 있습니다. 포인터입니다.
경고의 말
위에서 말한 것은 함수 의 매개 변수 로 배열을 얻은 경우에만 해당됩니다 . 로컬 배열로 작업하는 경우 배열은 포인터가 아닙니다. 윌 동작 값 읽을 때 등의 이전 포인터 배열로 변환한다 설명하기 때문에, 포인터로. 그러나 포인터와 혼동해서는 안됩니다.
대표적인 예는 다음과 같습니다.
char c[10];
char **c = &c; // does not work.
typedef char array[10];
array *pc = &c; // *does* work.
// same without typedef. Parens needed, because [...] has
// higher precedence than '*'. Analogous to the function example above.
char (*array)[10] = &c;
답변
어느 쪽이든 사용할 수 있습니다. 그것들은 완전히 같습니다. litb 의 의견과 답변을 참조하십시오 .
실제로 사용 방법에 달려 있습니다 (어쨌든 어느 쪽이든 사용할 수 있습니다).
// echo-with-pointer-arithmetic.c
#include <stdio.h>
int main(int argc, char **argv)
{
while (--argc > 0)
{
printf("%s ", *++argv);
}
printf("\n");
return 0;
}
// echo-without-pointer-arithmetic.c
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
for (i=1; i<argc; i++)
{
printf("%s ", argv[i]);
}
printf("\n");
return 0;
}
어느 것이 더 일반적인지는 중요하지 않습니다. 코드를 읽는 숙련 된 C 프로그래머는 둘 다 호환 가능한 것으로 간주합니다 (올바른 조건에서). 숙련 된 영어 사용자가 “그들”과 “그들”을 똑같이 쉽게 읽는 것처럼.
더 중요한 것은 당신이 그것들을 읽고 그것들이 얼마나 비슷한지를 배우는 것입니다. 작성하는 것보다 더 많은 코드를 읽을 수 있으며 두 가지 모두에 대해 똑같이 편안해야합니다.
답변
차이는 없지만 char *argv[]
가변 길이 문자열 (보통 char *
) 의 고정 크기 배열임을 보여주기 때문에 사용 합니다 .
답변
C 배열에서와 같이 두 가지 형식 중 하나를 사용할 수 있으며 함수 매개 변수 목록에서 포인터를 서로 바꿀 수 있습니다. http://en.wikipedia.org/wiki/C_(programming_language)#Array-pointer_interchangeability를 참조하십시오 .
답변
실제로 차이를 만들지는 않지만 후자는 더 읽기 쉽습니다. 두 번째 버전과 같이 char 포인터 배열이 제공됩니다. 그러나 첫 번째 버전에서와 같이 암시 적으로 이중 문자 포인터로 변환 될 수 있습니다.
답변
그것을 선언 char *argv[]
하는 많은 동등한 방법으로 인해 직관적 인 의미에 가장 가까운 문자열 배열로 선언해야합니다.
답변
char ** → 문자 포인터에 대한 포인터 및 char * argv []는 문자 포인터의 배열을 의미합니다. 배열 대신 포인터를 사용할 수 있으므로 둘 다 사용할 수 있습니다.