안녕하세요.
WooJi입니다.
첫 글을 쓴 후 오랜만에 글을 작성합니다.
공부하고 시험 보느라 바빴네요...
저번 글에서 C언어에서의 전위 연산자와 후위 연산자의 조건, 기능, 결과에 대해 알아보았습니다.
전위, 후위 연산자를 처음 사용하면 많이 헷갈립니다. 그래서 오늘은 전위, 후위 연산자를 사용할 때 에러가 발생하는 이유에 대해 알아볼까 합니다.
전위, 후위 연산자를 사용할 때 에러가 발생하는 경우에 대해 알아보기 전 복습을 해봅시다.
++연산자
조건: 수정 가능한 L-value (modifiable L-value) 즉, 피연산자가 수정이 가능한 공간이어야 한다는 것.
기능: 피연산자의 값을 1 증가
결과: 후위 연산자(a++)의 경우 피연산자의 값(a 값 그 자체) / 전위 연산자(++a)의 경우 증가된 피연산자의 값(a+1)
더 자세한 내용은 이전 글
<Noise 1-1> 전위(++a), 후위(a++) 연산자의 차이점에 대하여
안녕하세요. WooJi입니다. 오늘은 C언어에서의 전위 연산자와 후위 연산자에 대해 말해볼까 합니다. 우선 내용에 오류가 있을 수 있음에 양해 부탁드리며 오류를 발생하시면 댓글 등으로 알려주
aaaaaaaaaaayowooji.tistory.com
를 참고해주시기 바랍니다.
++연산자를 사용할 때 에러가 발생하는 경우는 일반적으로 L-value가 수정이 불가능하기 때문입니다.
다음은 전위, 후위 연산자 사용 시 에러가 발생하는 첫 번째 경우입니다.
#include <stdio.h>
int main()
{
int x = 1, y;
y = 2++;
z = (x+1)++;
x = ++x++;
printf("%d %d %d",x,y,z);
}
6 y = 2++;처럼 상수에 전위, 후위 연산자를 붙이게 되면 에러가 발생합니다.
수정 가능한 L-value가 아니기 때문입니다.
7 x+1 역시 상수(수정 불가능)이므로 후위 연산자의 조건에 부합하지 않아 에러가 발생합니다.
8 x = ++x++; 역시 에러가 발생합니다. 이유를 말씀드리기 전에 우선 알아야 할 것이 있는데요.
전위 연산자(++a)와 후위 연산자(a++) 중 후위 연산자의 우선순위가 높다는 것입니다.
그래서 생각을 해보면 ++(x++)과 같은 순서로 연산이 된다는 것인데 후위 연산을 먼저 하면 결과가 상수가 됩니다.
상수라는 것은 수정이 불가능한 값이기 때문에 전위 연산을 하기 위한 조건에 맞지 않아 에러가 발생하게 되는 것이죠.
다음 코드를 확인해주세요.
#include <stdio.h>
int main()
{
int a[3] = {1,2,3};
for (int i = 0; i < 3; i++)
{
printf("%d ",a[i]++);
}
printf("\n");
for (int i = 0; i < 3; i++)
{
printf("%d ",a[i]);
}
}
결과가 무엇일까요? 예측해보고 밑의 더보기를 눌러 확인하시기 바랍니다.
1 2 3
2 3 4
이렇게 출력되는 이유는 8번째 줄에서 a[i]++에 의해 결과는 a[i] 자체가 되므로 원소들의 값인 1 2 3이 차례대로 출력되는 것입니다. 이후 기능에 의해 각각 값이 1씩 증가하므로 다시 출력해보면 2 3 4가 되는 것이죠.
이렇게 일차원 배열에서 ++를 사용하는 것은 일차원 배열에서는 *연산을 한 번만 하면 곧장 공간으로 이어지기 때문에 문제 되는 경우가 드뭅니다.
그런데 문제는 이차원 배열을 사용할 때 발생합니다.
#include <stdio.h>
int main()
{
int b[2][3] = {{1,2,3},{4,5,6}};
printf("%p\n", b[1]++ );
printf("%p\n",(&b[1])++);
printf("%p\n",b++);
printf("%d\n",*(b+1));
}
다음 코드에서 에러가 발생하는 줄은 몇 번째일까요? 마찬가지로 생각해보시고 더보기를 눌러 확인해보시기 바랍니다.
6,7,8 줄 모두 에러가 발생합니다.
b[1], b는 모두 배열의 식별자입니다. 식별자는 애초에 변수가 아니기 때문에 수정이 불가능하죠. 따라서 전위, 후위 연산자를 사용할 수 없습니다.
&b[1]은 배열 자체의 포인터입니다. 전위, 후위 연산자의 기능 자체가 값을 1 증가시키는 것이다 보니 배열을 증가시킨다는 것은 말이 되지 않습니다. 다시 말해서, 배열은 연속된 메모리에 할당되어 값을 저장하는 것인데 할당되어 있는 메모리를 증감시킨다는 것이 성립하지 않는 겁니다.
반대로 9줄의 b자체는 첫 번째 원소의 포인터이므로 +1 연산을 하게 되면 4가 저장된 포인터 값이 되어 *연산을 거치면 4가 출력되는 것이죠.
배열에 관하여 헷갈리거나 위 설명이 잘 이해가지 않는다면 제 Tistory의 배열에 대해 설명한 글을 참고해주시기 바랍니다.
다음은 에러는 발생하지 않지만 많이 궁금해하는 유형입니다.
#include <stdio.h>
int main(){
int x = 1;
printf("%d %d \n", x++, ++x);
x = x++;
printf("%d\n",x);
x = ++x;
printf("%d\n",x);
}
다음과 같이 코딩하면 에러는 발생하지 않습니다. 실제로 실행해보면
2 3
3
4
와 같이 출력됩니다. (visual studio code에서는 말이죠)
이전 글([Noise 1: Coding/C Language] - 전위(++a), 후위(a++) 연산자의 차이점에 대하여)에서 전위, 후위 연산자가 값을 증감시키는 타이밍이 컴파일러에 따라 다르다고 했습니다.
5,7,10 줄과 같이 증감 연산자를 한 문장에 같은 변수에 대해 여러 번 사용하면 컴파일러마다 처리하는 시점이 다르기 때문에 사용하는 IDE에 따라 다른 결과가 나올 수 있습니다.
따라서 다음과 같이 코딩하는 것 자체가 좋지 않습니다.
오늘은 전위, 후위 연산자를 사용할 때 에러가 발생하는 이유에 대해 알아보았습니다.
저도 처음에 배울 때 많이 헷갈렸습니다. 생각 없이 코딩하고 실행하기보다 결과를 예측해보면서 코딩하면 좋겠습니다.
내용 중 오류를 발견하시면 댓글 등으로 꼭 알려주시기 바랍니다.
또 읽다가 모르는 점이 있으면 언제든 댓글 달아주세요.

다음 글에서 뵈어요~