source

포인터 투 포인트 슛은 C에서 어떻게 작동합니까? (그리고 언제 사용할 수 있습니까?)

manysource 2022. 11. 5. 17:38

포인터 투 포인트 슛은 C에서 어떻게 작동합니까? (그리고 언제 사용할 수 있습니까?)

포인터 투 포인트 슛은 C에서 어떻게 작동합니까?
제제사 용용 ??? ???

8비트 주소(따라서 메모리 256바이트)를 가진 8비트 컴퓨터를 가정해 보겠습니다.이것은 그 메모리의 일부입니다(상단의 숫자는 주소입니다).

  54   55   56   57   58   59   60   61   62   63   64   65   66   67   68   69
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|    | 58 |    |    | 63 |    | 55 |    |    | h  | e  | l  | l  | o  | \0 |    |
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+

여기서 알 수 있는 것은 주소 63에서 문자열 "hello"가 시작됩니다.따라서 이 경우 메모리에서 "hello"가 유일한 경우,

const char *c = "hello";

의 정의...의 정의c(읽기 전용) 문자열 "hello"에 대한 포인터가 되므로 값 63이 포함됩니다. c그 자체를 어딘가에 저장해야 합니다.위의 예에서는 위치 58에 저장되어 있습니다., 릭릭, 른른, 른른, 른른, 른g, 른g,eg, eg, :g, ::, :g, :g:§:

const char **cp = &c;

, 이제cpc 「」, 「」의 c 58). 갈 수 있습니다.네, 이렇게요.★★★★★★★★★★★★★★★★★★:

const char ***cpp = &cp;

, 이제cpp에는, 의 주소가 격납되어 있습니다.cp따라서 값 55(위의 예에 따라)가 설정되어 있으며, 그 자체는 주소 60에 저장되어 있습니다.


포인터에 대한 포인터를 사용하는 이유:

  • 배열의 이름은 일반적으로 첫 번째 요소의 주소를 생성합니다. 요소가 되어 있는 t에는 타입이 t *t이에는 타입이 .「 」 「 2D 」 「 」 。(t *)*=t **는 포인터에 대한 포인터입니다.
  • 문자열 배열이 일차원적으로 들리지만 문자열이 문자 배열이기 때문에 실제로는 2차원입니다. : 이때에 hence,char **.
  • af는 타입의 인수를 .t **t *.
  • 여기에 나열하기에는 너무 많은 다른 이유들이 있다.

나는 포인터 사용에 대한 포인터의 이 "실제" 코드 예를 좋아한다. Git 2.0에서는 7b1004b를 커밋한다.

라이너스는 이렇게 말했다.

저는 사실 더 많은 사람들이 정말 핵심인 낮은 수준의 코딩에 대해 이해하기를 바랍니다.잠금 없는 이름 검색과 같은 크고 복잡한 것이 아니라 단순히 포인터 투 포인터 등을 사용할 수 있습니다.
예를 들어, "prev" 엔트리를 추적하여 단일 링크 목록 엔트리를 삭제한 후 다음과 같은 작업을 수행하여 엔트리를 삭제하는 사용자를 너무 많이 볼 수 있습니다.


   if (prev)
     prev->next = entry->next;
   else
     list_head = entry->next;

그런 코드만 보면 '이 사람은 포인터를 몰라' 이러면서그리고 슬프게도 꽤 흔합니다.

포인터를 이해하는 사람들은 "엔트리 포인터 포인터"를 사용하여 list_head 주소로 초기화합니다.그런 다음 목록을 이동할 때 조건을 사용하지 않고 항목을 제거할 수 있습니다.

*pp =  entry->next

포인터

이 심플화를 적용하면 코멘트를 2줄 추가해도 이 기능에서 7줄을 잃을 수 있습니다.

- struct combine_diff_path *p, *pprev, *ptmp;
+ struct combine_diff_path *p, **tail = &curr;

Chris는 2016년 비디오 "Linus Torvalds's Double Pointer Problem"에 대한 코멘트에서 지적합니다.


