C언어 이론 정리 - 03

Lee Pil Ung·2021년 12월 5일
0

C

목록 보기
3/6
post-thumbnail

📖 C언어 이론 정리 - 03

C언어 이론 정리 파트 03
자료 참조 : TCP School.com

- 연산자(operator)

연산자(operator)란 프로그램의 산술식이나 연산식을 표현하고 처리하기 위해 제공되는 다양한 기호를 의미한다.

C언어에서는 여러 종류의 연산을 위해 다양한 연산자를 제공하고 있다.

산술 연산자(arithmetic operator)

산술 연산자는 사칙연산을 다루는 기본적이면서도 가장 많이 사용되는 연산자다.

산술 연산자는 모두 두 개의 피연산자를 가지는 이항 연산자이며, 피연산자들의 결합 방향은 왼쪽에서 오른쪽이다.

  • 🚩 항이란 해당 연산의 실행이 가능하기 위해 필요한 값이나 변수를 의미한다. 따라서 이항 연산자란 해당 연산의 실행을 위해서 두 개의 값이나 변수가 필요한 연산자를 의미한다.

🏷 산술 연산자 표

산술 연산자설명
+왼쪽의 피연산자에 오른쪽의 피연산자를 더함
-왼쪽의 피연산자에서 오른쪽의 피연산자를 뺌
*왼쪽의 피연산자에 오른쪽의 피연산자를 곱함
/왼쪽의 피연산자를 오른쪽의 피연산자로 나눔
%왼쪽의 피연산자를 오른쪽의 피연산자로 나눈 후, 그 나머지를 반환함

📝 예제

int num01 = 10;
int num02 = 4;

printf("+ 연산자에 의한 결괏값은 %d입니다.\n", num01 + num02); // + 연산자에 의한 결괏값은 14입니다.
printf("- 연산자에 의한 결괏값은 %d입니다.\n", num01 - num02); // - 연산자에 의한 결괏값은 6입니다.
printf("* 연산자에 의한 결괏값은 %d입니다.\n", num01 * num02); // * 연산자에 의한 결괏값은 40입니다.
printf("/ 연산자에 의한 결괏값은 %d입니다.\n", num01 / num02); // / 연산자에 의한 결괏값은 2입니다.
printf("% 연산자에 의한 결괏값은 %d입니다.\n", num01 % num02); // % 연산자에 의한 결괏값은 2입니다.

연산자의 우선순위(operator precedence)와 결합 방향(associativity)

연산자의 우선순위는 수식 내에 여러 연산자가 함께 등장할 때, 어느 연산자가 먼저 처리될 것인가를 결정한다.

다음 그림은 가장 높은 우선순위를 가지고 있는 괄호() 연산자를 사용하여 연산자의 처리 순서를 변경하는 것을 보여준다.

대입 연산자(assignment operator)

대입 연산자는 변수에 값을 대입할 때 사용하는 이항 연산자이며, 피연산자들의 결합 방향은 오른쪽에서 왼쪽이다.

또한, 앞서 살펴본 산술 연산자와 결합한 다양한 복합 대입 연산자가 존재하다.

대입 연산자설명
=왼쪽의 피연산자에 오른쪽의 피연산자를 대입함
+=왼쪽의 피연산자에 오른쪽의 피연산자를 더한 후, 그 결괏값을 왼쪽의 피연산자에 대입함
-=왼쪽의 피연산자에서 오른쪽의 피연산자를 뺀 후, 그 결괏값을 왼쪽의 피연산자에 대입함
*=왼쪽의 피연산자에 오른쪽의 피연산자를 곱한 후, 그 결괏값을 왼쪽의 피연산자에 대입함
/=왼쪽의 피연산자를 오른쪽의 피연산자로 나눈 후, 그 결괏값을 왼쪽의 피연산자에 대입함
%=왼쪽의 피연산자를 오른쪽의 피연산자로 나눈 후, 그 나머지를 왼쪽의 피연산자에 대입함

📝 예제

int num01 = 7;
int num02 = 7;
int num03 = 7;

num01 = num01 - 5;
num02 -= 5;
num03 =- 5;

