C 이론(9)

Hi Beck·2023년 5월 3일

TIL-Language(C & C++)

목록 보기
11/34

제5장 수식과 연산자

1.수식(expression) : 숫자에 대한 계산식
상수(숫자), 변수(x/y/principal 등), 연산자(사칙연산에 사용되는 애들)의 조합
연산자와 피연산자(=연산을 당하는 애들, 연산자를 제외한 나머지)로 나누어진다.

2.연산자 종류
연산자도 결국은 함수 중 하나이다!

a.대입(=) : 오른쪽을 왼쪽에 대입

b.산술(+ - * / %) : 사칙연산과 나머지 연산

  • % 나머지 연산자 10 % 3;는 1

  • / 나누기 연산자 10 / 3 은 3(몫만 나옴)

    c.관계(> < == != >= <=) : 오른쪽과 왼쪽을 비교

    !=는 '다르다'라는 뜻

    ===은 자바스크립트에 나오는 연산자임(변수유형까지 고려하는 비교연산자인듯)

    두개의 피연산자를 비교하는 연산자
    결과값은 참(1) 아니면 거짓(0)

    이 둘을 저장할 수 있는 자료형이 bool(불리언), 얘가 1비트인데 숫자 0과1을 표현할 수 있긴있다. 즉 2개만 표현 가능하니깐 트루 펄스를 표현하는 것!

    d.부호 : +-
    보통은 단행연산자에서 쓰이는게 부호 연산자
    이행연산자에선 산술연산자가 쓰이는 것

    e.조건(?) : 조건에 따라 선택(다음에 자세히,밑에)

    f.콤마(,) : 피연산자들을 순차적으로 실행

    g.비트 단위 연산자( & | ^ ~ << >> ) : 비트별 AND, OR, XOR, 이동, 반전
    예시) 2의보수 같은 비트 관련된 것들 (이것도 나중에)

    h.sizeof 연산자 : 자료형이나 변수의 크기를 바이트 단위로 반환
    (이게 단순 함수보단 연산자에 가까움)

    i.형변환 (type) : 변수나 상수의 자료형을 변환(다음에)
    포인터 연산자 (* & []) : 주소계산, 포인터가 가리키는 곳의 내용 추출(다음에)
    구조체 연산자 (. ->) : 구조체의 멤버 참조(다음에)

    3.논리연산자

    논리(&& || !) : 참이냐 거짓이냐. 논리적인 AND, OR

    우리가 수학 집합의 교집합 밴다이어그램은 서로 다른 조건이 있다고하면 동시에 둘 다 만족하는 요소들을 나타낸다.그리고 합집합 벤다이어그램은 두 요소를 다 합친 전체 그 자체임.

    and는 양쪽을 다 만족했을 때를 말하는 것
    or은 양쪽 중 하나라도 만족했을 때를 말하는 것

    c언어는 불리언이라는 자료형이 존재하는데 얘 또한 메모리를 할당받아 변수를 선언할 수 있다. 얘는 초기화할 때, 상수가 아니라 true아니면 false로 초기화한다.

    true과 false는 참과거짓인데 아래는 참일까 거짓일까

    bool istrue = true; //false;

    int num1 = 3;
    int num2 = 5;

    num1 == num2;

    본 가정은 거짓이다.3과5는 명백히 다르기에 ==라고 쓴 것에 대해 컴퓨터가 같다고 말 하는게 아니라 컴퓨터도 명확하게 다르다고 판단하는 것임.num1 == num2; 는 num1이랑 num2가 같니?라는 수식임( 피연산자 : num1, 2 연산자 : ==)

    이때 이 수식의 결과를 변수에 넣어서 선언하는것도 가능하다!
    위에서 초기화를 true로 해서 현제 값은 true인데

    istrue = (num1 == num2);

    이렇게 선언을 하면 값은 false여서 변수 istrue에 들어가는 값은 false 거짓임
    (printf함수를 써주면 false라고 출력됨)

    ==이런 같니 이런 연산자가 논리연산자임 반대로 !=도 관계이자 논리연산자

    istrue = (num1 != num2);이거 였으면 이때는 값이 true

    istrue = (num1 <= num2); -> true

    istrue = (num1 >= num2); -> false

    ㄱ.&& 엔드연산자

    이런 연산자도 있다.num2가 num1보다 크면서 num1이 num2랑 같지 않니?
    istrue = (num1 < num2) && (num1 != num2);

    이런 경우에는 num끼리 크기 비교를 먼저함.-> 일단 앞 비교보면 num2가 더 크니깐 true이고, 뒷 비교는 다르니깐 참
    여기서 수식은 괄호를 기준으로 우선적으로 계산하는거 잊지말기!(수학처럼)

    istrue는 (true) && (true);가 되는 것임

    && AND연산자
    이 연산자는 요소가 다 true(참)일때만 true를 return해주는 애
    (왼도 참 오른쪽도 참이여야된단 소리로, 만약 어느 하나라도 거짓이면 그건 거짓으로 리턴됨)

    istrue = (num1 < num2) && (num1 = num2);
    이 경우는 istrue는 (true) && (false);가 되는 경우로 false가 됨.

    프로그램이 복잡해질수록 이런 조건과 연산자는 많아진다.&&는 수많은 조건을 참으로 판단해야지만 최종적으로 참으로 작동시킬 수 있음.

    논리연산자의 우선순위
    논리 연산자 계산식 중에 괄호가 안쳐져있는 식들도 많은데 보통은 논리연산자가 좀 나중이고 수식연산자가 좀 우선순위로 있다. (이런 연산자들마다 계산 우선순위가 있는데 많이 코딩하다보면 터득함)

    중요한건 코딩할 때 가독성을 위해 괄호를 쳐주자.

    &&와 || 연산자의 우선 순위는 모든 산술 연산자나 관계 연산자보다 낮다.
    &&가 || 연산자보다는 우선 순위가 높다(얘네는 맨나중에 한다)

    -> 결국 얘네들이 다른 연산자들보다 낮다는건데, 수학과 같음 곱하기나 나누기가 먼저면서 만약 괄호가 있다면 괄호부터 처리하는것처럼 하는 것임.

    논리연산자의이해하는데 도움되는 윤년 프로젝트 쳐보기
    개념적으로 아는거나 코딩을 짜는거는 다른 영역인데 그걸 판별할 수 있는 지표가 이거임

    논리연산자의 단축 계산
    && 연산자의 경우, 첫번째 피연산자가 거짓이면 다른 피연산자들을 계산하지 X

    ( 2 > 3 ) && ( ++x < 5 ) 예로 들어 이렇게 있을 때,
    둘다 참일때 참인데 순서가 앞에꺼 뒤에꺼하고 엔드엔드 연산을 그때 하는데
    만약 앞에게 false라면 뒤에것하는게 의미가 없으니 연산을 중지하고 false라고하는것
    (To효율성,컴퓨터는 일단 앞만 판단하고 넘어가는 것)

    이런걸 단축계산이라고 한다!

    || 연산자의 경우, 첫번째 피연산자가 참이면 다른 피연산자들을 계산하지 X
    ( 3 > 2 ) || ( --x < 5 )
    이것도 앞에게 참이면 참이기에 뒤에걸 굳이 할 필요없음
    예로들어 수식이 50개인데 하나만 참이면 될 것을 일일히 다 할 필요는 없으니깐

    단,++나 --는 실행이 안될 수도 있다

    ㄴ.|| OR연산자
    백스페이스 + 시프트로 입력 가능
    얘는 둘 중에 하나만 참이면 무조건 참으로 return한다.

    둘 다 참인것 역시 조건 충족으로 참임.그러면 거짓으로 나오는 경우는 딱 한가지임
    둘 다 거짓일때..!!

    ㄷ.!
    느낌표는 보통 반대일 때 씀
    x가 트루일 때, 앞에다가 !를 붙히면 펄스가 된다.
    x = false; !x = true;

    이걸 쓰는 이유 ?
    내가 건 조건의 반대의 결과가 나왔으면 좋겠다하는 목적을 위해 이런걸 만든 것

    C에서는 0이 아닌 값은 참으로 취급한다는 말이 나오는데 이건 고전 c언어에서
    0만 아니면 3이나 4도 참으로 취급한다는 소리임.

