포인터 주소와 포인터 값을 증가시키는 방법은 무엇입니까?


96

가정 해 봅시다.

int *p;
int a = 100;
p = &a;

다음 코드는 실제로 무엇을 어떻게할까요?

p++;
++p;
++*p;
++(*p);
++*(p);
*p++;
(*p)++;
*(p)++;
*++p;
*(++p);

나는 이것이 코딩 측면에서 다소 지저분하다는 것을 알고 있지만, 우리가 이와 같이 코딩 할 때 실제로 어떤 일이 일어날 지 알고 싶습니다.

참고 : 의 주소가 주소 인 a=5120300포인터에 저장되어 있다고 가정합니다 . 이제 각 문을 실행 한 후의 값은 무엇입니까?p3560200p & a


3
왜 디버거에서 실행하지 않습니까?
AndersK

24
글쎄요 .. 그냥 시도해 보시지 않겠 습니까? printf% p로 포인터를 인쇄합니다
Brian Roach 2011

행동에 대해 궁금하다면 그냥 가지고 놀아보세요. 이 모든 유스 케이스를 거치는 간단한 c 프로그램을 작성하고 그것이 당신에게 의미가 있는지 확인하십시오.
Cyrus

@AndersK. OP가 정의되지 않은 동작을 기대할 수 있습니까? ... 아니면 아닐 수도 있습니다.
Mateen Ulhaq 2011

답변:


180

첫째, ++ 연산자가 * 연산자보다 우선하고 () 연산자가 다른 모든 연산자보다 우선합니다.

둘째, ++ number 연산자는 아무 것도 할당하지 않으면 number ++ 연산자와 같습니다. 차이점은 number ++는 숫자를 반환 한 다음 숫자를 증가시키고, ++ number는 먼저 증가한 다음이를 반환한다는 것입니다.

셋째, 포인터의 값을 늘리면 내용의 크기만큼 포인터가 증가합니다. 즉, 배열에서 반복하는 것처럼 포인터를 증가시킵니다.

따라서 모든 것을 요약하면 다음과 같습니다.

ptr++;    // Pointer moves to the next int position (as if it was an array)
++ptr;    // Pointer moves to the next int position (as if it was an array)
++*ptr;   // The value of ptr is incremented
++(*ptr); // The value of ptr is incremented
++*(ptr); // The value of ptr is incremented
*ptr++;   // Pointer moves to the next int position (as if it was an array). But returns the old content
(*ptr)++; // The value of ptr is incremented
*(ptr)++; // Pointer moves to the next int position (as if it was an array). But returns the old content
*++ptr;   // Pointer moves to the next int position, and then get's accessed, with your code, segfault
*(++ptr); // Pointer moves to the next int position, and then get's accessed, with your code, segfault

여기에는 케이스가 많기 때문에 실수를했을지도 모르지만, 틀렸다면 정정 해주세요.

편집하다:

그래서 나는 틀렸고, 우선 순위는 내가 쓴 것보다 조금 더 복잡합니다. http://en.cppreference.com/w/cpp/language/operator_precedence


6
* ptr ++, 값은 증가하지 않고 포인터는 증가합니다. 이러한 단항 연산자는 우선 순위가 동일하지만 오른쪽에서 왼쪽으로 평가됩니다. 코드는 "ptr이 가리키는 곳에서 내용을 가져온 다음 ptr을 증가시킨다"는 의미입니다. 매우 일반적인 C 코드입니다 (예, 매우 혼란 스럽습니다). 이 문제를 수정하면 반대표를 제거하겠습니다. * (ptr) ++와 동일하며 괄호는 아무것도하지 않습니다.
Lundin 2011

Lundin에게 대단히 감사합니다. 내가 다른 것을 놓친 것이 있습니까?
felipemaia 2011

@Lundin 안녕하세요, 위의 답변이 수정 되었습니까? 감사.
Unheilig 2014 년

4
@Unheilig 첫 번째 문장은 여전히 ​​완전히 잘못되었습니다. 접두사 ++는 접두사 ++와 동일한 우선 순위를 갖는 단항 *보다 우선합니다. 그 외에는 괜찮아 보입니다.
룬딘

4
@felipemaia segfault가 확실합니까? 아마도 정의되지 않은 동작일까요?
jotik apr

15

프로그램을 확인하고 결과는 다음과 같습니다.

p++;    // use it then move to next int position
++p;    // move to next int and then use it
++*p;   // increments the value by 1 then use it 
++(*p); // increments the value by 1 then use it
++*(p); // increments the value by 1 then use it
*p++;   // use the value of p then moves to next position
(*p)++; // use the value of p then increment the value
*(p)++; // use the value of p then moves to next position
*++p;   // moves to the next int location then use that value
*(++p); // moves to next location then use that value

