본문 바로가기

Programming

[C언어] C언어 기초강좌 5 / C언어 / 프로그래밍 기초 / 프로그램 만들기

이번 강좌는 C언어의 연산자에 대해서 알아보도록 하겠습니다.

1. 연산자 



이제부터는 좀 쉬운 것들을 배우도록 하죠 

어렵지는 않지만 매우 중요한 것이니 잘 들으시길 바랍니다. 

이제부터 배울껀 연산자 입니다. 

C언어는 키워드는 적어도 연산자 만큼은 그 그 어떤 언어보다도 많습니다. 

그것이 C언어가 강력한 이유중 하나이죠. C에서 연산자는 매우 중요하므로 잘 들으셔야 할 부분입니다. (1) 기본 수학 연산자 우선 간단히 기본 수학 연산자를 하겠습니다. C를 모르는 그 어떤 사람이라도 다 아는 것이니 머리 식힐겸 잘 읽어보세요. 기본 수학 연산에는 덧셈, 뺄셈, 곱셈, 나눗셈이 있습니다. 이에 따른 연산자는 다음과 같습니다. ------------- + 덧셈 - 뺄셈 * 곱셈 / 나눗셈 % 나머지 ------------- 나머지 구하는 연산자 빼면 누구나 다 아는 것이죠? 특별히 설명할것두 없겠네요. c=a+b; 이렇게 하면 c에 a와 b를 더해 넣는 것이고 c=a-b; 이렇게 하면 c에 a에서 b를 빼 넣는 것이고 더 이상의 설명은 필요 없겠죠? %는 사용법은 똑같으나 단지 나머지를 구하는 것 입니다. (2) 단한 연산자 다음에는 단항 연산자를 알아보죠. 단항 연산자에는 +와 -가 있습니다. 단항 연산자는 변수나 상수앞에 붙여서 부호 표시를 하거나 부호를 바꿀때 쓰입니다. 예를 들어 a=-b; 이렇게 하면 a에는 b의 부호를 바꾼 값이 들어가겠죠? 만약 b가 -10이라면 a에는 10이 b가 10이라면 a에는 -10이 들어갑니다. 단항연산자중 +는 생략하면 기본으로 지정되므로 거의 쓰이지는 않습니다. (3) 우선 순위 다음으로 연산자 우선순위를에 대해 알아보죠. 모든 연산자가 우선순위가 있다는 것은 알고 계시겠죠? 수학에서도 곱셈을 덧셈보다 먼저 하자나요. 그것은 곱셈의 우선순의가 높기 때문이죠. 아직 연산자를 많이 배우지는 않았지만 기본 수학 연산자의 우선순위를 알아보죠. 우선순위는 *, /, % 이 가장 높고 그 다음이 +, -입니다. 그리고 같은 순위에서는 왼쪽부터 계산이 됨니다. 또한 수식에 괄호가 있다면 괄호 안에 식을 먼져 계산하게 됨니다. (4) 치환 연산자 우선 치환 연산자 입니다. 치환 연산자는 지금까지 계속 써 왔던 것 입니다. 치환 연산자는 바로 = 입니다. 이 연산자의 쓰임세는 아주 간단하죠? 모두들 알고계실 겁니다. 예를 들어 a=b; 이런 문장이 있다면 a에 b의 값을 넣으라는 것이 되겠죠? 이렇게 아주 간단합니다. 이렇게 지금까지 쓰던 문장을 단일 치환문 이라고 합니다. 그런데 C에서는 이런 단일 치환문 외에도 다중 치환문이 있습니다. 이것에 대해서도 자세히 알아보죠. 다중 치환문도 그리 어렵지 않은 것 입니다. 이 문장을 보세요. a=b=c=d=e=f=1; 이렇게 한 문자에 치환 연산자가 2개 이상 쓰인 것을 다중 치환문 이라고 합니다. 이 문장의 결과는 어떻게 될까요? a,b,c,d,e,f모두에 1이 들어가겠죠? 치환 연산자는 +,-,*,/등의 연산자와는 다르게 오른쪽에서 왼쪽으로 연산을 수행합니다. 예를 들어.. e=a+b+c+d; 이건 a와 b를 더하고 그 값에 c를 더하는 식으로 왼쪽에서 오른쪽으로 연산을 수행하지만 a=b=c=d=e=f=1; 이건 f에 1을 넣고 e에 f의 값 즉 1을 넣고 하는 식으로 오른쪽에서 왼쪽으로 연산을 수행합니다. 위에 있는 다중 치한문 까지는 쉽게 이해가 되셨을 겁니다. 그럼 다음을 보세요. a=10+(c=12-2); 이해가 빨리 되시나요? 어떻게 보면 잘못된 문장 같기도 하지만 이건 에러 없는 정확한 수식 입니다. 그럼 그 문장을 조금 바꿔 두 문장으로 해 보죠. c=12-1; a=10+c; 이제 이해가 되시나요??? 위의 수식을 줄여 쓴 것이 a=10+(c=12-2); 이거 입니다.. C에서는 이렇게 희귀한 수식도 인정합니다. 이제 예제 하나 볼까요?? /* 파일 이름 : C5-2.C 프로그램 내용 : 다중 치환문 예제 */ #include void main() { int a,b,c,d,e,f; a=b=c=d=e=f=0; b=10; c=20; a=b+(d=c); printf("%d %d %d %d %d %d\n",a,b,c,d,e,f); } 정말 간단한 소스죠. 조금 햇갈리실 것 이지만 잘 분석하면 결과는.. C:\>C5-2.EXE 30 10 20 20 0 0 C:\> 이렇게 나옴니다. (5) 타입 캐스팅 이제 치환 연산자도 다 끝났습니다. 그런데 배울것이 하나 더 있는데 그걸 배우기 전에 다음과 같은 경우를 생각해 봅시다. 만약 int형과 unsigned long형태를 같이 계산하면 어떻게 될까요? 자료형의 형태가 다르니 잘못하면 잘못된 결과가 나올수도 있습니다. 이럴때는 데이터 형태을 일시적으로 변경시켜 주면 되는데 이렇게 일시적으로 데이터 형태를 바꿔주는 것을 타입캐스팅(Typecasting) 이라고 합니다. C에서 타입캐스팅을 하려면 타입캐스팅 연산자를 사용해야 합니다. 그런데 타입캐스팅 연산자는 아주 간단합니다. 타입 형태 키워드들 즉 int, char, float등등이 타입캐스팅 연산자 기능까지 해 주기 때문이죠. 타입캐스팅 방법은 (타입)데이터 이렇게 하면 타입캐스팅이 됨니다. 여기서 타입은 바꿀 형태의 타입캐스팅 연산자 이고 데이터는 형태를 바꿀 데이터 인데 변수나 상수가 올수 있습니다. 또한 수식이 와도 상관 없습니다. 예를 들어보죠 int a=10; unsigned long=b,c; c=(unsigned long)a+b; 이 소스는 int형인 a를 unsigned long로 타입캐스팅 해서 unsigned long형태인 b와 더해 c에 넣는 것 입니다. 이제 이해가 되셨겠죠?? (6) 접미사 한가지 여기서 알고 넘어갈 것이 있는데 (사실 지금 설명할건 연산자와는 상관 없는 거지만....) 상수중 실재값은 정수의 경우 무조건 signed형태로 인식하고 int형태 범위 내에 값이면 int형으로 인식하며 그것을 벗어나면 long형으로 인식하게 됨니다. 그리고 소수의 경우는 무조건 double로 인식하죠 그러므로 상수는 타입 캐스팅이 많이 필요합니다. 만약 123이란 상수가 있다고 합시다. 이건 int형태 범위 내에 있으므로 signed int로 인식됨니다. 그런데 이걸 unsigned long로 타입캐스팅 하려면 (unsigned long)123 이렇게 하면 됨니다 하지만 이 방법보다 편한 방법이 있는데 123을 그냥 unsigned long형태로 인식시키는 것이죠. 그렇게 하기 위해선 접미사를 쓰면 됨니다. 접미사에는 L,F,U의 3가지가 있습니다. 그리고 대소문자 구별은 없습니다. L은 long를, F는 float를, U는 unsigned를 의미 합니다. 그러므로 위에 것을 123UL 이렇게 서 주면 이 123은 unsigned long로 인식되어 타입 캐스팅이 필요가 없어 집니다. 이번 강좌에서는 계속해서 연산자인관계형 연산자, 논리 연산자, 비트별 연산자 등에 대해 알아보겠습니다. 2. 관계형 연산자. 관계형 연산자는 ..보타 크다, ..보다 작다, ..와 같다, ..와 같지 않다 등등.. 어떤 데이터들을 비교할때 쓰이는 연산자 입니다. 주로 제어 구조, 특히 if문에서 쓰이지만 꼭 그런것은 아님니다. 우선 관계형 연산자에는 어떤것이 있는지 알아보죠. 관계형 연산자에는 ------------------------------ == ..와 같다 > ..보다 크다 < ..보다 작다 >= ..보다 크거나 같다. <= ..보다 작거나 같다. != ..와 다르다. ------------------------------ 다음과 같은 것들이 있습니다. 그럼 각 연산자들의 이해를 돕기 위해 다음 표를 보시기 바랍니다. ----------------------------------- a == b a와 b가 같다 a > b a가 b보다 크다 a < b a가 b보다 작다 a >= b a가 b보다 크거나 같다. a <= b a가 b보다 작거나 같다. a != b a와 b가 다르다. ----------------------------------- 이걸 보시면 이해가 되실겁니다. 그런데 대부분의 연산자들은 어떤 값을 돌려주죠. 예를 들어 +연산자는 두개의 값을 더해 돌려 주죠. 그러면 이 관계형 연산자는 무엇을 돌려 줄까요? 돌려주는 값은 0과 1중 한가지 입니다. 관계형 연산자가 쓰인 수식을 보면 어떤 조건을 나타내고 있음을 알게되실 겁니다. 그 수식이 참이면 1을 돌려주고, 거짓이면 0을 돌려주죠. 예를 들어 a=1==2; 이런 문장이 있다고 합시다. 그럼 a에는 어떤 값이 들어갈까요? '1과 2는 같다' <- 이건 거짓이므로 a에는 0이 들어가겠죠? 3. 논리 연산자. 논리 연산자는 아까 관계 연산자의 수식 두가지를 논리적으로 연관시키는 연산자 입니다. 쉽게 말하지면 관계형 연산자로 조건이 만들어 지는데 이런 조건 두개가 동시에 만족해야할 경우가 있다고 합시다. 그럴 경우 이 논리 연산자를 쓰면 됨니다. 논리 연산자에는 다음과 같은 것들이 있습니다. -------------- && AND || OR ! NOT -------------- 각각의 의미는 위에 쓰여진 그대로인데 이걸 보세요 그런데 여기서 a와 b는 관계형 연산자로 만든 조건이라고 합시다. ---------------------------- a && b a와 b모두 참일때 a || b a또는 b가 참일때 ! a a의 반대 ---------------------------- a && b의 경우 a라는 조건과 b라는 조건이 모두 참일때 1을 돌려주고. 하나라도 거짓이면 0을 돌려 주죠 a || b의 경우는 둘 중 하나만 참이면 1을 모두 거짓일때만 0을 돌려주죠. ! a의 경우 반대로 되는데 즉 참이면 0을 거짓이면 1을 돌려줌니다. 만약 다음과 같은 문장이 있다고 합시다 a=(2>1)&&(3>1); 이럴경우 a에는 어떤 값이 들어갈까요? 당연히 1이 들어가죠 하지만 a=(1>5)&&(3>1); 이럴땐 0이 들어가겠죠?? 4. 비트별 연산자 비트별 연산자는 비트단위 연산을 할때 쓰이는 연산자 입니다. 먼저 비트별 연산자의 종류를 알아보죠. 비트별 연산자에는 다음과 같은 것 들이 있습니다. ------------------------------ & AND (비트별 논리곱) | OR (비트별 논리합) ^ XOR (비트별 배타 논리합) ~ 1의 보수 << 왼쪽으로 쉬프트 >> 오른쪽으로 쉬프트 ------------------------------ 다음과 같은 것들이 있는데 하나씩 자세히 알아보죠. (1) 비트별 논리곱 &는 비트 단위로 AND연산을 하는 건데, 연산하려는 두 개의 비트가 모두 1일때만 결과가 1이 되고 하나라도 0이면 결과는 0이 됨니다. 정리하면 ------------------------------------ 첫번째 비트 두번째 비트 결과 ------------------------------------ 1 & 1 1 1 & 0 0 0 & 1 0 0 & 0 0 ----------------------------------- 이렇게 되죠 한가지 문제를 드리죠 0x0F & 0xFF = ? 알아맞춰 보세요. 답은 0x0F죠. 0x0F는 이진수로 00001111입니다. 0xFF는 11111111이죠. 그런데 &연산자는 모두 1일때만 1을 돌려 줌니다. 00001111과 11111111에서 모두 1인 부분은 뒤쪽 4개의 비트죠. 그러므로 결과는 00001111 이걸 16진수로 고치면 0x0F가 되죠. 다시 정리하면 ----------------------------- 0x0F = 00001111 0xFF = 11111111 ---------- (& 연산) 00001111 = 0x0F ----------------------------- 이해가 되시죠? (2) 비트별 논리합 다음으로 |연산자에 대해 자세히 알아보죠. |는 OR연산을 하는 것으로 &와는 달리 두개의 비트중 1개라도 1이면 1을 돌려주는 연산자 입니다. 즉 ------------------------------------ 첫번째 비트 두번째 비트 결과 ------------------------------------ 1 | 1 1 1 | 0 1 0 | 1 1 0 | 0 0 ------------------------------------ 이런 연산을 하는 연산자 입니다. 그럼 이것두 문제를 드릴까요? 아까처럼 0x0F와 0xFF를 쓰도록 하죠 그런데 이 두개를 OR연산 하면 어떤 결과가 나올까요? 당연히 0xFF죠. 이유는 하나라도 1이면 1을 돌려 주므로. ----------------------------- 0x0F = 00001111 0xFF = 11111111 ---------- (| 연산) 11111111 = 0xFF ----------------------------- 이렇게 되기 때문이죠. (3) 비트별 배타 논리합 다음으로 ^연산자에 대해 알아보죠. ^는 비트단위 배타 OR연산 즉 비트단위 XOR연산을 하는 연산자 입니다. 이 연산자는 OR비슷하지만, 다른점은 두개의 비트가 모두 1일때는 0을 돌려준다는 것이죠. OR에서는 1을 돌려주지만 즉.. ------------------------------------ 첫번째 비트 두번째 비트 결과 ------------------------------------ 1 ^ 1 0 1 ^ 0 1 0 ^ 1 1 0 ^ & 0 ------------------------------------ 다음과 같은 연산을 하게 됨니다. 그럼 이번엔 0x0F와 0xFF를 XOR연산 하면 어떤 결과가 나올까요? 이건 ----------------------------- 0x0F = 00001111 0xFF = 11111111 ---------- (| 연산) 11110000 = 0xF0 ----------------------------- 이렇게 해서 0xF0이 나오게 됨니다. (4) 1의 보수 다음으로 ^연산자에 대해 알아보죠. ^는 1의 보수를 구하는 연산자로 그냥 쉽게 비트들을 반대로 즉 0이면 1로 1이면 0으로 바꿔버린다고 알고계시면 됨니다. ----------------------- 비트 결과 ----------------------- ~ 0 1 ~ 1 0 ----------------------- 이런 연산을 하는 것이죠. 1의 보수 연산을 잘 쓰면 좋은점이 많이 있습니다. 만약 여러분이 unsigned long가 가질수 있는 가장 큰 값을 써야 할 경우 어떻게 할까요? unsigned long는 4294967296까지 넣을수 있는데 이걸 직접 써야 할까요? 그렇게 해도 되고 좀더 쉬운 방법으로 0xFFFFFFFF라고 써도 되겠지만 더 쉬운 방법은 ~0이라고 쓰는 것 입니다. 0은 모든 비트가 0인데 이걸 1의 보수 연산자로 ~0이라고 쓰면 모든 비트가 1이 되므로 가장 큰값이 되는 것이죠. (5) 쉬프트 다음으로 쉬프트 연산자인 <<와 >>에 대해 알아보죠 <<,>>는 지정된 방향으로 지정되 수 만큼 비트를 이동시키는 것 입니다. 예를 들어 ?? = 0xF0 >> 4; 이렇게 하면 0xF0 즉 11110000을 >>방향으로 4만큼 이동시키는 것이죠 그래서 결과는 00001111 즉 0x0F가 됨니다. 만약 1이 오른쪽 끝까지 갔다면 그냥 없어집니다. 그리고 왼쪽은 0으로 계속 채워지구요. <<도 이것과 똑같으나 방향만 다를 뿐 입니다. 이것으로 비트별 연산자는 마치도록 하죠. 5. 기타 연산자. 다음으로 기타 연산자들을 배워 보기로 하겠습니다. 여기서 배울 것에는 조건 연산자, 증감 연산자, 그리고 sizeof연산자와, 혼합 연산자가 있습니다. (1) 조건 연산자 조건 연산자는 주어진 조건에 따라 어떤 수식을 실행하고 그 결과를 돌려주는 연산자 입니다. 사용법은 조건 ? 수식1 : 수식2 이런 식으로 사용하죠. 여기서 조건은 관계형 연산자로 만든 조건입니다. 여기서 만약 조건이 참이면 수식1을 실행한 후 그 결과를 돌려주고, 거짓이면 수식2를 실행하는 것 입니다. 예를 들어 보죠. a = 1>3 ? 1+3 : 2+6; 여기서 a에 들어가는 값은? 1>3이란 조건은 거짓이므로 두번째 수식인 2+6이 실행되고 결과로 8을 돌려주므로 a는 8이 되겠죠. 이 문장은 1>3 ? a=1+3 : a=2+6; 이렇게 써도 상관 없습니다. =이 들어가도 수식이므로 (2) 증감 연산자 이번엔 증감 연산자에 대해 알아보죠. 증감 연산자는 어떠 변수에 1을 더하거나 빼 주는 연산자이죠 연산자에는 --------------------- ++ 1을 증가시킴 -- 1을 감소시킴 --------------------- 이렇게 두 가지가 있습니다. 이 두 연산자는 변수 앞이나 뒤에 붙여 사용하면 되는데 앞에 붙일때와 뒤에 붙일때의 차이점은 일단 나중으로 넘기고 예를 들어보죠. 만약 a++; 이렇게 하면 a는 1이 증가하게 됨니다. 즉 a=a+1;가 되는 것이죠. 그리고 a--; 이렇게 하면 a=a-1;이 되는 것 이고요. 그럼 앞에 붙이느냐 뒤에 붙이느냐에 차이를 알아보죠. 이 차이가 나는 곳은 바로 이 연산자가 하나로만 쓰이지 않고 여러개의 연산자와 같이 쓰였을때 차이가 남니다. 이 연산자를 앞에 붙이면 이 연산이 가장 먼저 수행되고 다른 연산이 수행됨니다. 하지만 이 연산자를 뒤에 붙이면 다른 모든 연산을 수행하고 이 연산을 수행하게 되죠. 예를 들어 int a,b=1; a = 6 - ++b; 이렇게 했을때는 앞에 붙었으므로 우선 b를 1 증가시켜 2로 만든 후 6에서 빼 a에는 4가 들어가지만 int a,b=1; a = 6 - b++; 이럴경우 우선 다른 연산부터 해서 a에는 5가 들어가고 마지막으로 b가 1이 증가되어 2가 되게 됨니다. (3) sizeof연산자 이번엔 sizeof연산자에 대해 알아보죠. sizeof는 어떤 데이터 타입이나 변수, 또는 상수의 크기를 바이트 단위로 알아내는 연산자 입니다. 사용법은 sizeof(데이터타입) 또는 sizeof(데이터) 예를 들어 a=sizeof(char) 이렇게 할 경우 char형태는 1바이트 이므로 a는 1이 됨니다. 그리고 char c; a=sizeof(c); 이렇게 해도 1이 되죠 a=sizeof(long); 이렇게 하면 4를 돌려 주겠죠? 그리고 만약 배열이라면 배열 크기를 바이트 수로 돌려줌니다. 예를 들어 int array[10]; a=sizeof(array); 이렇게 할 경우 int는 2바이트 이고 10개의 배열이므로 2*10=20이므로 20을 돌려줌니다. (4) 혼합 연산자. 혼합 연산자는 말 그대로 두개의 연산자를 혼합한 것 입니다. 프로그램을 만들다 보면 a=a+3; a=a-2; a=a*3; a=a/2; a=a|0x0F; a=a&0x0A; a=a>>4; 이런 수식처럼 한개의 데이터 여기선 a가 겹치는 수식을 쓸 때가 있습니다. 이럴때 더 간단히 쓸 수가 있습니다. 바로 혼합 연산자를 쓰면 되는데 혼합 연산자의 종류에는 +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= 이런 것들이 있습니다. 각각의 기능을 살펴보면 ------------------------------ a += b -> a = a + b a -= b -> a = a - b a *= b -> a = a * b a /= b -> a = a / b a %= b -> a = a % b a &= b -> a = a & b a |= b -> a = a | b a ^= b -> a = a ^ b a <<= b -> a = a << b a >>= b -> a = a >> b ------------------------------ 이런 기능을 합니다. 이렇게 혼합 연산자를 잘 쓰면 수식을 더 간단히 쓸수 있죠. 이것으로 이번 강좌는 마치도록 하겠습니다. 이제 연산자 부분은 다 끝났습니다. 다음 강좌 부터는 프로그램 흐름 제어에 관한 공부를 해 보겠습니다.