4.증감연산자

증감 : ++ -- 증가 감소 연산
++ (=증가시켜라)

예시
int num = 3;

num++;

printf("d%", num);

이걸 출력하면 4가 나온다. 즉 ++든 --든 무조건 1씩 증감시키는 것이다.
num = num + 1;과 같은 것!
넘에 1을 더한 것을 계속 대입해가는것

-- (=감소시켜라)는 2가 나옴

주의할 점
num++이 아닌 ++num도 있다.다를 것 같지만 기능상으로 동일한 애다.
단,순서가 다르다.이게 무슨말이냐하면 num++은 num을 먼저 사용한 다음에 ++해준다.
그리고 ++num은 ++을 해주고 num을 사용한다.

ㄱ. num++인 경우

int num = 3;

printf("%d", num++);

이렇게 했을 때 출력값은 3이 나온다.
4가 아니라 왜 3이냐면 num++는 내가 속한 이번 줄에선 변수만 사용하고 다음줄에서 ++을 사용할거야 라는 소리와 같음.그래서 위의 예시같은 경우는 num++을 선언해주고 프린트에프가 마지막에 한번뿐이니 4가 출력되는거고 지금 같은 경우는 4가 나오게 할려 면 다음줄에 printf("%d", num);까지 출력해야되는 것.
=++은 해당 변수 줄을 한번 찍은다음에 다음줄에서 ++시킨다.

