포인터 표현식 : * ptr ++, * ++ ptr 및 ++ * ptr


128

최근에 나는 혼자서 이해할 수없는이 문제를 발견했다.

이 세 가지 표현은 정말로 무엇을 의미합니까?

*ptr++
*++ptr
++*ptr

나는 Ritchie를 시도했다. 그러나 불행히도 그가이 세 가지 작전에 대해 말한 것을 따를 수 없었습니다.

나는 그것들이 모두 포인터 / 가리키는 값을 증가시키기 위해 수행된다는 것을 알고 있습니다. 평가의 우선 순위와 순서에 대해 많은 것들이있을 수 있습니다. 포인터를 먼저 증가시킨 다음 해당 포인터의 내용을 가져오고, 단순히 내용을 가져온 다음 포인터 등을 증가시킵니다. 보시다시피 실제 작업 에 대한 명확한 이해가 없습니다. 가능한 한 빨리 정리하십시오. 하지만 프로그램에 적용 할 기회가 생기면 정말 길을 잃었습니다. 예를 들면 :

int main()
{
    const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
    return 0;
}

이 출력을 제공합니다.

ello

그러나 나의 기대는 그것이 인쇄 될 것이라는 것이었다 Hello. 마지막 요청 하나-주어진 코드 스 니펫에서 각 표현식이 작동하는 방식에 대한 예제를 제공하십시오. 대부분의 경우 이론의 단순한 단락 만이 내 머리 위로 날아갑니다.


6
: 당신은 네 번째 놓친 (*ptr)++(괄호에서 명확하게하는 데 필요한 *ptr++)
user4815162342을

15
인쇄하기 전에 포인터를 증가 시켰기 때문입니다. 당신은 while (* p) 및 printf ( "% c", * p ++);
dcaswell 2013 년

인터뷰를위한 좋은 질문입니다. 제한된 실제 사용. 나는 C는 그 포인터 :)하지 않았다 소원
Himanshu

5
@Himanshu 인터뷰 대상자의 국수를 굽는 경우 다음을 시도하십시오. 전역 포인터,, char* p고유 문자의 유효한 종료 문자열을 가리 킵니다. 그런 다음 함수가 fn(char ch)인쇄 것을 모두ch 매개 변수 현재 숯불에 의해 지적을 p. 이제 fn(*p++);Q : fn같은 문자를 두 번 인쇄 합니까 ? 얼마나 많은 교수 들이 그 질문을 잘못 이해 하는지 놀라실 것입니다.
WhozCraig

1
를 작성해야 리터럴 문자열에 P 점 이후const char* p = "Hello";
hetepeperfan

답변:


275

도움이 되었으면하는 자세한 설명이 있습니다. 가장 간단하게 설명 할 수있는 프로그램부터 시작하겠습니다.

int main()
{
    const char *p = "Hello";
    while(*p++)
        printf("%c",*p);
    return 0;
}

첫 번째 진술 :

const char* p = "Hello";

p대한 포인터로 선언 합니다 char. "pointer to a char"라고하면 무슨 뜻입니까? 의 값이 pa의 주소임을 의미합니다 char. p메모리에서 char.

문은 또한 p문자열 리터럴의 첫 번째 문자를 가리 키도록 초기화 됩니다 "Hello". 이 연습 p을 위해 전체 문자열이 아니라 첫 번째 문자 인을 가리키는 것으로 이해 하는 것이 중요합니다 'H'. 결국 , 전체 문자열이 아닌 p하나에 대한 포인터 char입니다. 의 값 p의 주소이다 'H'에서 "Hello".

그런 다음 루프를 설정합니다.

while (*p++)

루프 조건 *p++은 무엇을 의미합니까? (적어도 친숙 함이 시작될 때까지)이 혼란스러운 세 가지가 여기서 작동합니다.

  1. 두 연산자의 우선 순위, 접미사 ++및 간접*
  2. 접미사 증가 식의 값
  3. 접미사 증분 식의 부작용

1. 우선 순위 . 연산자에 대한 우선 순위 표를 간략히 살펴보면 후위 증분이 역 참조 / 간접 (15)보다 우선 순위 (16)가 더 높다는 것을 알 수 있습니다. 이것은 복잡한 표현식 *p++이 다음과 같이 그룹화 된다는 것을 의미합니다 *(p++).. 즉, *부품의 가치에 부품이 적용됩니다 p++. 그러니 p++먼저 참여 합시다 .