Kumar씨코멘트에서 블로그 투고 「Linus on Understanding Points」를 지적하고 있습니다.Grisha Trubetkoy는 다음과 같이 설명하고 있습니다.

다음과 같이 정의된 링크 목록이 있다고 가정합니다.

   typedef struct list_entry {
       int val;
       struct list_entry *next;
   } list_entry;

처음부터 끝까지 반복하여 값이 to_remove 값과 동일한 특정 요소를 제거해야 합니다.
하다

   list_entry *entry = head; /* assuming head exists and is the first entry of the list */
   list_entry *prev = NULL;
   
   while (entry) { /* line 4 */
       if (entry->val == to_remove)     /* this is the one to remove ; line 5 */
           if (prev)
              prev->next = entry->next; /* remove the entry ; line 7 */
           else
               head = entry->next;      /* special case - first entry ; line 9 */
   
       /* move on to the next entry */
       prev = entry;
       entry = entry->next;
   }

위의 내용은 다음과 같습니다.

  • 가 될 합니다.NULL
  • 삭제할 엔트리가 발견되면(5행),
  • 현재 다음 포인터의 값을 이전 포인터에 할당합니다.
  • 따라서 전류 요소(라인 7)가 제거됩니다.

. 항목이 .반복의 선두에는 이전 엔트리가 없습니다(prevNULL리스트의 첫 번째 엔트리를 삭제하려면 헤드 자체를 수정해야 합니다(9행).

Linus가 말하고자 하는 것은 위의 코드를 단순히 포인터가 아닌 포인터로 만드는 것으로 단순화할 수 있다는 것입니다.
을 사용하다

   list_entry **pp = &head; /* pointer to a pointer */
   list_entry *entry = head;

   while (entry) {
       if (entry->val == to_remove)
           *pp = entry->next;
       else
            pp = &entry->next;
       entry = entry->next;
   }

는 이전. 코드에서는, 「」를 참조해 .ppNULL영리합니다.심플하고 영리합니다.

이 가, 는, 「」, 「」, 「」, 「」라고 하고 있습니다.*pp = entry->nextatomic입니다.그것은 확실히 원자력이 아니다.
에는 2개의 연산자2」)가 되어 있습니다.* ★★★★★★★★★★★★★★★★★」->그리고 한 가지 과제가 있는데, 이 세 가지 중 어느 것도 원자적인 것이 아닙니다.
이것은 일반적인 오해입니다만, 애석하게도 C의 거의 모든 것이 원자적인 것으로 간주되어서는 안 됩니다.++ ★★★★★★★★★★★★★★★★★」--★★★★★★★★★★★★★★★★★★!

포인터에 대한 포인터는 C에서 어떻게 작동합니까?

우선 포인터는 다른 변수와 마찬가지로 변수이지만 변수의 주소를 유지합니다.

포인터에 대한 포인터는 다른 변수와 마찬가지로 변수이지만 변수의 주소를 유지합니다.그 변수는 단지 포인터일 뿐입니다.

언제 사용하실 건가요?

반환 값은 사용하지 않고 힙의 일부 메모리에 포인터를 반환해야 할 때 사용할 수 있습니다.

예:

int getValueOf5(int *p)
{
  *p = 5;
  return 1;//success
}

int get1024HeapMemory(int **p)
{
  *p = malloc(1024);
  if(*p == 0)
    return -1;//error
  else 
    return 0;//success
}

그리고 이렇게 부르죠.

int x;
getValueOf5(&x);//I want to fill the int varaible, so I pass it's address in
//At this point x holds 5

int *p;    
get1024HeapMemory(&p);//I want to fill the int* variable, so I pass it's address in
//At this point p holds a memory address where 1024 bytes of memory is allocated on the heap

모든 C 프로그램의 main() 인수에는 argv 포인터에 대한 포인터가 있으며 각 요소에는 명령줄 옵션인 문자 배열이 있습니다.포인터의 포인터를 사용하여 2차원 배열을 가리킬 때는 2차원 배열을 가리킬 때 포인터를 사용하는 것이 좋습니다.

왜 위험하죠?