2
@alex 사용은 예를 들어 'int * a = p ++;' 여기서 포인터 'p'의 첫 번째 값이 사용되며 그 후에 p는 다음 위치로 이동합니다. 따라서 위의 문을 실행 한 후 'a'는 'p'가 가리키는 이전 위치의 주소를 가지며 'p'는 다음 위치를 가리키는 것입니다. 먼저 위와 같이 할당 표현식에 'p'값을 사용하고 다음 위치를 가리 키도록 'p'값을 증가시킵니다
Sujith R Kumar

요컨대 그는 "할당"이라는 좀 더 공식적인 용어에 "사용"이라는 문구를 사용한다고 생각합니다. 그게 다입니다.
Apekshik Panigrahi

4

다음은 다양한 "인쇄하기"제안의 인스턴스화입니다. 나는 그것이 유익하다는 것을 알았다.

#include "stdio.h"

int main() {
    static int x = 5;
    static int *p = &x;
    printf("(int) p   => %d\n",(int) p);
    printf("(int) p++ => %d\n",(int) p++);
    x = 5; p = &x;
    printf("(int) ++p => %d\n",(int) ++p);
    x = 5; p = &x;
    printf("++*p      => %d\n",++*p);
    x = 5; p = &x;
    printf("++(*p)    => %d\n",++(*p));
    x = 5; p = &x;
    printf("++*(p)    => %d\n",++*(p));
    x = 5; p = &x;
    printf("*p++      => %d\n",*p++);
    x = 5; p = &x;
    printf("(*p)++    => %d\n",(*p)++);
    x = 5; p = &x;
    printf("*(p)++    => %d\n",*(p)++);
    x = 5; p = &x;
    printf("*++p      => %d\n",*++p);
    x = 5; p = &x;
    printf("*(++p)    => %d\n",*(++p));
    return 0;
}

그것은 반환

(int) p   => 256688152
(int) p++ => 256688152
(int) ++p => 256688156
++*p      => 6
++(*p)    => 6
++*(p)    => 6
*p++      => 5
(*p)++    => 5
*(p)++    => 5
*++p      => 0
*(++p)    => 0

포인터 주소를 ints로 캐스트하여 쉽게 비교할 수 있습니다.

GCC로 컴파일했습니다.


1
연산 후 x와 p의 값을 포함하도록 변경합니다.
NetJohn

3

"포인터 주소와 포인터 값을 증가시키는 방법" 과 관련하여 나는 그것이 ++(*p++);실제로 잘 정의되어 있다고 생각하고 당신이 요구하는 것을 수행합니다.

#include <stdio.h>

int main() {
  int a = 100;
  int *p = &a;
  printf("%p\n",(void*)p);
  ++(*p++);
  printf("%p\n",(void*)p);
  printf("%d\n",a);
  return 0;
}

시퀀스 포인트 전에 동일한 것을 두 번 수정하지 않습니다. 나는 그것이 대부분의 용도에 대해 좋은 스타일이라고 생각하지 않습니다-그것은 내 취향에 비해 너무 비밀 스럽습니다.


실제로 괄호는 불필요합니다. ++*p++값과 포인터를 모두 성공적으로 증가시킵니다 (접미사 ++는 역 참조보다 강력하게 바인딩 되며 순서로 인해 *접두사 앞에 ++발생합니다). 괄호는 값을 증가시키기 전에 필요한 경우에만 필요합니다 (*p++)++. all-prefix로 이동하면 ++*++p괄호 없이도 잘 작동합니다 (하지만 포인터 증가 후에 가리키는 값을 증가시킵니다).
cmaster - 분석 재개 모니카

1
        Note:
        1) Both ++ and * have same precedence(priority), so the associativity comes into picture.
        2) in this case Associativity is from **Right-Left**

        important table to remember in case of pointers and arrays: 

        operators           precedence        associativity

    1)  () , []                1               left-right
    2)  *  , identifier        2               right-left
    3)  <data type>            3               ----------

        let me give an example, this might help;

        char **str;
        str = (char **)malloc(sizeof(char*)*2); // allocate mem for 2 char*
        str[0]=(char *)malloc(sizeof(char)*10); // allocate mem for 10 char
        str[1]=(char *)malloc(sizeof(char)*10); // allocate mem for 10 char

        strcpy(str[0],"abcd");  // assigning value
        strcpy(str[1],"efgh");  // assigning value

        while(*str)
        {
            cout<<*str<<endl;   // printing the string
            *str++;             // incrementing the address(pointer)
                                // check above about the prcedence and associativity
        }
        free(str[0]);
        free(str[1]);
        free(str);

연관성은 무엇입니까?
71GA

1
코드에서 * str ++를 ​​볼 수 있습니다. 이제 *와 ++ 모두 동일한 우선 순위 (평신도 용어에서 동일한 우선 순위)를 가지며 * str ++도 * (str ++) 또는 (* str) ++와 같은 괄호를 사용하여 구분되지 않습니다. 평가 방법이 필요합니다. 그래서 오른쪽에서 왼쪽은 (x = str ++) 그리고 (y = * x)
Abhishek DK
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.