혼자 연구하는 C/C++ 5장 정리(연산자)

2015. 2. 27. 14:40창고

728x90
728x90

1. 연산자의 종류

자료는 데이터화, 프로그래밍으로 정보(Information)로 만들 수 있다.

프로그램은 사람을 대신해 일을 하는 소프트웨어, 정보를 만드는 주된 수단이 바로 연산자이다.

 

 

2. 산술 연산자

가감승제의 가장 기본적이고 많이 쓰이는 연산자이다.

ex) 2*3 = 6

 

일반적인 수학의 연산자와 다른 것은 /연산자이다.

컴퓨터의 연산자의 특징상 피연산자의 자료형에 따라 결과가 달라진다.

ex)

3.0/2,.0 = 1.5

3/2 = 1


3.0과 2.0은 실수형이기 때문에 결과값이 실수형으로 나오지만

3/2는 정수형이기 때문에 1.5가 출력되지 않고 뒷자리는 버리고 1의 값이 나온다.

 

ex)

a+b;

a+-b; //a와 b의 음수값을 더한다.

a-b;

a--b; //a와 b의 음수값을 뺀다.


3. 대입 연산자

대입 연산자(Assignment)이란 변수에 어떤 값을 집어넣는 동작이며 대입 연산자는 변수의 값을 변경할 때 사용한다.


ex)

i = 2+3;

i = j+k*m;


좌변값(l - value)

대입연산자의 우변에는 상수, 변수와 연산자들로 구성된 계산할 수 있는 표현식이다.

좌변값은 대입 연산자의 왼쪽에 올 수 있는 값이라는 뜻이고 실제적으로 메모리를 점유하고 있는 실체.

ex) l-value 대입 실패

1 = 2+3;

a+b = 4;

1은 실제 메모리를 점유하고 있지 않으며 값이 고정되어 있어 바꿀 수 없다.

변수로 구성된 식도 좌변값이 될 수 없다.


char str[12];

str = "STRING";

str이 배열의 주소를 가지고 있다. *str은 좌변값이 될 수 있지만 str과 &str은 좌변값이 될 수 없다.


연산자의 리턴값

C의 모든 연산자는 연산 후 그 결과를 돌려주는데 이를 리턴값이라 부른다.

연산자도 일종의 함수이므로 연산 결과를 리턴한다.


a = 5;

b = 5;

c = 5;


a=b=c=5;

 

두 문장은 같은 표현.




복합 대입 연산자

대입 연산자와 다른 연산자가 결합된 연산자.

a = a_3;

a += 3;

같은 문장!


복합 대입 연산자는 언제 사용하나요?

변수를 두 번 활용할 필요가 없이 편리하게 사용할 수 있다.

VeryLongNameVariable = VeryLongNameVariable + 3;

VeryLongNameVariable += 3;


복합 연산자가 가능한 형태

+= -= *= /= %= <<= >>= &= |= ^=

복잡한 연산에는 사용하지 않는 것을 추천!


증감 연산자

피연산자를 1씩 증가시키거나 감소시키는 연산자를 말한다. 

루프의 제어 변수처럼 순서대로 어떤 작업을 할 때 사용하는 변수이다.


a = a+1;

a += 1;

a++; (후위 증감연산자)

다 같은 것들!


전위형(prefix) - 증감연산자가 피연산자 앞에 위치. 일단 값을 먼저 증감시킨 후 그 결과를 리턴.

후위형(postfix) - 증감연산자가 피연산자 뒤에 위치. 먼저 리턴을 하고 증감.


a++++, ++a++ 에러!


4. 복잡한 수식

a = a+1 (어셈블리로 ADD [a],1)

a++ (어셈블리로 INC[a])


a++가 성능이 좋다. 컴파일러는 a = a+1을 a++로 바꿔서 컴파일 한다. 똑똑한 컴파일러!


하지만! 이것을 너무 남발해서 쓰면 위험할 수 있다.


ex)

b = (++a+1)*a++;

b = a++ + ++a;