void test()
{
  double **a;
  int i1 = sizeof(a[0]);//i1 == 4 == sizeof(double*)

  double matrix[ROWS][COLUMNS];
  int i2 = sizeof(matrix[0]);//i2 == 240 == COLUMNS * sizeof(double)
}

다음으로 2차원 배열에 대한 포인터의 예를 나타냅니다.

int (*myPointerTo2DimArray)[ROWS][COLUMNS]

ROWS 및 COLUMNS에 대해 다양한 수의 요소를 지원하려면 2차원 배열에 대한 포인터를 사용할 수 없습니다. 그러나 미리 알고 있으면 2차원 배열을 사용합니다.

이 개념을 더 잘 이해하려면 다음 그림과 프로그램을 검토하십시오.

이중 포인터 다이어그램

그림과 같이 ptr1변수 num의 주소를 가진 단일 포인터이다.

ptr1 = #

마찬가지로 ptr2는 포인터 ptr1의 주소를 가진 포인터(더블 포인터)에 대한 포인터입니다.

ptr2 = &ptr1;

다른 포인터를 가리키는 포인터를 더블 포인터라고 합니다.이 예에서는 ptr2가 더블 포인터입니다.

위 다이어그램의 값:

Address of variable num has : 1000
Address of Pointer ptr1 is: 2000
Address of Pointer ptr2 is: 3000

예:

#include <stdio.h>

int main ()
{
   int  num = 10;
   int  *ptr1;
   int  **ptr2;

   // Take the address of var 
   ptr1 = &num;

   // Take the address of ptr1 using address of operator &
   ptr2 = &ptr1;

   // Print the value
   printf("Value of num = %d\n", num );
   printf("Value available at *ptr1 = %d\n", *ptr1 );
   printf("Value available at **ptr2 = %d\n", **ptr2);
}

출력:

Value of num = 10
Value available at *ptr1 = 10
Value available at **ptr2 = 10

대학의 프로그래밍 코스에 관한 포인터를 다룰 때, 우리는 그것들을 배우기 시작하는 방법에 대한 두 가지 힌트를 얻었다.첫 번째는 포인터 펀을 빙키와 함께 보는 것이었다.두 번째는 루이스 캐럴의 '유리를 통해'에 나오는 '하덕의 눈'의 구절을 생각해보는 것이었다.

"당신은 슬프군요."라고 기사는 불안한 어조로 말했다. "너를 위로하기 위해 노래를 불러줄게."

"많이 길어요?"앨리스는 그날 많은 시를 들었기 때문에 물었다.

기사는 "긴데, 아주, 아주 아름답습니다."라고 말했다.제 노래를 듣는 사람들은 모두 눈물을 흘리거나 아니면 눈물을 흘리거나 둘 중 한 명이었어요.

"그렇지 않으면?"앨리스는 말했다.그 기사는 갑자기 멈칫하고 있었기 때문입니다.

"그렇지 않으면 그렇지 않습니다.이 노래의 제목은 '해덕스 아이즈'입니다."

"아, 그 노래 이름이구나"앨리스는 흥미를 느끼려고 애쓰며 말했어요.

"아뇨, 당신은 이해하지 못해요." 기사는 약간 짜증난 표정으로 말했다."이름을 그렇게 부릅니다.그 이름은 정말 노인이다.

"그러면 '그 노래'라고 했어야 했는데"앨리스는 정정했다.

"안 돼, 안 돼, 그건 전혀 다른 거야!이 노래의 제목은 'Ways And Means'입니다. 하지만 그 노래의 제목은 'Ways And Means'뿐입니다.

"그럼, 무슨 노래죠?" 이때 완전히 당황한 앨리스가 말했어요.

"그곳에 가고 있었어요." 기사가 말했다."이 노래는 정말 'A-Siting On A Gate'입니다. 그리고 이 곡은 제가 만든 것입니다."

포인터의 주소 값에 대한 포인터입니다.(그건 나도 알아)

기본적으로 다른 포인터의 주소 값으로 포인터를 넘기면 다음과 같이 하위 함수에서 다른 포인터가 가리키는 위치를 수정할 수 있습니다.

void changeptr(int** pp)
{
  *pp=&someval;
}