int num = 3;

printf("%d", num++);
printf("%d", num); 이렇게 하면 34가 출력됨.

ㄴ. ++num인 경우
얘는 그럼 이번 줄에서 먼저 ++을 시켜주고 다음줄에서 변수만 사용하니깐 반대로 43으로 출력이되냐? 이건 먼저 해당 줄에서 증감을 시켜준 것이니깐 다음줄에서도 증감한 값이 그대로 유지됨 역순이 아니라 ++을 먼저 해준것 그니깐 출력문이 달라도 동일한 값이 나옴
(이미 증가된거면 증가된거지 다시 역으로 줄어지고그런건아님)

여기서 주의할게 ++num을 쓴다는 건
printf("%d", ++num);에서 여기서 num을 하나 더 한것을 찍어준다라는 의미가 아니라 num에다가 1을 먼저 더해주고 그걸 찍어서 프린트해줘라라는 의미와 같다.(결국은 단순히 값이 증가하는게 아닌 순서가 다른 것을 말한거임)

5.피연산자수에 따른 연산자 분류
a.단항 연산자: 피연산자의 수가 1개
++x; --y;
b.이항 연산자: 피연산자의 수가 2개
x + y x - y
c.삼항 연산자: 연산자의 수가 3개
x ? y : z

6.대입연산자
우리가 처음에 배운 대입 개념을 생각해서 우측 수식의 값을 좌측의 변수에 대입할 때 쓰는게 바로 '대입연산자'임

변수(variable) = 수식(expression); ( 수식이 거창한게 아니더라도 상수 및 변수자체만 들어갈 수도 있음)

대입연산자 주의할 점
a.왼쪽에는 항상 변수가 와야 한다.
x + 2 = 0; -> 왼편이 변수이름이 아니기 때문에 잘못된 수식!!
2 = x; -> 왼편이 변수이름이 아니기 때문에 잘못된 수식!!

b.다음의 문장은 수학적으로는 올바르지 않지만 C에서는 가능
x = x + 1; -> x의 값이 하나 증가 된다= 증가된 x의 값이 계속 대입됨.

7.복합 대입 연산자

복합 대입 연산자란 +=처럼 대입연산자=와 산술연산자를 합쳐 놓은 연산자

이걸 어떻게 쓰냐?
앞에 증감연산자 배울때 num = num + 1과 같단 소리를 했었는데 이것도 마찬가지다

'x += y'의 의미는 'x = x + y'인데,
'x = x + y'는 x와y를 더한 값을 x에 대입해준다라는 의미로 x의 값이 바뀐다는 의미다.
값들이 들어있었어도 결국은 x+y값으로 다시 덮어씌운다는 뜻.

이걸 왜 쓰냐? 소스를 간결한게 만들 수 있음
근데 개발자들이 이걸 조금이라도 편하게 쓸려고 복합대입연산자를 만든 것
프로그램을 만들다보면 수식과 연산자가 많아지는데 기존식이 혼동되어 햇갈릴때가 있다고한다.(내가 안써도 되긴함 각자의 스타일이 다르기에 근데 협업차 최소 읽을 순 있어야되는것)

어떤 종류들이 있나?
x += y x = x + y
x -= y x = x - y
x = y x = x y
x /= y x = x / y
x %= y x = x % y
z %= x + y; z = z % (x + y ) 등

8.형변환 (=자료형 변하는 것)

연산시에 데이터의 유형이 변환되는 것을 말한다.
우리가 저장할려는 자료의 형태에 따라서 그 값을 제대로 저장하기위해서 자료형을 지정해놓는다.근데 우리가 자료형을 정의해놨는데, 이 자료형이 자동 혹은 수동으로 변할 때가 있다.

형변환의 두 가지 유형
a.자동적인 형변환
대입연산시 자동 형변환
말그대로 대입을 하는 연산식에서 일어나는건데 '올림변환'과 '내림변환'이 존재함

올림변환(단어는 중요하지않고 이렇게 바뀔 수 있다를 알고있기)