문법에는 문제가 없지만 어떤 의도로 작성한 코드인지 알 수 없다.

평가 방법은 컴파일러마다 달라 이식성에 문제가 생길 수 있다.

그러므로 이런 현란한 코드는 절대! 절대! 쓰지 말자.


5. 관계 연산자

피 연산자를 두개 취하는 이항 연산자!

좌변과 우변을 비교하여 같은지, 다른지, 다르다면 어느 쪽이 큰지를 조사한다.


== 와 != 는 같다와, 다르다의 의미로 상등 연산자(Equality Operator)로 분류된다.


관계 연산자는 수식을 평가하고 결과가 참이면 1(true)를 리턴하고 거짓이면 0(false)을 리턴한다.

C에서 숫자 0은 일반적으로 거짓, 0이 아닌 모든 값은 참.(일반적으로 1을 참이라고 표현)


조건문에서 유의사항

if( i = 7){ }


위 if문은 i가 7일때,(i == 7)을 조건으로 하기 위해 작성한 코드다.

하지만 i=7을 넣는 대입 연산이 되었고 대입된 결과인 7을 리턴한다.

그러므로 이 문장은 항상 참이 되어 뒤의 블락 문장을 항상 수행하게 된다.


if( 7 == i) { }


위의 문제를 예방할 수 있는 방법은 대입 연산자의 l-value가 될 수 있는 정수를 왼쪽에 두는 것!

살짝 어색하긴 하지만 실수를 미연에 방지할 수 있다는 측면에서 좋은 코딩 습관이라 할 수 있다.


6. 논리 연산자

두 개 이상의 조건식을 결합하여 하나의 진리값을 만들어 낸다.



ex)

1
2
3
4
if(a != 0)
{
    if(b/== 3) function();
}

cs


a가 0이 아니고 b/a가 3이 되면 값을 출력하란 뜻이다.

이를 쉽게 논리 연산자를 이용해 쉽게 표현하자면,


1
if(a != 0 || b/== 3) function();
cs

 

이렇게 표현할 수 있다.


7. 비트 연산자

논리 연산과 비슷하지만 비트를 연산 대상으로 삼는다는 점이 조금 다르다.


비트(bit)란? 기억 장치의 최소 단위로 1또는 0을 기억하며 8개의 비트가 모여서 1바이트가 된다.






int num = 1234;

라는 문장이 있다고 가정하면 메모리 공간 어딘가에 4바이트만큼 그림과 같이 저장된다.


비트 연산은 메모리 공간에 직접 접근할 수 있어 섬세한 처리를 하고자 할 때 사용해주어야 한다.

반전, 스크롤, 투명 처리 등이 가능했으며 일반적인 산술 연산보다 훨씬 더 속도가 빨랐다.




~ 연산자

0 1 0 1 1 0 0 1 = 0x59 (a)

1 0 1 0 0 1 1 0 = 0xa6 (~a)

1의 보수를 만들어 준다.


& 연산자

0 1 0 1 1 0 0 1 = 0x59 (a)

0 0 0 0 1 1 1 1 = 0x01 (b)

0 0 0 0 1 0 0 1 = 0x09 (a&b)

특정 비트를 강제로 0으로 만들어 버리는 연산. 마스크 오프(mask off)


| 연산자

0 1 0 1 1 0 0 1 = 0x59 (a)

0 0 0 0 1 1 1 1 = 0x01 (b)

0 1 0 1 1 1 1 1 = 0x51 (a|b)

특정 비트를 덮개를 씌워 강제로 1로 바꿔버리는 연산. 마스트 on(mask on)


한글의 저장 방법

영문 알파벳은 모두 128보다 작기 때문에 최상위 비트가 0이 되어 있어 한글과 구분된다.

비트연산으로 초성과 중성, 종성을 비트 연산으로 조작할 수 있다.


Han & 0x11        // 종성만 분리

Han & 0x7c00     // 초성만 분리

Han & 0xffe0 | 2 // 종성만 ㄱ으로 바꾼다.


^ 연산자

