C에서 * ptr + = 1과 * ptr ++의 차이점


122

방금 C를 공부하기 시작했고 포인터를 함수의 매개 변수로 포인터에 전달하는 예제를 수행 할 때 문제를 발견했습니다.

이것은 내 샘플 코드입니다.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int* allocateIntArray(int* ptr, int size){
    if (ptr != NULL){
        for (int i = 0; i < size; i++){
            ptr[i] = i;
        }
    }
    return ptr;
}

void increasePointer(int** ptr){
    if (ptr != NULL){
        *ptr += 1; /* <----------------------------- This is line 16 */
    }
}

int main()
{
    int* p1 = (int*)malloc(sizeof(int)* 10);
    allocateIntArray(p1, 10);

    for (int i = 0; i < 10; i++){
        printf("%d\n", p1[i]);
    }

    increasePointer(&p1);
    printf("%d\n", *p1);
    p1--;
    free(p1);
    fgets(string, sizeof(string), stdin);
    return 0;
}

16 행 *ptr+=1에서 *ptr++. 예상되는 결과는 전체 배열과 숫자 1이어야하지만 내가 사용할 *ptr++때 결과는 0입니다.

+=1과 사이에 차이 가 ++있습니까? 둘 다 똑같다고 생각했습니다.


2
지정된 코드는 선언하지 않았으므로 컴파일되지 않습니다 string.
Spikatrix

6
기타 참고 사항 : 1) 함수의 배열 인 allocateIntArray것처럼 보이기 때문에 잘못된 이름 malloc이지만 그렇지 않습니다. fillIntArray대신 제안 합니다. 2) 반환 값을 사용하지 않습니다 allocateIntArray. 반환 유형을로 변경하는 것이 좋습니다 void. 3) 안 if (ptr != NULL)기능의 increasePointerif (*ptr != NULL)? 4) 캐스트 인 malloc은 불필요합니다. 위의 Sourav의 의견을 참조하십시오. 5)이 : for (int i = 0; i < 10; i++){ printf("%d\n", p1[i]); }printf("%d\n", *p1); p1--;요구를 묶어야합니다 if(p1 != NULL). 6) string.h미사용입니다.
Spikatrix

9
p+=1같지 ++p않습니다.p++
Kos

5
이 질문은 4 년 전에 질문되었습니다. 포인터의 경우 ++이 + = 1과 같습니까
ren

3
@ren 거의,하지만 정답은 아닙니다. 연결된 질문은 여기서 OP 문제의 핵심 인 역 참조 연산자를 포함하지 않습니다.
Jason C

답변:


289

차이점은 연산자 우선 순위 때문입니다.

사후 증가 연산자 ++는 역 참조 연산자보다 우선 순위가 높습니다 *. 그래서 *ptr++동일합니다 *(ptr++). 즉, 포스트 증가는 포인터가 가리키는 것이 아니라 포인터를 수정합니다.

할당 연산자는 +=참조 연산자보다 낮은 우선 순위를 가지고 *있으므로, *ptr+=1동일하다 (*ptr)+=1. 즉, 할당 연산자는 포인터가 가리키는 값을 수정하고 포인터 자체는 변경하지 않습니다.


3
초보자, 니모닉은 유사도이다 *p++하고 *++p. 후자의 연산자 우선 순위는 분명하며 전자 중 하나가 다음과 같습니다.
Walter Tross

21

질문에 관련된 세 연산자의 우선 순위는 다음과 같습니다.

사후 증가 ++> 역 참조 *> 할당+=

주제에 대한 자세한 내용은 이 페이지 에서 확인할 수 있습니다 .

표현식을 구문 분석 할 때 일부 행에 나열된 연산자는 그 아래 행에 나열된 연산자보다 인수에 더 밀접하게 바인딩됩니다 (괄호로 묶인 것처럼). 예를 들어 표현식 *p++은로가 *(p++)아니라로 구문 분석 됩니다 (*p)++.

간단히 말해서, *ptr+=1post-increment 연산자를 사용 하여이 할당을 표현 하려면 역 참조 연산자에 괄호를 추가 ++하여이 작업보다 우선 순위를 부여해야합니다.(*ptr)++


3
흥미롭게도, 이것은 현재 솔루션을 포함하는 유일한 답변입니다 ... (* ptr) ++
hyde

7

작업 순서 를 표시하기 위해 괄호를 적용 해 보겠습니다.

a + b / c
a + (b/c)

다시 해보자

*ptr   += 1
(*ptr) += 1

그리고 다시

*ptr++
*(ptr++)
  • 에서는 *ptr += 1포인터가 가리키는 변수의 값을 증가시킵니다 .
  • 에서 *ptr++, 우리는 포인터를 증가 후에 이루어집니다 우리의 전체 문 (코드 행) 및 변수에 우리의 포인터에 대한 참조를 반환 포인트 에.

후자는 다음과 같은 작업을 수행 할 수 있습니다.

for(int i = 0; i < length; i++)
{
    // Copy value from *src and store it in *dest
    *dest++ = *src++;

    // Keep in mind that the above is equivalent to
    *(dest++) = *(src++);
}

이것은 src배열을 다른 dest배열 로 복사하는 데 사용되는 일반적인 방법 입니다.


"포인터가 가리키는 변수에 대한 참조를 반환합니다." C에는 참조가 없습니다.
Miles Rout

@MilesRout 아마도 그것을 lvalue라고 부르는 것이 더 정확할까요? 그러나 전문 용어를 추가하지 않고 어떻게 넣을지 모르겠습니다.
Mateen Ulhaq

3

아주 좋은 질문입니다.

K & R "C 프로그래밍 언어" "5.1 포인터 및 주소"에서 이에 대한 답을 얻을 수 있습니다.

"단항 연산자 * 및 &는 산술 연산자보다 더 밀접하게 결합합니다."

*ptr += 1      //Increment what ptr points to.

"* 및 ++와 같은 단항 연산자는 오른쪽에서 왼쪽으로 연결 됩니다."

*ptr++        //Increment prt instead of what ptr point to.

// * (ptr ++)처럼 작동합니다.

올바른 방법은 다음과 같습니다.

(*ptr)++      //This will work.

Stack Overflow에 대해 처음으로 언급 한 것입니다. 코드 형식을 업데이트했습니다. ^^ 제안 해 주셔서 감사합니다.
Nick.Sang

2

* ptr + = 1 : ptr이 가리키는 데이터를 증가시킵니다. * ptr ++ : 포인터가 가리키는 데이터 대신 다음 메모리 위치를 가리키는 포인터를 증가시킵니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.