포인터에 대한 참조가 필요한 경우 포인터에 대한 포인터가 사용됩니다.예를 들어, 호출된 함수의 범위에서 선언된 포인터 변수의 값(주소를 가리킨 경우)을 변경하는 경우입니다.

단일 포인터를 인수로 전달하면 호출 범위 내의 원래 포인터가 아닌 포인터의 로컬복사본을 변경합니다.포인터에 대한 포인터를 사용하여 포인터를 수정합니다.

포인터에 대한 포인터

우리는 int에 대한 포인터, char에 대한 포인터, 그리고 우리가 정의한 구조에 대한 포인터, 그리고 사실 C의 어떤 타입에 대한 포인터를 가질 수 있기 때문에 우리가 다른 포인터에 대한 포인터를 가질 수 있다는 것은 그리 놀랄 일이 아니다.

포인터에 대한 포인터는 핸들이라고도 합니다.메모리 내에서 개체를 이동하거나 제거할 수 있는 경우가 많습니다.접근 시 오브젝트가 이동하지 않도록 오브젝트의 사용법을 잠그고 잠금을 해제하는 것이 일반적입니다.

Palm OS와 같이 메모리가 제한된 환경에서 자주 사용됩니다.

컴퓨터.howstuffworks.com 링크 >>

www.flippinbits.com 링크 >>

포인터의 구조를 설명하는 5분 분량의 비디오:


포인터 버킷

포인터에 대한 포인터는 포인터에 대한 포인터입니다.

의미 있는 예로서Type**는 2차원 어레이입니다.다른 어레이에 대한 포인터로 채워진 어레이가1개 있습니다.따라서 글을 쓸 수 있습니다.

모니터 [5][6]

5번째 위치에 있는 다른 어레이에 대한 포인터를 포함하는 어레이에 액세스하여 포인터를 얻은 다음(fpointer[6]), 해당 어레이를 참조하는 어레이의 6번째 요소(fpointer[6])에 액세스합니다.

주소가 포함된 변수가 있습니다.그건 포인터야.

그런 다음 첫 번째 변수의 주소를 포함하는 다른 변수가 있습니다.그건 포인터로 가는 포인터야.

구조:다른 포인터를 저장할 수 있는 변수입니다.

언제 사용할 것인가: 많은 경우, 그 중 하나는 함수가 배열을 구축하여 호출자에게 반환하는 경우입니다.

//returns the array of roll nos {11, 12} through paramater
// return value is total number of  students
int fun( int **i )
{
    int *j;
    *i = (int*)malloc ( 2*sizeof(int) );
    **i = 11;  // e.g., newly allocated memory 0x2000 store 11
    j = *i;
    j++;
    *j = 12; ;  // e.g., newly allocated memory 0x2004 store 12

    return 2;
}

int main()
{
    int *i;
    int n = fun( &i ); // hey I don't know how many students are in your class please send all of their roll numbers.
    for ( int j=0; j<n; j++ )
        printf( "roll no = %d \n", i[j] );

    return 0;
}

유용한 설명들이 많긴 한데, 간단한 설명을 못 찾아서..

기본적으로 포인터는 변수의 주소입니다.간단한 요약 코드:

     int a, *p_a;//declaration of normal variable and int pointer variable
     a = 56;     //simply assign value
     p_a = &a;   //save address of "a" to pointer variable
     *p_a = 15;  //override the value of the variable

//print 0xfoo and 15 
//- first is address, 2nd is value stored at this address (that is called dereference)
     printf("pointer p_a is having value %d and targeting at variable value %d", p_a, *p_a); 

참조참조 해제의 의미 항목에서도 유용한 정보를 찾을 수 있습니다.

그리고 언제가 유용한 포인터가 될지는 잘 모르겠습니다만, 공통적으로 수동/동적 메모리 할당(malloc, calloc 등)실시할 때는 포인터를 사용해야 합니다.

그래서 문제가 있는 부분을 명확히 하는 데에도 도움이 되었으면 합니다.

언급URL : https://stackoverflow.com/questions/897366/how-do-pointer-to-pointers-work-in-c-and-when-might-you-use-them