베타적 논리합이라 부르며 ~와 마찬가지로 비트를 반전시키는 기능을 한다.

~연산자와 차이점은 전체 비트를 반전시키지 않고 지정한 비트만 반전시킨다.

0 1 0 1 1 0 0 1 = 0x59 (a)

0 0 0 0 1 1 1 1 = 0x01 (b)

0 1 0 1 0 1 1 0 = 0x56 (a^b)

마스크 반전이라 부른다.


8. 쉬프트 연산자

쉬프트 연산자는 비트를 지정한 수만큼 좌우로 이동시키는 연산자다.

>> 연산자는 오른쪽, <<는 왼쪽으로 이동시킨다.

a << 3은 3비트 왼쪽으로 이동시킨다.


ex) a >> 1



ex) a << 1




쉬프트 연산의 활용

위에서 설명 했듯이 한글은 1, 5, 5, 5 바이트로 한글비트, 초성과 중성, 종성이 나눠져있다.

ex) 한글 "강"을 예시로 초성 ㄱ을 찾아내 비교하고 싶은 상황.



5비트로 잘라져 있기때문에 &연산으로 초성 5비트만 남기고 마스크 연산을 하면 된다.

1 0 0 0 1 0 0 0 0 1 1 1 0 1 1 1 = 0x8877

                       &

0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 = 0x7c00

                       =

0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 = 0x0800


붉은 부분이 ㄱ이다.


0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 = 0x0800

                     >> 10

0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 = 0x0002


이렇게 자리를 맞춰서 직접 값을 비교할 수 있다.

if(((a & 0x7c00) >> 10) == 2) {...}


쉬프트 연산과 곱셈

쉬프트 연산은 곱셈과 나눗셈의 대용으로 사용할 수 있다.

a << b == a * 2^b


3배 : a << 1 + a;

9배 : a << 3 + a;

15배 : a << 4 - a;

60배 : a << 6 - a << 2;


와.. 60배 진짜 천재적인 코드다. 예술코드.


9. 회전 연산

쉬프트 연산과 비슷한 비트 조작 명령이다.

비트 연산 - 선형, 회전 연산 - 원형


연산자 형태로는 제공되지 않으며 _rotl, _rotr 함수로 제공.

C수준에서는 사용할 일이 그리 많지 않다.






10. 기타 연산자

삼항 조건 연산자

(조건식) ? 값1 : 값2

? 앞에 조건식이 참이라면 값1, 거짓이라면 값2


쉼표 연산자

쉼표 기호(,)를 사용하는데 구두점같이 생겨 연산자가 아니라고 오해받기도 하지만 분명한 연산자!

j = (i = 3, i + 2);

좌변을 먼저 평가하므로 쉼표 연산자는 

우선 i = 3에 대입 > 3 + 2가 되어 j = 5가 된다.

j = (i=3)+2; 와 같은 문장.


sizeof 연산자

타입 또는 변수의 크기를 리턴해주는 연산자.

형식

sizeof(타입 또는 변수)

괄호 안이 메모리를 얼마나 차지하는지 알 수 있다.


배열의 요소 개수를 구하고 싶다면?

sizeof(array) / sizeof(array[0])


배열 전체 크기를 요소의 크기로 나누면 배열 요소의 개수가 됨!


캐스트 연산자

변수의 타입을 강제로 다른 타입으로 바꾸는 연산자.

(타입)변수

타입(변수)

전자는 C, 후자는 C++에서 추가된 캐스트 연산자 형식이다.


11. 연산 규칙

연산자 우선순위와 결합순서



결합순서?

수식 내에 같은 종류의 연산자가 있을 때 어떤 방향의 연산을 먼저 수행할 것인가를 결정.

ex) a = b = c = 3;

a,b,c 모두 3을 대입하는데 대입 연산자는 오른쪽이 우선!

그래서 c = 3 > b = c > a = b 순으로 실행된다.


산술 변환

C언어는 데이터 타입이 조금 다른 변수끼리라도 자동으로 변환하여 연산을 허용한다.



728x90
반응형