2. 후위 식 값 . 의 값은 증분 전의p++ 값입니다 . 당신이 가지고 있다면:p

int i = 7;
printf ("%d\n", i++);
printf ("%d\n", i);

출력은 다음과 같습니다.

7
8

증가하기 전에로 i++평가 i되기 때문 입니다. 마찬가지로은 p++의 현재 값으로 평가됩니다 p. 아시다시피의 현재 값 p은의 주소입니다 'H'.

이제의 p++일부 *p++가 평가되었습니다. 의 현재 값입니다 p. 그런 다음 *부품이 발생합니다. *(current value of p)의미 :가 보유한 주소의 값에 액세스합니다 p. 우리는 그 주소의 값이 'H'. 식 그래서 *p++평가 'H'.

이제 잠깐만 요. 로 *p++평가 되면 위 코드에서 'H''H'인쇄 되지 않습니까? 그것이 부작용 이 발생하는 곳 입니다.

3. 후위 표현 부작용 . 접미사 ++는 현재 피연산자 의 을 갖지만 해당 피연산자를 증가 시키는 부작용 이 있습니다. 어? 해당 int코드를 다시 살펴보십시오 .

int i = 7;
printf ("%d\n", i++);
printf ("%d\n", i);

앞서 언급했듯이 출력은 다음과 같습니다.

7
8

경우 i++제 평가되고 printf(), 그 평가 7 그러나 어떤 시점에서 제 전에 그 C 표준 보증 printf()실행 시작은 부작용++운영자가 일어난 것이다. 즉, 두 번째 printf()가 발생 하기 전에 첫 번째 i에서 ++연산자 의 결과로 증가 합니다 printf(). 그건 그렇고, 이것은 표준이 부작용의 타이밍에 대해 제공하는 몇 안되는 보장 중 하나입니다.

그러면 코드에서식 *p++이 평가 될 때 'H'. 그러나 당신이 이것에 도달 할 때까지 :

printf ("%c", *p)

성가신 부작용이 발생했습니다. p증가했습니다. 우와! 그것은 더 이상 포인트 'H'지만, 한 문자의 과거 'H'다음에 'e', 즉있다. 그것은 당신의 탄탄한 출력을 설명합니다.

ello

따라서 다른 답변에 유용한 (그리고 정확한) 제안의 합창이 있습니다. 받침 된 발음을 인쇄하고 "Hello"그것의 딱딱한 대응 물 을 인쇄 하려면 다음과 같은 것이 필요합니다.

while (*p)
    printf ("%c", *p++);

너무 많이. 나머지는 어떻습니까? 다음과 같은 의미에 대해 질문합니다.

*ptr++
*++ptr
++*ptr

방금 첫 번째에 대해 이야기 했으므로 두 번째에 대해 살펴 보겠습니다 *++ptr..

이전 설명에서 postfix 증분 p++에는 특정 우선 순위 , 부작용 이 있다는 것을 알았습니다 . 접두사 증분 ++p은 접미사 대응 와 동일한 부작용 이 있습니다. 피연산자를 1 씩 증분합니다. 그러나 우선 순위 이 다릅니다 .

접두사 증가는 접미사보다 우선 순위가 낮습니다. 즉, 역 참조 / 간접 연산자와 동일한 우선 순위를 갖습니다 *. 같은 표현에서

*++ptr

중요한 것은 우선 순위가 아닙니다. 두 연산자는 우선 순위가 동일합니다. 따라서 연관성이 시작됩니다. 접두사 증가와 간접 연산자는 오른쪽-왼쪽 연관성을 갖습니다. 이러한 연관성 때문에 피연산자 ptr는 가장 ++왼쪽에 있는 연산자 앞에 가장 오른쪽에있는 연산자와 함께 그룹화됩니다 *. 즉, 표현식이 그룹화됩니다 *(++ptr). 따라서 *ptr++다른 이유에서 와 마찬가지로 여기서도 *부품이 부품의 값에 적용됩니다 ++ptr.

그렇다면 그 가치는 무엇입니까? 접두사 증분 식의 값은 증분 이후의 피연산자 값입니다 . 이것은 접미사 증가 연산자와는 매우 다른 짐승입니다. 다음이 있다고 가정 해 보겠습니다.

int i = 7;
printf ("%d\n", ++i);
printf ("%d\n", i);