double f;로 실수형 자료형으로 변수선언하고
f = 10+20;처럼 정수의 값을 넣었다했을 때 출력하면 30이 아니라 30.0으로 나옴
-> 이렇게 넣으면 컴퓨터가 자동으로 정수를 실수로 바꿔 f에 넣어준다.

내림변환

int i;
i = 3.14554566...;
얘는 반대로 정수형에 실수를 넣으면 얘는 소수점 아래의 숫자들을 다 버리고 정수만 남김
(상황에 따라 버리는게 값이 같으면 상관없는데 같지않으면 x)
얘는 그저 자기역할에 충실한 것 버리는데 있어서 손해보는건 우리

근데 이건 우리가 의도적으로도 쓸 수 있다.프로그램을 짜는데 분할해주는데 남아서 쓰기그런걸 과감히 버릴때 이걸 응용하면 되는 것

근데 원래 대부분은 이렇게 값이 짤리면 안됨

결론 : 자동정리형변환이 일어날 수 있으니 조심하자

정수연산시 형변환
정수연산시에도 자동 형변환이 일어나는데

char x = 10;
short y = 20;
z = x + y;
이때 z앞엔 int형이 있지만 생략되어있음.케릭터랑(1바이트) 쇼트(2바이트) 다 크기가 작은 애들인데 이 두 개를 더해서 int형 변수에다가 넣어주면 자동으로 int형으로 바뀌어서 들어간다. 즉 큰 자료형에 맞춰 들어간다는 뜻(2개 중 하나가 들어가는게 아니라 3개 중에 잴 큰 자료형에 들어간다고 생각하자!)

수식연산시 형변환(중요)
서로 다른 자료형이 혼합하여 사용되는 경우, 더 큰 자료형으로 통일된다.
예로 들어 정수랑 실수를 더하면 실수가 되는데, 이게 뭔 차이냐면 아까 변수에 넣었을때는 값이 일부 버림을 당했는데, 지금처럼 수식 내에서는 더 큰 자료형에 따라가는 것임

b.명시적인 형변환(=우리가 직접 명령을 하는것 즉 이게 수동적인 경우를 뜻하는것임)
형변환(type cast): 사용자가 데이터의 타입을 변경하는 것
ex) 나는 정수 5가 아니라 실수 5.0으로 쓰고싶어

그럼 아래와 같이 내가 나타내고싶은 자료형에 괄호를 쳐서 표기하고 우측에 괄호를 친 값을 나타내면 그 값은 원하는 자료형으로 나타난다.

(double)(5)
f = (double)i + (double)j;
f = (double)((int)y + 3);
f = (float)(x = 5); // 수식 x = 5의 결과값인 5가 float형으로 변

int i;
double f;

f = 5 / 4; // f는 1

-> 얘는 지금 나누기 연산자인데 결과값이 실수형이기에 1.0으로 나와야되지만 값이 여기에선 정수에서 정수로 나눠 1이 표기됨
f = (double)5 / 4; // f는 1.25

-> 더블로 5를 바꿔놓고 실수에서 정수를 나누면 얘는 1.25가 나온다.실수 나누기에선 몫만 나오지않는다.소수점까지 계산해서 나옴(5.0/4)
f = 5 / (double)4; // f는 1.25

-> 5가아닌 4를 4.0으로 바꿔서 나눠도 값은 같음
f = (double)5 / (double)4; // f는 1.25

-> 둘다 실수로 해도 값은 같다.

i = 1.3 + 1.8; // i는 3
계산 후 소수점 버림
i = (int)1.3 + (int)1.8; // i는 2
정수로 바꿔서 소수점 버린 것끼리 더함

  1. 조건 연산자 ?
    exp1 ? exp2 : exp3 라는 식이 있다. 이게 뭐냐면
    피연산자 3개가 있는데 exp1가 참이면 exp2가 답이고 exp1가 거짓이면 exp3이 답이다라는 식임(삼항연산자라고 한다)

예시
(5 > 2) ? 5 : 2
5가 2보다 크니라는 수식이 일단 있는것 -> 이것부터 파악 -> 참
그럼 5가 반환이 되는 것 아니면 2가 되는거고

팁: ?와 :을 찾고 수식이 참인지 거짓인지를 판별해라 그리고 참이면 콜론 앞 거짓이면 콜론 뒤

  1. 콤마연산자
    콤마로 연결된 수식은 순차적으로 계산된다.
    예시
    x=1, y=2;는 x=1; y=2;와 동일
    int 변수1,변수2,변수3 = 3;
profile
Emotional realizer

0개의 댓글