printf("- 연산자에 의한 결괏값은 %d입니다.\n", num01);  // -  연산자에 의한 결괏값은 2입니다.
printf("-= 연산자에 의한 결괏값은 %d입니다.\n", num02); // -= 연산자에 의한 결괏값은 2입니다.
printf("=- 연산자에 의한 결괏값은 %d입니다.\n", num03); // =- 연산자에 의한 결괏값은 -5입니다.
  • 🚩 위의 예제에서 num03 =- 5 연산은 단순히 -5를 변수 num03에 대입(=)하는 연산이 되었다.
    이처럼 복합 대입 연산자에서 연산자의 순서는 매우 중요하므로 주의를 기울여야 한다.

증감 연산자(increment and decrement operator)

증감 연산자는 피연산자를 1씩 증가 혹은 1씩 감소시킬 때 사용하는 연산자이다.

이 연산자는 피연산자가 단 하나뿐인 단항 연산자다.

증감 연산자는 해당 연산자가 피연산자의 어느 쪽에 위치하는가에 따라 연산의 순서 및 결과가 달라진다.

🏷 증감 연산자 표

증감 연산자설명
++x먼저 피연산자의 값을 1 증가시킨 후에 해당 연산을 진행함
x++먼저 해당 연산을 수행하고 나서, 피연산자의 값을 1 증가시킴
--x먼저 피연산자의 값을 1 감소시킨 후에 해당 연산을 진행함
x--먼저 해당 연산을 수행하고 나서, 피연산자의 값을 1 감소시킴

📝 예제

#include <stdio.h>

int main()
{
    int num01 = 7;
    int num02 = 7;
    int result01, result02;

    result01 = (++num01) - 5;
    result02 = (num02++) - 5;

    printf("전위 증가 연산자에 의한 결괏값은 %d이고, 변수의 값은 %d로 변했습니다.\n", result01, num01);
    // 전위 증가 연산자에 의한 결괏값은 3이고, 변수의 값은 8로 변했습니다.
    printf("후위 증가 연산자에 의한 결괏값은 %d이고, 변수의 값은 %d로 변했습니다.\n", result02, num02);
    // 후위 증가 연산자에 의한 결괏값은 2이고, 변수의 값은 8로 변했습니다.
}

위의 예제에서 첫 번째 연산은 변수 num01의 값을 먼저 1 증가시킨 후에 나머지 연산을 수행한다.

하지만 두 번째 연산에서는 먼저 모든 연산을 마친 후에 변수 num02의 값을 1 증가시킨다.

따라서 변수 num02의 증가는 관련된 연산에 아무런 영향도 미치지 않는다.

증감 연산자의 연산 순서

증감 연산자는 피연산자의 어느 쪽에 위치하는가에 따라 연산의 순서가 달라진다.

다음 예제는 증감 연산자의 연산 순서를 살펴보기 위한 예제이다.

📝 예제

#include <stdio.h>

int main()
{
    int x = 10;
    int y = x-- + 5 + --x;

    printf("변수 x의 값은 %d이고, 변수 y의 값은 %d입니다.\n", x, y);
    // 변수 x의 값은 8이고, 변수 y의 값은 23입니다.
}

연산 과정을 대충 살펴보면 꽤나 복잡하게 느껴진다.