출력은 다음과 같습니다.

8
8

... 우리가 접미사 연산자로 본 것과는 다릅니다. 마찬가지로 다음이있는 경우 :

const char* p = "Hello";
printf ("%c ", *p);    // note space in format string
printf ("%c ", *++p);  // value of ++p is p after the increment
printf ("%c ", *p++);  // value of p++ is p before the increment
printf ("%c ", *p);    // value of p has been incremented as a side effect of p++

출력은 다음과 같습니다.

H e e l                // good dog

왜 그런지 아십니까?

이제 질문 한 세 번째 표현 인 ++*ptr. 실제로 가장 까다로운 것입니다. 두 연산자 모두 동일한 우선 순위와 오른쪽-왼쪽 연관성을 갖습니다. 이는 표현식이 그룹화됨을 의미합니다 ++(*ptr). ++부분의 값에 적용되는 *ptr부품.

그래서 우리가 가지고 있다면 :

char q[] = "Hello";
char* p = q;
printf ("%c", ++*p);

놀랍게도 이기적인 결과는 다음과 같습니다.

I

뭐?! 좋아요, *p부품은 'H'. 그런 다음 작동 ++이 시작 'H'되면 포인터가 아닌에 적용됩니다 ! 에 1을 더하면 어떻게됩니까 'H'? 1 더하기 ASCII 값 'H', 72를 얻습니다 . 73을 얻습니다.이를으로 나타내면 ASCII 값 73 : char을 얻습니다 .char'I'

질문에서 질문 한 세 가지 표현을 처리합니다. 질문에 대한 첫 번째 의견에서 언급 된 또 다른 내용은 다음과 같습니다.

(*ptr)++ 

그것도 흥미 롭다. 당신이 가지고 있다면:

char q[] = "Hello";
char* p = q;
printf ("%c", (*p)++);
printf ("%c\n", *p);

다음과 같은 열광적 인 결과를 얻을 수 있습니다.

HI

무슨 일이야? 다시 말하지만, 우선 순위 , 표현 값부작용 의 문제입니다 . 괄호로 인해 *p부품이 기본 표현식으로 처리됩니다. 기본 표현은 다른 모든 것보다 우선합니다. 먼저 평가를받습니다. 그리고 *p아시다시피는 'H'. 나머지 표현식 인 ++부분은 해당 값에 적용됩니다. 따라서이 경우 (*p)++'H'++.

의 가치는 'H'++무엇입니까? 만약 당신이라고 말했다면 'I', 당신은 (이미!) 우리의 가치 대 후위 증가에 대한 부작용에 대한 논의를 잊었습니다. 기억 'H'++평가 의 현재 값을 'H' . 그래야 첫째 printf()인쇄 할 것입니다 'H'. 그리고, 같은 부작용 , 즉 'H'로 증가 될 예정이다 'I'. 두 번째 printf()는 그것을 인쇄합니다 'I'. 그리고 당신은 즐거운 인사를합니다.

좋습니다.하지만 마지막 두 가지 경우에는 왜

char q[] = "Hello";
char* p = q;

왜 내가 뭔가를 가질 수 없습니까?

/*const*/ char* p = "Hello";
printf ("%c", ++*p);   // attempting to change string literal!

"Hello"문자열 리터럴 이기 때문 입니다. 시도 하면 문자열의를 ++*p로 변경 하여 전체 문자열을 만듭니다. C에서 문자열 리터럴은 읽기 전용입니다. 수정하려고하면 정의되지 않은 동작이 호출됩니다. 영어에서도 정의되지 않았지만 우연의 일치입니다.'H''I'"Iello""Iello"

반대로, 당신은 가질 수 없습니다

char p[] = "Hello";
printf ("%c", *++p);  // attempting to modify value of array identifier!

왜 안돼? 이 경우 p는 배열 이기 때문입니다 . 배열은 수정 가능한 l- 값이 아닙니다. p배열의 이름이 마치 상수 포인터 인 것처럼 작동하기 때문에 이전 또는 이후 증가 또는 감소 로 포인트 위치를 변경할 수 없습니다 . (실제로 그게 아니라보기에 편리한 방법 일뿐입니다.)

요약하면 다음과 같은 세 가지 질문에 대해 물어 보았습니다.

