C의 함수 인수로 포인터
예를 들어 다음과 같은 코드를 사용할 수 있습니다.
int num = 5;
int *ptr = #
다음 두 기능의 차이점은 무엇입니까?
void func(int **foo);
void func(int *foo);
함수를 호출하는 위치:
func(&ptr);
둘 중 하나는 포인터를 매개 변수로 사용하고, 두 번째는 포인터만 사용한다는 것을 알고 있습니다.
지나가면func(&ptr)
, 저는 효과적으로 포인터를 보내고 있습니다.포인터가 다른 포인터를 가리킨다면 어떤 차이가 있습니까?
후자가 비호환성 경고를 할 것으로 생각하지만, 당신이 무엇을 하고 있는지 알기만 하면 세부 사항은 중요하지 않은 것 같습니다.가독성과 전자를 이해하기 위해서 더 나은 선택지(2성 포인터)인 것 같지만 논리적인 관점에서 보면 어떤 차이가 있습니까?
사용자가 정확하게 전달된 내용을 변경할 수 없다는 것이 합리적인 경험칙입니다. 이는 발신자가 변경 내용을 보는 방식입니다.포인터를 전달하는 것이 해결책입니다.
:void fcn(int foo)
값을 전달하면 값의 복사본을 얻을 수 있습니다.함수의 값을 변경해도 호출자는 변경 내용에 관계없이 원래 값을 볼 수 있습니다.
포인터를 값으로 전달:void fcn(int* foo)
포인터를 지나가면 포인터의 복사본이 나타납니다. 포인터는 원본과 동일한 메모리 위치를 가리킵니다.이 메모리 위치는 원본이 저장되는 위치입니다.이렇게 하면 포인투 값을 변경할 수 있습니다.그러나 포인터 복사본만 받았기 때문에 실제 포인터를 데이터로 변경할 수는 없습니다.
포인터를 값에 포인터 전달:void fcn(int** foo)
포인터를 값에 대한 포인터로 전달하면 위의 내용을 이해할 수 있습니다.위와 같이 발신자 코드가 사용하고 있는 메모리 위치와 동일하므로 발신자가 변경 내용을 볼 수 있도록 값을 변경할 수 있습니다.같은 이유로 포인터를 값으로 변경할 수 있습니다.이를 통해 함수 내에 메모리를 할당하고 반환하는 등의 작업을 수행할 수 있습니다.&arg2 = calloc(len);
수 복사본을 받기 때문에 포인터를 포인터로 변경할 수는 없습니다.
프로세서가 코드를 처리할 때 차이점은 간단히 말해집니다.가치 자체는 두 경우 모두 주소일 뿐입니다. 사실입니다.그러나 주소가 역참조됨에 따라 프로세서와 컴파일러 모두가 역참조 후 무엇을 처리할 것인지 아는 것이 중요합니다.
예를 들어 다음과 같은 코드를 사용할 수 있습니다.
int num = 5; int *ptr = #
다음 두 기능의 차이점은 무엇입니까?
void func(int **foo); void func(int *foo);
첫번째는 int를 가리키는 포인터를 원하고, 두번째는 int를 직접 가리키는 포인터를 원합니다.
함수를 호출하는 위치:
func(&ptr);
~하듯이ptr
인트를 가리키는 지시자입니다&ptr
주소이며, A와 호환됩니다.int **
.
a를 취하는 함수는int *
와 같이 뭔가 다른 일을 할 것입니다.int **
되지 않은 할 수 대화의 결과가 완전히 달라져서 정의되지 않은 행동으로 이어지거나 충돌이 발생할 수 있습니다.
func(&ptr)를 통과하면 포인터를 효과적으로 통과합니다.포인터가 다른 포인터를 가리킨다면 어떤 차이가 있습니까?
+++++++++++++++++++
adr1 (ptr): + adr2 +
+++++++++++++++++++
+++++++++++++++++++
adr2 (num): + 42 +
+++++++++++++++++++
앳.adr2
, 42달러의 내재가치가 있습니다.
앳.adr1
, 우리는 주소를 가지고 있습니다.adr2
, 포인터만 한 크기의
&ptr
우리에게 dr1을 주고,ptr
, 가치가 있습니다.&num
은 dr2 .
사용하면adr1
…int *
,adr2
정수로 잘못 처리되어 (possibly가 상당히 큰) 숫자로 이어집니다.
사용하면adr2
…int **
, 첫 번째 참조 해제는 42로 이어지는데, 이는 주소로 잘못 interpre되어 프로그램이 중단될 가능성이 있습니다.
그것은 단지 광학적인 것 이상의 차이를 가지는 것입니다.int *
그리고.int **
.
후자가 위화감 경고를 할 것이라고 생각합니다.
... 그 뜻은...
하지만 당신이 뭘 하고 있는지 알기만 하면 세부사항은 중요하지 않은 것 같습니다.
그러니?
가독성과 전자를 이해하기 위해서 더 나은 선택지(2성 포인터)인 것 같지만 논리적인 관점에서 보면 어떤 차이가 있습니까?
그것은 기능이 포인터로 무엇을 하느냐에 따라 달라집니다.
실무적으로 크게 두 가지 차이점이 있습니다.
포인터를 포인터에 전달하면 호출자가 볼 수 있는 방식으로 해당 포인터의 내용을 수정할 수 있습니다.고전적인 예는 두번째 주장입니다.
strtol()
. 에 전화를 걸면 다음으로strtol()
, 해당 포인터의 내용은 계산하기 위해 구문 분석되지 않은 문자열의 첫 번째 문자를 가리켜야 합니다.long
value로 요. 만약 당신이 그 포인터를 그냥 넘겨줬다면.strtol()
, 그러면 변경 사항은 로컬이 될 것이고, 발신자에게 위치를 알리는 것은 불가능할 것입니다.그 포인터의 주소를 넘기면strtol()
호출자가 볼 수 있는 방식으로 수정할 수 있습니다.다른 변수의 주소를 전달하는 것과 같습니다.더 근본적으로, 컴파일러는 참조를 해제하기 위해 가리키는 유형을 알아야 합니다.예를 들어, 재참조할 때 a.
double *
, 컴파일러가 해석할 것입니다. (다음과 같은 구현에 대해)double
8바이트를 소비합니다) 메모리 위치에서 시작하는 8바이트를 두 배의 값으로 사용합니다.하지만 32비트 구현에서, 재참조할 때,double **
, 컴파일러는 그 위치에서 시작하는 4바이트를 다른 두 배의 주소로 해석할 것입니다.포인터를 재참조할 때 해당 주소에서 데이터를 해석하는 방법에 대해 컴파일러가 가진 정보는 포인터가 가리키는 유형뿐이므로 정확한 유형을 아는 것이 중요하며, 이 때문에 "모두 포인터일 뿐인데 뭐가 다를까?"라고 생각하면 오류가 발생합니다.
일반적으로 이 차이는 함수가 포인터에 할당된다는 것을 의미하며, 이 할당은 함수에만 로컬로 적용되어서는 안 됩니다.예를 들어, (그리고 이 예들은 완전한 기능이 아닌 음식의 특성을 조사하기 위한 것이며, 원래 게시물의 코드가 실제 작동 코드인 것으로 간주되는 것 이상의 것임을 명심하십시오.)
void func1 (int *foo) {
foo = malloc (sizeof (int));
}
int a = 5;
func1 (&a);
와 비슷합니다.
void func2 (int foo) {
foo = 12;
}
int b = 5;
func2 (b);
그런 의미에서foo
func2 (),에서는 12와 같을 수 있지만 func2 ()이 돌아오면,b
5와 같아질 겁니다func1()에서,foo
새로운 int를 가리키지만,a
아직은a
func1 ()이 돌아올 때.
만약 우리가 그 가치를 바꾸고 싶다면?a
아니면b
? WRTb
, 정규 int:
void func3 (int *foo) {
*foo = 12;
}
int b = 5;
func2 (&b);
효과가 있을 겁니다. 우리는 int에 대한 포인터가 필요하다는 것을 주목하세요.포인터의 값을 변경합니다(즉,int가 가리키는 주소(Int가 가리키는 값뿐만 아니라 int가 가리키는 주소):
void func4 (int **foo) {
*foo = malloc (sizeof (int));
}
int *a;
foo (&a);
'a'는 이제 func4에서 malloc에 의해 반환된 기억을 가리킵니다.주소를&a
주소는a
, 인트를 가리키는 말int 포인터는 int의 주소를 포함합니다.func4()
func3 ()가 int의 주소를 가져가서 새로운 int 값을 넣을 수 있는 것처럼 int의 주소를 이 주소에 넣을 수 있도록 int 포인터의 주소를 가져갑니다.
이렇게 다양한 논증 스타일이 사용됩니다.
이 질문을 받은 지는 꽤 됐지만, 여기에 대한 저의 의견이 있습니다.나는 지금 C를 배우려고 노력중이고 포인터들은 끝없이 혼란스럽습니다...그래서 저는 적어도 저를 위해 포인터에 대한 포인터를 명확히 하기 위해 이 시간을 할애하고 있습니다.제 생각은 이렇습니다.
여기서 예를 들어 보겠습니다.
#include <stdlib.h>
#include <string.h>
int allocstr(int len, char **retptr)
{
char *p = malloc(len + 1); /* +1 for \0 */
if(p == NULL)
return 0;
*retptr = p;
return 1;
}
int main()
{
char *string = "Hello, world!";
char *copystr;
if(allocstr(strlen(string), ©str))
strcpy(copystr, string);
else fprintf(stderr, "out of memory\n");
return 0;
}
allocstr에 더블 포인터가 필요한 이유가 궁금합니다.포인터라면 패스할 수 있으며 반환 후 변경됩니다.
이 예제를 수행하면 잘 작동합니다.그러나 allocstr을 **pointer 대신 *pointer만(및 ©strin main 대신 copystr만)하도록 변경하면 segmentation fault가 발생합니다. 왜죠?코드에 프린트를 좀 넣었는데 strcpy가 있는 라인까지 잘 작동합니다.그래서 나는 그것이 copystr에 대한 메모리를 할당하지 않았다고 추측합니다.다시 한번, 왜?
포인터로 지나가면 어떤 의미가 있는지 다시 한 번 살펴보도록 하겠습니다.즉, 기억 위치를 지나면 원하는 값을 바로 쓸 수 있습니다.값의 메모리 위치에 액세스할 수 있으므로 값을 수정할 수 있습니다.
마찬가지로 포인터를 포인터에 전달하면 포인터의 메모리 위치, 즉 메모리 위치의 메모리 위치를 전달합니다.이제 포인터만 사용할 때 값을 변경할 수 있으므로 메모리 위치를 변경할 수 있습니다.
코드가 작동하는 이유는 메모리 위치의 주소를 전달하기 때문입니다.함수 allocstr은 "Hello world!"를 유지할 수 있도록 해당 메모리 위치의 크기를 변경하고 해당 메모리 위치에 포인터를 반환합니다.
포인터를 보내는 것과 같지만 값 대신 메모리 위치가 있습니다.
C에서 링크된 구조를 사용하는 경우, 예를 들어 단순 링크된 리스트.목록에 일부 항목이 있고 새 항목을 추가하려는 경우 항목 순서가 중요하지 않을 때 처음에 삽입하는 것이 가장 쉬운 방법입니다.자, 여기 간단한 아이템 구조가 있습니다.
typedef struct {
char *data; /* item data */
struct item *next; /* point to successor */
} item;
그리고 맨 앞에 삽입하면,
void insert_item( item **head, char *data) {
item *new_item; /* temporary pointer */
new_item = malloc( sizeof(item) );
new_item->data = data;
/* This is how we would set the next item if the parameter was item* head */
//new_item->next = head;
/* till this line, nothing useful for passing item** head */
new_item->next = *head;
/*
* Here is where we needed to update the head to point to the newly inserted item at
* the beginning. which wouldn't be possible if the head parameter was item* head.
*/
*head = new_item;
}
이렇게 테스트를 할 수 있습니다.
item *head;
head = malloc( sizeof(item) );
head->data = "head item data";
printf("before inserting: %s \n", head->data); //before inserting: head item data
insert_item(&head, "new item data");
printf("after inserting: %s \n", head->data); //after inserting: new item data
언급URL : https://stackoverflow.com/questions/18698317/pointers-as-function-arguments-in-c
'programing' 카테고리의 다른 글
j부모의 부모 쿼리 (0) | 2023.10.28 |
---|---|
iOS 오류 "임베디드 바이너리가 상위 앱과 동일한 인증서로 서명되지 않았습니다." (0) | 2023.10.28 |
Chart.js의 파이 차트에서 이벤트를 클릭 (0) | 2023.10.28 |
글꼴(@font-face)이 이미 로드되었는지 어떻게 알 수 있습니까? (0) | 2023.10.28 |
양식 유효성 검사 - 전자 메일 유효성 검사가 AngularJs에서 예상대로 작동하지 않습니다. (0) | 2023.10.28 |