허나 하나하나 뜯어서 보면 그렇게 복잡하지 않음을 알 수 있다.

  1. 우선 x--는 연산을 진행하고 연산자의 값을 빼기 때문에 10 + 5를 진행하고 x의 값을 1 뺴준다(x = 9)

  2. 그후에 오는 --x는 우선 연산자의 값(x = 9 - 1을 빼고 연산을 진행하기 때문에 10 + 5 + --x(x = 8)이 되서 23이 된다.

비교 연산자(comparison operator)

비교 연산자는 피연산자 사이의 상대적인 크기를 판단하는 연산자다.

비교 연산자는 왼쪽의 피연산자와 오른쪽의 피연산자를 비교하여, 어느 쪽이 더 큰지, 작은지, 또는 서로 같은지를 판단한다.

비교 연산자는 모두 두 개의 피연산자를 가지는 이항 연산자이며, 피연산자들의 결합 방향은 왼쪽에서 오른쪽(->)이다.

🏷 비교 연산자 표

비교 연산자설명
==왼쪽의 피연산자와 오른쪽의 피연산자가 같으면 1을 반환함
!=왼쪽의 피연산자와 오른쪽의 피연산자가 같지 않으면 1을 반환함
>왼쪽의 피연산자가 오른쪽의 피연산자보다 크면 1을 반환함
>=왼쪽의 피연산자가 오른쪽의 피연산자보다 크거나 같으면 1을 반환함
<왼쪽의 피연산자가 오른쪽의 피연산자보다 작으면 1을 반환함
<=왼쪽의 피연산자가 오른쪽의 피연산자보다 작거나 같으면 1을 반환함
  • 🚩 C언어에서 거짓(false)은 0이며, 0이 아닌 모든 것은 참(true)으로 인식된다. 즉 위의 표에서 1을 반환하는 것은 참(True)을 반환하는 것으로 봐도된다.

📝 예제

#include <stdio.h>

int main()
{
  int num01 = 3;
  int num02 = 7;

  printf("== 연산자에 의한 결괏값은 %d입니다.\n", num01 == num02); 
  // == 연산자에 의한 결괏값은 0입니다.

  printf("<= 연산자에 의한 결괏값은 %d입니다.\n", num01 <= num02);  
  // <= 연산자에 의한 결괏값은 1입니다.
}

논리 연산자(logical operator)

논리 연산자는 주어진 논리식을 판단하여, 참(true)거짓(false)을 결정하는 연산자이다.

AND 연산과 OR 연산은 두 개의 피연산자를 가지는 이항 연산자이며, 피연산자들의 결합 방향은 왼쪽에서 오른쪽이다.

NOT 연산자는 피연산자가 단 하나뿐인 단항 연산자이며, 피연산자의 결합 방향은 오른쪽에서 왼쪽이다.

🏷 논리 연산자(AND, OR, NOT) 표

논리 연산자설명
&&논리식이 모두 참이면 1을 반환함. (논리 AND 연산)
ll논리식 중에서 하나라도 참이면 1을 반환함. (논리 OR 연산)
!논리식의 결과가 참이면 0을, 거짓이면 1을 반환함. (논리 NOT 연산)

🏷 논리 연산자 진리표

ABA && BA ㅣㅣ B(OR)!A
1 (true)1 (true)1 (true)1 (true)0 (false)
1 (true)0 (false)0 (false)1 (true)0 (false)
0 (false)1 (true)0 (false)1 (true)1 (true)
0 (false)0 (false)0 (false)0 (false)1 (true)

📝 예제

#include <stdio.h>

int main()
{
    int num01 = 3;
    int num02 = -7;
    int result01, result02;

    result01 = (num01 > 0) && (num01 < 5);
    result02 = (num02 < 0) || (num02 > 10);

    printf("&& 연산자에 의한 결괏값은 %d입니다.\n", result01);
    // && 연산자에 의한 결괏값은 1입니다.
    printf("|| 연산자에 의한 결괏값은 %d입니다.\n", result02);
    // || 연산자에 의한 결괏값은 1입니다.
    printf(" ! 연산자에 의한 결괏값은 %d입니다.\n", !result02);
    //  ! 연산자에 의한 결괏값은 0입니다.
}

비트 연산자(bitwise operator)

비트 연산자는 비트(bit) 단위로 논리 연산을 할 때 사용하는 연산자이다.

또한, 비트 단위로 전체 비트를 왼쪽이나 오른쪽으로 이동시킬 때도 사용한다.

🏷비트 연산자 표

비트 연산자설명
&대응되는 비트가 모두 1이면 1을 반환함. (비트 AND 연산)
l대응되는 비트 중에서 하나라도 1이면 1을 반환함. (비트 OR 연산)
^대응되는 비트가 서로 다르면 1을 반환함. (비트 XOR 연산)
~비트를 1이면 0으로, 0이면 1로 반전시킴. (비트 NOT 연산)
<<지정한 수만큼 비트들을 전부 왼쪽으로 이동시킴. (left shift 연산)
>>부호를 유지하면서 지정한 수만큼 비트를 전부 오른쪽으로 이동시킴. (right shift 연산)

다음 그림은 비트 AND 연산자(&)의 동작을 나타낸다.

비트 AND 연산자는 대응되는 두 비트가 모두 1일 때만 1을 반환하며, 다른 경우는 모두 0을 반환한다.

다음 그림은 비트 OR 연산자(|)의 동작이다.

비트 OR 연산자는 대응되는 두 비트 중 하나라도 1이면 1을 반환하며, 두 비트가 모두 0일 때만 0을 반환한다.

다음 그림은 비트 XOR 연산자(^)의 동작을 나타낸다.

이처럼 비트 XOR 연산자는 대응되는 두 비트가 서로 다르면 1을 반환하고, 서로 같으면 0을 반환합니다.

다음 그림은 비트 NOT 연산자(~)의 동작을 나타낸다.

이처럼 비트 NOT 연산자는 해당 비트가 1이면 0을 반환하고, 0이면 1을 반환한다.

📝 예제

#include <stdio.h>

int main()
{
  int num01 = 15; int num02 = 8;  

  printf(" ~ 연산자에 의한 결괏값은 %d입니다.\n", ~num01);     // 1의 보수
  //  ~ 연산자에 의한 결괏값은 -16입니다.
  printf("<< 연산자에 의한 결괏값은 %d입니다.\n", num02 << 1); // 곱하기 2
  // << 연산자에 의한 결괏값은 16입니다.
  printf(">> 연산자에 의한 결괏값은 %d입니다.\n", num02 >> 1); // 나누기 2
  // >> 연산자에 의한 결괏값은 4입니다.
}

- 기타 연산자

삼항 연산자(ternary operator)

이 연산자는 C언어에서도 유일하게 피연산자를 세 개나 가지는 조건 연산자이다.

자바스크립트에서도 사용하는 연산자인데 C언어에서 파생된 듯 하다.

✅ 문법

  조건식 ? 반환값1 : 반환값2

물음표(?) 앞의 조건식에 따라 결괏값이 참(true)이면 반환값1을 반환하고, 결괏값이 거짓(false)이면 반환값2를 반환한다.

반환값에는 값뿐만 아니라 수식, 함수 호출 등 여러 가지 형태의 명령문이 올 수 있다.

📝 예제

int num01 = 15;
int num02 = 8;
int result;  

result = (num01 > num02) ? num01 : num02;
printf("둘 중에 더 큰수는 %d입니다.\n", result);  // 둘 중에 더 큰수는 15입니다.

삼항 연산자는 짧은 if / else 문 대신에 사용할 수 있으며, 코드를 간결하게 작성할 수 있도록 도와준다.

쉼표 연산자

쉼표(,) 연산자는 얼핏 연산자가 아닌 것처럼 보이지만 다양한 용도로 사용되는 연산자입니다.

이 연산자는 어떠한 연산을 수행하는 것이 아니라 다음과 같은 상황에서 사용됩니다.

  • 두 연산식을 하나의 연산식으로 나타내고자 할 때

  • 둘 이상의 인수를 함수로 전달하고자 할 때

📝 예제

int num01 = 15, num02 = 8;

printf("첫 번째 수는 %d이고, 두 번째 수는 %d입니다.\n", num01, num02);  // 첫 번째 수는 15이고, 두 번째 수는 8입니다.

위의 예제에서 쉼표 연산자는 둘 이상의 변수를 동시에 선언하기 위해서 사용되었다.

또한, printf() 함수에서는 둘 이상의 인수를 동시에 printf() 함수로 전달하기 위해서 사용되었다.

sizeof 연산자

사용자의 컴퓨터 환경에 따라 타입에 할당되는 메모리의 크기가 달라질 수 있다.

sizeof 연산자는 단항 연산자로 피연산자의 크기를 바이트 단위로 반환한다.

이 연산자는 피연산자로 타입뿐만 아니라 변수나 상수를 전달받을 수도 있다.

sizeof 연산자에 변수나 상수가 피연산자로 전달되면, 해당 변수나 상수에 해당하는 타입의 크기를 반환해 준다.

📝 예제

#include <stdio.h>

int main()
{
  int num01 = 15;
  int num02 = 8;

  printf(" num01의 크기는 %d입니다.\n", sizeof(num01)); 
  //  num01의 크기는 4입니다.
  printf(" num02의 크기는 %d입니다.\n", sizeof(num02)); 
  //  num01의 크기는 4입니다.
}

포인터 연산자

C언어에서 포인터와 연관되어 사용되는 연산자는 다음과 같다.

  1. 주소 연산자(&)

  2. 참조 연산자(*)

주소 연산자(&)는 변수의 이름 앞에 사용하여, 해당 변수의 주소값을 반환한다.

'&'기호앰퍼샌드(ampersand)라고 읽으며, 번지 연산자라고도 불린다.

참조 연산자(*)는 포인터의 이름이나 주소 앞에 사용하여, 포인터에 가리키는 주소에 저장된 값을 반환한다.

C언어에서 *기호는 사용하는 위치에 따라 다양한 용도로 사용된다.

이항 연산자로 사용하면 곱셈 연산으로 사용되며, 포인터의 선언 시나 메모리에 접근할 때도 사용된다.

profile
Frontend SoftWare Engineer(2022.06.27 ~)

0개의 댓글