*ptr++   // effectively dereferences the pointer, then increments the pointer
*++ptr   // effectively increments the pointer, then dereferences the pointer
++*ptr   // effectively dereferences the pointer, then increments dereferenced value

그리고 나머지 세 개만큼 재미있는 네 번째 항목이 있습니다.

(*ptr)++ // effectively forces a dereference, then increments dereferenced value

첫 번째와 두 번째 ptr는 실제로 배열 식별자 인 경우 충돌합니다 . 세 번째와 네 번째는 ptr문자열 리터럴을 가리키는 경우 충돌합니다 .

거기에 있습니다. 이제 모든 것이 수정 이길 바랍니다. 당신은 훌륭한 청중이었고 저는 일주일 내내 여기있을 것입니다.


22
이 포럼에 오기 전에 내가 소유 한 3 권의 "C"도서를 검색했습니다. 나는 또한 몇 가지 주목할만한 온라인 자습서를 시도했습니다. 그러나 그들 중 어느 것도 당신의 설명에 가깝지 않습니다 (특히 당신이 그것을 모두 합친 방식). 당신은 내가 물어 본 질문에 답했을뿐만 아니라 풀뿌리 수준에서 더 많은 것을 논의했습니다. 사실 오늘은 제가 전에 부족했던 기본적인 것들을 많이 가르쳐 주셨습니다. 나는 내 대답을 토글하는 것 외에는 도울 수 없었다. :) 다시 한번 감사드립니다.
할당

26
+1 나는 이것이 내가 읽은 가장 긴 대답이라고 생각합니다. 모두가이 답변에서 많은 것을 배울 수 있다고 생각합니다.
Shafik Yaghmour 2013-08-29

9
당신 각하, C.에 대한 책 작성해야
딜론 버튼

1
좋은 질문에 대한 얼마나 아름다운 대답입니까! 잘 했어 @verbose!
benka 2013 년

7
당신의 이름에 살았던 .. :) 당신에게 선생님을 @verbose
sleeping_dragon

44

ptrarray의 i 번째 요소를 가리킨다 고 가정 arr합니다.

  1. *ptr++의 (i + 1) 번째 요소로 평가되고 이를 가리 키도록 arr[i]설정 ptr합니다 arr. 그것은 동일합니다 *(ptr++).

  2. *++ptrptr의 (i + 1) 번째 요소를 가리 키도록 설정 arr하고로 평가됩니다 arr[i+1]. 그것은 동일합니다 *(++ptr).

  3. ++*ptr1 씩 증가 arr[i]하고 증가 된 가치로 평가됩니다. 포인터 ptr는 그대로 유지됩니다. 그것은 동일합니다 ++(*ptr).

또한 하나 더 있지만 작성하려면 괄호가 필요합니다.

  1. (*ptr)++1 씩 증가 arr[i]하고 증가 하기 전에 그 값으로 평가됩니다. 포인터 ptr는 다시 그대로 유지됩니다.

나머지는 스스로 알아낼 수 있습니다. @Jaguar도 답변했습니다.


13

*ptr++ : post increment a pointer ptr

*++ptr : Pre Increment a pointer ptr

++*ptr : preincrement the value at ptr location

사전 증가 및 사후 증가 연산자에 대해 여기에서 읽으 십시오.


이것은 Hello출력으로 줄 것입니다.

int main()
{
    const char *p = "Hello";
    while(*p)
         printf("%c",*p++);//Increment the pointer here 
    return 0;
}

@ Nik-Lz 예, 출력은 다음과 같습니다Hello
Jainendra

7

루프의 상태가 나쁩니다.

while(*p++)
    printf("%c",*p);

와 같다

while(*p)
{
    p++;
    printf("%c",*p);
}

그리고 그것은 잘못된 것입니다.

while(*p)
{
    printf("%c",*p);
    p++;
} 

*ptr++과 동일합니다 *(ptr++).

const char  *ptr = "example";
char  value;

value = *ptr;
++ptr;
printf("%c", value); // will print 'e'

*++ptr과 동일합니다 *(++ptr).

const char  *ptr = "example";
char  value;

++ptr;
value = *ptr;
printf("%c", value); // will print 'x'

++*ptr과 동일합니다 ++(*ptr).

const char  *ptr = "example";
char  value;

value = *ptr;
++value;
printf("%c", value); // will print 'f' ('e' + 1)

