본문으로 바로가기

[C언어] 기본연산자 #3 (증감, 삼항)

category C 2014. 5. 2. 15:17

증감연산자

증감 연산자는 1씩 증가 혹은 1씩 감소시킨다.

1씩 증가 또는 1씩 감소 되는 경우가 굉장히 빈번하게 일어나기 때문에

a = a + 1; 보다는 ++a, a++ 가 더 간편하고 편리하다.

 

전위형(Prefix)

++a, --a

후위형(Postfix)

a++, a--

 

**a, //a. a**, a// 같은 연산자는 없다.

**는 앞으로 학습하게 될 이중포인터를 의미하며

// 은 한줄 주석처리하는 문장이다. 

 

1씩 증가 시키는 문장은 4가지 형태가 존재한다.

1. a = a + 1;

2. a += 1;

3. a++;

4. ++a;

 

1씩 감소 시키는 문장은 4가지 형태가 존재한다.

1. a = a -1;

2. a -= 1;

3. a--;

4. --a;

 

<질문>위의 4가지 형태 중 어떤 것이 실행 속도가 가장 빠를까?

 

  a++;
00411A35  cmp         byte ptr [ebp-0D1h],0 
00411A3C  jne         main+3Bh (411A4Bh) 
00411A3E  push        411ABDh 
00411A43  call        @ILT+550(__RTC_UninitUse) (41122Bh) 
00411A48  add         esp,4 
00411A4B  mov         eax,dword ptr [a] 
00411A4E  add         eax,1 
00411A51  mov         byte ptr [ebp-0D1h],1 
00411A58  mov         dword ptr [a],eax 
 a= a+ 1;
00411A5B  cmp         byte ptr [ebp-0D1h],0 
00411A62  jne         main+61h (411A71h) 
00411A64  push        411ABDh 
00411A69  call        @ILT+550(__RTC_UninitUse) (41122Bh) 
00411A6E  add         esp,4 
00411A71  mov         eax,dword ptr [a] 
00411A74  add         eax,1 
00411A77  mov         byte ptr [ebp-0D1h],1 
00411A7E  mov         dword ptr [a],eax 
 a+=1;
00411A81  cmp         byte ptr [ebp-0D1h],0 
00411A88  jne         main+87h (411A97h) 
00411A8A  push        411ABDh 
00411A8F  call        @ILT+550(__RTC_UninitUse) (41122Bh) 
00411A94  add         esp,4 
00411A97  mov         eax,dword ptr [a] 
00411A9A  add         eax,1 
00411A9D  mov         byte ptr [ebp-0D1h],1 
00411AA4  mov         dword ptr [a],eax  

 

 

<질문> 전위형과 후위형은 어떤 차이가 있을까?

#include <stdio.h>

void main()

{

    int a = 0;

    printf("a = %d\n", ++a); // 결과는 ? 1

    printf("a = %d\n", a++); // 결과는 ? 1

    printf("a = %d\n", ++a); // 결과는 ? 2+1 =3

    printf("a = %d\n", a++); // 결과는 ? 3

    printf("a = %d\n", ++a); // 결과는 ? 4 +1 = 5

}

 

<두 문장 비교>

    printf("a = %d\n", ++a);

    -> a 의 값을 1 증가 시킨 후 %d 에 대입한다.

    printf("a = %d\n", a++);

    -> a 의 값을 %d 에 대입 시킨 후 1 증가 시킨다. 

 

++a 는 먼저 증가하고, 값을 대입시키며,

a++ 는 먼저 값을 대입시키고, 나중에 증가한다.

 

--a, a-- 동일한 패턴으로 진행된다.

 

<컴파일 된 어셈블리로 분석>

void main()
{
 int a = 0;
 int b = 0;
 a = ++b;

 a = b++;


 a = b;
 b = b + 1;

 


}

 

 a = ++b;
00411A2C  mov         eax,dword ptr [b] 
00411A2F  add         eax,1
 
00411A32  mov         dword ptr [b],eax 
00411A35  mov         ecx,dword ptr [b] 
00411A38  mov         dword ptr [a],ecx 
 a = b++;
00411A3B  mov         eax,dword ptr [b] 
00411A3E  mov         dword ptr [a],eax 
00411A41  mov         ecx,dword ptr [b] 
00411A44  add         ecx,1 
00411A47  mov         dword ptr [b],ecx

 a = b;
00411A4A  mov         eax,dword ptr [b] 
00411A4D  mov         dword ptr [a],eax 
 b = b + 1;
00411A50  mov         eax,dword ptr [b] 
00411A53  add         eax,1 
00411A56  mov         dword ptr [b],eax
 
}

 

<유의사항>

특별한 상황이 아니라면 a++ 후치형 보다 ++a 부분을 쓰는 것이 훨씬 더 명확하다.

어셈블리 코드에서도 나와 있듯이

a = b++;

-------

a = b

b = b + 1;

두 코드는 글자 하나 틀리지 않고 똑같은 코드로 되어 있다.

따라서, a++ 는 초보자들에게는 위험 요소를 안고 있기 때문에 특별한 상황이 아니라면 ++a를 쓰는 것이 훨씬 더 좋다.

 

 

2씩이상 일때는 +, -, *, / 가 같은 형태로 적용 된다.

a += 2; // a = a + 2;

b -= 2; // b = b - 2;

c *= 2; // c = c * 2;

d /= 2; // d = d / 2;

 

<생각해 볼 점>

a++, a+=1 이러한 것이 있다는 것만 알고 있으면 충분하고 다른 사람 코드를 보았을때 이해만 가능하면 된다. a++, a+=1 은 a = a + 1 가 비교해서 어셈블리코드도 같을 뿐만 아니라 실행 속도도 같기 때문에 괜한 겉멋 들여서 a+=1 로 쓰지 않고 가장 가독성이 높은 a = a + 1 로 써주는 것도 현명한 방법이다. 단지 글자 몇자 더 적어 줄 뿐이다.

 

삼항연산자

if 문과 흡사한 형태이다.

<문법>

(조건식) ? 문장1:문장2

 

조건식이 참이면 문장1을 실행하고, 거짓이면 문장2를 실행한다.

 

예1)

#include <stdio.h>
void main()
{
  int a, b;
  scanf("%d%d", &a, &b);
  printf("Max(%d, %d):%d\n", a, b, (a > b) ? a:b);   
}

 

예2)

#include <stdio.h>
void main()
{
  int a, b;
  scanf("%d%d", &a, &b);
  printf("Max(%d, %d):", a, b);
  (a > b) ? printf("%d\n", a) : printf("%d\n", b);
}

 

예3)

#include <stdio.h>
void main()
{
 char szLastNum[8];
 printf("주민번호 끝자리(7글자)를 입력하세요\n");  
 scanf("%7s", szLastNum);
 printf("당신은 %s입니다.\n", ((szLastNum[0]-'0') % 2 == 1) ? "남자":"여자");
}