나는 대답의 첫 부분에 절대적으로 동의 할 것입니다. 두 번째 부분에서 포인터를 정수로 초기화하는 것은 포인터 사용법을 이해하는 데 어려움을 겪는 사람에게 혼란 스럽습니다.
nickie

4

우선 순위에 관해서는 *은 접두사 증가보다 우선하지만 접미사 증가에는 우선하지 않습니다. 이러한 분류 방법은 다음과 같습니다.

*ptr++ -왼쪽에서 오른쪽으로 이동하여 포인터를 역 참조한 다음 포인터 값을 증가시킵니다 (접미사가 역 참조보다 우선하기 때문에 가리키는 값이 아님).

*++ptr -포인터를 증가시킨 다음 역 참조하십시오. 이것은 접두사와 역 참조가 동일한 우선 순위를 가지기 때문에 오른쪽에서 왼쪽 순서로 평가되기 때문입니다.

++*ptr-우선 순위 측면에서 위와 비슷합니다. 다시 오른쪽에서 왼쪽으로 이동하여 포인터를 역 참조한 다음 포인터가 가리키는 것을 증가시킵니다. 귀하의 경우 읽기 전용 변수 ( char* p = "Hello";) 를 수정하려고하기 때문에 정의되지 않은 동작이 발생 합니다.


3

다른 답변은 정확하지만 뭔가 빠진 것 같기 때문에 내 테이크를 추가 할 것입니다.

 v = *ptr++

방법

 temp = ptr;
 ptr  = ptr + 1
 v    = *temp;

어디로

 v = *++ptr

방법

 ptr = ptr + 1
 v   = *ptr

사후 증가 (및 사후 감소)가 의미한다는 것을 이해하는 것이 중요합니다.

 temp = ptr       // Temp created here!!!
 ptr  = ptr + 1   // or - 1 if decrement)
 v    = *temp     // Temp destroyed here!!!

왜 중요한가요? C에서는 그렇게 중요하지 않습니다. C ++에서는 ptr반복기와 같은 복잡한 유형일 수 있습니다. 예를 들면

 for (std::set<int>::iterator it = someSet.begin(); it != someSet.end(); it++)

이 경우 it복잡한 유형 it++이기 때문에 temp생성으로 인한 부작용이있을 수 있습니다 . 물론 당신은 컴파일러가 필요하지 않은 것 코드를 멀리 던져하려고합니다 운이 있지만, 반복자의 생성 자나 소멸자 후 아무것도 할 경우 경우 it++가 만들 때 그 효과를 보여줄 것입니다 temp.

내가 말하려는 것의 부족은 Write What You Mean 입니다. 당신은 평균 경우 증가 PTR 다음 쓰기 ++ptr없습니다 ptr++. 당신이 의미 temp = ptr, ptr += 1, temp한다면ptr++


0
*ptr++    // 1

이것은 다음과 같습니다.

    tmp = *ptr;
    ptr++;

따라서가 가리키는 객체의 값 ptr이 검색된 다음 ptr증가합니다.

*++ptr    // 2

이것은 다음과 같습니다.

    ++ptr;
    tmp = *ptr;

따라서 포인터 ptr가 증가하고 ptr가 가리키는 객체를 읽습니다.

++*ptr    // 3

이것은 다음과 같습니다.

    ++(*ptr);

따라서가 가리키는 객체 ptr는 증가합니다. ptr그 자체는 변하지 않습니다.


0

접미사와 접두사는 역 참조보다 우선 순위가 높으므로

* ptr ++ 여기서 ptr 증가를 게시 한 다음 ptr의 새 값을 가리 킵니다.

* ++ ptr here Pre Increment fist then point of new value of ptr

++ * ptr 여기서 먼저 ptr 값을 가져와 해당 vlaue를 증가시킵니다.


1
이것은 올바르지 않습니다. 접미사는 더 높은 우선 순위를 갖지만 접두사는 역 참조와 동일한 우선 순위를 갖습니다.
verbose

0

포인터 표현식 : * ptr ++, * ++ ptr 및 ++ * ptr :

참고 : 포인터는 초기화되어야하며 유효한 주소가 있어야합니다. 왜냐하면 우리 프로그램 (a.out)과는 별도로 RAM에는 동시에 실행되는 프로그램이 훨씬 더 많기 때문입니다. 즉, OS를 위해 예약되지 않은 일부 메모리에 액세스하려고하면 세분화 오류가 발생합니다.

이것을 설명하기 전에 간단한 예를 고려해 보겠습니다.

#include<stdio.h>
int main()
{
        int num = 300;
        int *ptr;//uninitialized pointer.. must be initialized
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr = *ptr + 1;//*ptr means value/data on the address.. so here value gets incremented
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        /** observe here that "num" got changed but manually we didn't change, it got modified by pointer **/
        ptr = ptr + 1;//ptr means address.. so here address got incremented
        /**     char pointer gets incremented by 1 bytes
          Integer pointer gets incremented by 4 bytes
         **/
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

위 코드의 출력을 분석하고 위 코드의 출력을 얻었 으면합니다. 위 코드에서 한 가지 분명한 것은 포인터 이름 ( ptr )은 주소 에 대해 이야기 하고 있음을 의미 하고 * ptr 은 abbout / data에 대해 이야기하고 있음을 의미 합니다.

사례 1 : * ptr ++, * ++ ptr, * (ptr ++) 및 * (++ ptr) :

위에서 언급 한 4 가지 구문은 모두 비슷 address gets incremented하지만 주소가 증가하는 방식은 다릅니다.

참고 : 모든 표현식을 해결하려면 표현식에 몇 개의 연산자가 있는지 확인한 다음 연산자의 우선 순위 를 찾으십시오 . 우선 순위가 동일한 여러 연산자 가 오른쪽 (R)에서 왼쪽 (L)으로, 왼쪽에서 오른쪽으로 (L) 수있는 진화 순서 또는 연관성 을 확인 합니다.

* ptr ++ : 여기서 두 개의 연산자가 있습니다. 즉 de-reference (*)와 ++ (increment)입니다. 둘 다 동일한 우선 순위를 가지고 R에서 L 로의 연관성을 확인합니다. 따라서 연산자가 먼저 오는 경우 오른쪽에서 왼쪽으로 해결을 시작합니다.

* ptr ++ : R에서 L로 해석하는 동안 처음 ++이 왔으므로 주소는 증가하지만 포스트 증가는 증가합니다.

* ++ ptr : 여기서 첫 번째 주소와 동일하게 주소가 증가하지만 사전 증가입니다.

* (ptr ++) : 여기에 3 개의 연산자가 있는데, 그 중 우선 순위가 가장 높은 그룹 ()을 가지고 있으므로 먼저 ptr ++에서 해결 된 주소가 증가하지만 게시됩니다.

* (++ ptr) : 위와 같은 경우에도 주소가 증가하지만 사전 증가합니다.

사례 2 : ++ * ptr, ++ (* ptr), (* ptr) ++ :

위에서 언급 한 모든 4 가지 구문은 비슷합니다. 모든 값 / 데이터가 증가 하지만 값이 변경되는 방식은 다릅니다.

++ * ptr : first *는 R에서 L로 해석하는 동안 왔으므로 값은 변경되지만 사전 증분입니다.

++ (* ptr) : 위의 경우와 동일하게 값이 수정됩니다.

(* ptr) ++ : 여기에 3 개의 연산자가 있는데, 그 중 우선 순위가 가장 높은 그룹 (), 내부 () * ptr이 있으므로 첫 번째 * ptr이 해결됩니다. 즉, 값이 증가하지만 게시됩니다.

참고 : ++ * ptr 및 * ptr = * ptr + 1은 모두 동일하며 두 경우 모두 값이 변경됩니다. ++ * ptr : 1 개의 명령어 (INC) 만 사용되며, 직접 값은 단일 샷으로 변경됩니다. * ptr = * ptr + 1 : 여기서 첫 번째 값이 증가 (INC)되고 할당 (MOV)됩니다.

위의 모든 포인터 증가 구문을 이해하려면 간단한 코드를 고려하십시오.

#include<stdio.h>
int main()
{
        int num = 300;
        int *ptr;
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//address changed(post increment), value remains un-changed
//      *++ptr;//address changed(post increment), value remains un-changed
//      *(ptr)++;//address changed(post increment), value remains un-changed
//      *(++ptr);//address changed(post increment), value remains un-changed

//      ++*ptr;//value changed(pre increment), address remains un-changed
//      (*ptr)++;//value changed(pre increment), address remains un-changed
//      ++(*ptr);//value changed(post increment), address remains un-changed

        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

위의 코드에서 주석을 주석 / 주석 해제하고 출력을 분석하십시오.

포인터를 상수로 : 포인터를 상수로 만들 수있는 방법이 없습니다. 여기서 언급하는 것은 거의 없습니다.

1) const int * p OR int const * p : 여기 value상수가 있고, 주소가 일정하지 않습니다. 즉, p가 가리키는 곳? 어떤 주소? 그 주소에서 가치는 무엇입니까? 어떤 가치가 맞습니까? 그 값은 일정하며 그 값을 수정할 수 없지만 포인터가 가리키는 곳은 어디입니까? 주소가 맞죠? 다른 주소도 가리킬 수 있습니다.

이것을 이해하려면 아래 코드를 고려하십시오.

#include<stdio.h>
int main()
{
        int num = 300;
        const int *ptr;//constant value, address is modifible
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//
//      *++ptr;//possible bcz you are trying to change address which is possible
//      *(ptr)++;//possible
//      *(++ptr);//possible

//      ++*ptr;//not possible bcz you trying to change value which is not allowed
//      (*ptr)++;//not possible
//      ++(*ptr);//not possible

        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

위 코드의 출력을 분석해보십시오.

2) int const * p : ' **constant pointe**r'ie 라고 address is constant but value is not constant합니다. 여기서 주소는 변경할 수 없지만 값은 수정할 수 있습니다.

참고 : 상수 포인터 (위의 경우)는 스스로 선언하면서 초기화해야합니다.

이것을 이해하기 위해 간단한 코드를 확인하십시오.

#include<stdio.h>
int main()
{
        int x = 300;
        int* const p;
        p = &x;
        printf("x = %d p =%p and *p = %d\n",num,p,*p);
}

위 코드에서 ++ * p 또는 * p ++가없는 것을 발견하면 주소 나 값을 변경하지 않고 오류가 발생하므로 간단한 경우라고 생각할 수 있습니다. 왜 ? 댓글에서 언급 한 이유.

#include<stdio.h>
int main()
{
        int x = 300;
        /** constant pointer must initialize while decaring itself **/
        int* const p;//constant pointer i.e its pointing to some address(here its pointing to garbage), it should point to same address(i.e garbage ad
dress only 
        p = &x;// but here what we are doing ? we are changing address. we are making p to point to address of x instead of garbage address.
        printf("x = %d p =%p and *p = %d\n",num,p,*p);
}

그래서이 문제의 해결책은 무엇입니까?

     int* const p = &x;

이 경우에 대한 자세한 내용은 아래 예제를 고려하십시오.

#include<stdio.h>
int main()
{
        int num = 300;
        int *const ptr = &num;//constant value, address is modifible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//not possible
//      *++ptr;//not possible bcz you are trying to change address which is not possible
//      *(ptr)++;//not possible
//      *(++ptr);//not possible

//      ++*ptr;// possible bcz you trying to change value which is allowed
//      (*ptr)++;// possible
//      ++(*ptr);// possible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

3) const int * const p : 여기서 주소와 값은 모두 상수 입니다.

이것을 이해하려면 아래 코드를 확인하십시오.

#include<stdio.h>
int main()
{
        int num = 300;
        const int* const ptr = &num;//constant value,constant address 
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//not possible
        ++*ptr;//not possible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

-1
const char *p = "Hello";   

*p means "Hello"
          ^
          | 
          p

*p++ means "Hello"
             ^
             | 
             p

*++p means "Hello"
            ^
            |     (WHILE THE STATEMENT IS EXECUTED)
            p

*++p means "Hello"
             ^
             |     (AFTER THE STATEMENT IS EXECUTED)
             p

++*p수단은 당신의 ASCII 값 증가하려고하는 것을*p

   is "Hello"
       ^
       | 
       p

값을 늘릴 수 없습니다. 상수이기 때문에 오류가 발생합니다.

while 루프의 경우 루프는 (NULL) 문자 *p++가있는 문자열의 끝에 도달 할 때까지 실행됩니다 '\0'.

이제 *p++첫 번째 문자를 건너 뛰기 때문에 두 번째 문자에서 시작하는 출력 만 얻을 수 있습니다.

다음 코드는 while 루프가 '\0'

const char *p = "Hello";
    while('\0') 
         printf("%c",*p);

다음 코드는 다음 코드, 즉 ello와 동일한 출력을 제공합니다.

const char *p = "Hello";
    while(*++p)
         printf("%c",*p);

...................................

const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.