처음으로 배우는 C 프로그래밍 제5부 추가적인 화제들 제 12 장 부가 특성
제 1 절 부가기능 typedef 선언문 이미 존재하는 C 자료형 이름을 다른 이름으로 사용할 수 있게 한다. 제 1 절 부가기능 typedef 선언문 이미 존재하는 C 자료형 이름을 다른 이름으로 사용할 수 있게 한다. typedef float REAL; REAL val; float val; 같은 의미를 갖는다.
제 1 절 부가기능 typedef의 확장 typedef struct { char name[100]; int id_num; 제 1 절 부가기능 typedef의 확장 는 와 같다. typedef struct { char name[100]; int id_num; }EMP_REC; EMP_REC employee[74]; struct { char name[100]; int id_num; } employee[75];
제 1 절 부가기능 enum 명세자 enum color a, b, c; a = red; b = a; 제 1 절 부가기능 enum 명세자 사용자가 정의한 값의 목록인 나열 자료형(enumeration data type)이다. enum color { red, green, blue}; color 라는 나열 자료형은 red, green, blue라는 값을 갖는다. 내부적으로 나열 자료형에 나열된 값들은 0에서부터 시작하여 양의 정수로 순서적으로 치환된다. 예) enum color a, b, c; a = red; b = a; if (c==yellow) printf("\nThe color is yellow");
제 1 절 부가기능 프로그램 12-1 #include <stdio.h> void main(void) { 제 1 절 부가기능 프로그램 12-1 #include <stdio.h> void main(void) { enum color red, green, yellow; enum color crayon = red; /* crayon을 color 형으로 선언하고 red값으로 초기화함 */ printf("\f2 nThe color is %d", crayon); printf("Enter in a value: "); scanf("%d", &crayon); if (crayon == red) printf("The crayon is red. "); else if (crayon == green) printf("The crayon is green. "); else if (crayon == yellow) printf("The crayon is yellow. "); else printf("The crayon is not defined. "); }
제 1 절 부가기능 컴파일러에 의해 나열 자료형 값에 대한 정수는 나열 자료형이 생성될 때 특정 정수 값을 할당함으로써 변경될 수 있다. enum color {red, green = 7, yellow}; red는 정수 0으로 치환되지만, green과 yellow는 각각 정수 7과 8로 치환된다. 표준 C 자료형에 적용 가능한 유효범위 규칙(scope rule)이 나열 자료형에도 적용된다. 나열 자료형에서 사용자가 정의한 자료 값과 정수는 일대일로 대응되므로 cast 연산자를 사용하여 강제로 정수를 사용자 정의 자료 값으로 혹은 사용자 정의 자료 값을 동일한 정수로 변환시킬 수 있다.
제 1 절 부가기능 캐스트(casts) 표 12-1 산술 연산자의 변환 규칙 제 1 절 부가기능 캐스트(casts) 표 12-1 산술 연산자의 변환 규칙 규칙 1: 모든 문자와 short 정수 피연산자는 항상 정수로 변환된다. 모든 부동소수점 피연산자는 배정밀도 수로 변환된다. 규칙 2: 하나의 피연산자가 배정밀도 수이면 다른 피연산자는 배정밀도 수로 변환되며 수식의 결과도 배정밀도 수이다. 규칙 3: 하나의 피연산자가 long 형 정수이면 다른 피연산자는 long형 정수로 변환되며 수식의 결과도 long 형 정수이다. 규칙 4: 하나의 피연산자가 부호 없는 정수이면 다른 피연산자는 부호 없는 정수로 변환되며 이 수식의 결과는 부호 없는 정수이다. 규칙 5: 두 피연산자가 int 형이면 변환이 일어나지 않으며 이 수식의 결 과는 정수이다. 이들 규칙은 단계적으로 적용된다.
제 1 절 부가기능 자동 형 변환 a = b * d - e % f; a, b : 정수형(int) e : short 정수형 제 1 절 부가기능 자동 형 변환 a = b * d - e % f; a, b : 정수형(int) e : short 정수형 f : long 정수형 b : 부동 소수점 변수 강제 형 변환 값을 다른 형으로 변환하기 위한 연산자는 캐스트(cast) 연산자이다. (int)(a * b) 주의 a,b는 배정밀도 변수 (int)a * b
제 1 절 부가기능 조건 수식(conditional expression) if (hours > 40) 제 1 절 부가기능 조건 수식(conditional expression) 형태 : expression1 ? expression2 : expression3 수식 expression1의 값이 0이 아니면, 즉 참(true)이면 수식 expression2의 값이 구해지고, 그렇지 않으면 수식 expression3의 값이 구해진다. if (hours > 40) rate = 0.045; else rate = 0.02; rate = (hours > 40) ? 0.045 : 0.02;
제 1 절 부가기능 goto 문 if (denom == 0.0) goto err; else 제 1 절 부가기능 goto 문 프로그램의 실행 제어를 아무 조건 없이 다른 곳으로 넘길 수 있다. if (denom == 0.0) goto err; else result = num / denom; err: printf("Error - Attempted Division by Zero");
제 1 절 부가기능 if (a == 100) goto first; else x = 20; goto sec; 제 1 절 부가기능 goto 문의 부적절한 사용 예 if (a == 100) goto first; else x = 20; goto sec; first: x= 50; sec: y= 10; if (a == 100) x = 50; else x = 20; y = 10;
제 2 절 비트별 연산자(bitwise operator) C 언어는 문자, 정수 상수 및 변수의 개개 비트를 조작할 수 있는 기능을 제공한다. 비트 조작을 실행하기 위해 사용된 연산자를 비트 연산자(bit operator)라 한다.
제 2 절 비트별 연산자(bitwise operator) AND연산자 (AND operator) AND 연산자는 두 피연산자간의 비트별 AND 비교를 수행한다. 각 비트별 비교 결과는 비교되어질 두 비트가 1인 경우 1이고 그 이외의 경우는 모두 0이다. 1 0 1 1 0 0 1 1 & 1 1 0 1 0 1 0 1 ----------------- 1 0 0 1 0 0 0 1
제 2 절 비트별 연산자(bitwise operator) #include <stdio.h> void main(void) { int op1 = 0325, op2 = 0263; printf("%o ANDed with %o is %o",op1,op2,op1&op2); } 실행 결과 => 325 ANDed with 263 is 221
제 2 절 비트별 연산자(bitwise operator) AND 연산은 임의의 피연산자로부터 선택된 비트를 제거하거나 혹은 마스킹(masking)하는데 유용하게 사용된다. op2에 있는 비트 0은 op1에 대응되는 비트를 마스크(mask) 시키고, op2에 있는 비트 1는 op1에 대응되는 비트를 여과시킨다(filtering). 변수 op2를 마스크라고 한다. op1= x x x x x x x x op2= 0 0 0 0 1 1 1 1 ----------------- 0 0 0 0 x x x x
제 2 절 비트별 연산자(bitwise operator) 포함 OR 연산자 (inclusive OR operator) 서로 비교되어질 두 비트들 중 하나라도 1이면 포함 OR 비교의 결과는 1이며, 그렇지 않으면 0이다. 1 0 1 1 0 0 1 1 | 1 1 0 1 0 1 0 1 ----------------- 1 1 1 1 0 1 1 1
제 2 절 비트별 연산자(bitwise operator) #include <stdio.h> void main(void) { int op1 = 0325, op2 = 0263; printf("%o ORed with %o is %o",op1,op2,op1|op2); } 실행 결과 => 325 ORed with 263 is 367
제 2 절 비트별 연산자(bitwise operator) op2에 있는 비트 1은 항상 대응되는 결과 비트를 1로 만들고, 비트 0에 대해서는 대응되는 결과 비트를 변하지 않는 op1 비트로 만든다. op1 = x x x x x x x x op2 = 1 1 1 1 0 0 0 0 --------------------- 결과 = 1 1 1 1 x x x x
제 2 절 비트별 연산자(bitwise operator) 배타 OR 연산자 (exclusive OR operator) 비교될 두 비트가 서로 다르면 비교 결과는 1이고 그렇지 않으면 그 결과는 0이다. 1 0 1 1 0 0 1 1 ^ 1 1 0 1 0 1 0 1 ----------------- 0 1 1 0 0 1 1 0
제 2 절 비트별 연산자(bitwise operator) op2에 있는 1에 의해 원래 비트 값이 보수로 변했고, op2에 있는 0은 원래 비트 값을 그대로 유지한다. op1 = x x x x x x x x op2 = 0 1 0 1 0 1 0 1 --------------------- 결과 = x x x x x x x x
제 2 절 비트별 연산자(bitwise operator) 보수 연산자 (complement operator) 보수 연산자 ~는 단항 연산자로 피연산자에 있는 비트 1을 0으로, 비트 0을 1로 바꾼다. 변수 op1이 이진수로 11001010이면 ~op1은 00110101이다. 보수 연산자는 피연산자의 임의의 비트를 모두 0으로 만들기 위해 사용될 수 있다. 예를 들어, op1 = op1 & ~07; (간단하게 op1 &= ~07;)은 op1의 마지막 세 비트 값 모두를 0으로 만든다.
제 2 절 비트별 연산자(bitwise operator) 서로 다른 크기의 자료 항목 비트 연산자 &, |, ^이 서로 다른 크기의 피연산자를 사용하는 경우 길이가 짧은 피연산자의 길이를 증가 시킨다. 그림 12-4 16비트 부호 없는 자료를 32비트 자료로 확장
제 2 절 비트별 연산자(bitwise operator) 그림 12-4 16비트 부호 있는 자료를 32비트 자료로 확장
제 2 절 비트별 연산자(bitwise operator) 이동 연산자(Shift Operator) 좌측 이동 연산자(<<)는 피연산자에 있는 비트를 주어진 수만큼 좌측으로 이동시킨다. 부호 없는 정수에 대해 좌측 이동은 2를 곱한 것과 같다. 그림 12-6 좌측이동 예
제 2 절 비트별 연산자(bitwise operator) 우측 이동 연산자(>>)는 피연산자에 있는 비트를 주어진 수만큼 우측으로 이동시킨다. 그림 12-7a 부호 없는 수의 우측 이동 예
제 2 절 비트별 연산자(bitwise operator)
제 2 절 비트별 연산자(bitwise operator) 그림 12-7c 양수의 산술 우측 이동 예
제 2 절 비트별 연산자(bitwise operator) 산술 우측 이동에서 우측으로 한번 이동은 2로 나눈 것과 같다. 논리 이동(logical shift) 부호 있는 수에 대해 우측 이동 시 빈 비트를 부호 비트로 채우는 대신 빈 비트를 0으로 채우는 경우
제 3 절 매크로 동치 관계가 하나 이상의 값, 연산자 혹은 변수로 구성되는 경우 기호명을 매크로(macro)라고 부르고, 기호명 대신에 문장으로 치환하는 것을 매크로 확장(macro expansion) 혹은 매크로 치환(macro substitution)이라 한다. #define 전처리기가 상수와 연산자를 기호명(symbolic name)과 같게 하기 위해 사용된다. 예) #define SALESTAX 0.05 예) #define FORMAT “The answer is %f” printf(FORMAT, 15.2); #define 문은 직접적 문장 치환이외에도 인자를 사용하는 동치 문을 정의할 수 있다. 예) #define SQUARE(x) x * x y = SQUARE(num);와 같은 문장은 전처리기에 의해 y = num * num;으로치환된다.
제 3 절 매크로 #define SQUARE(x) (x) * (x) 매크로 사용의 주의 제 3 절 매크로 매크로 사용의 주의 #define SQUARE(x) x * x val = SQUARE(num1 + num2); val = (num1+num2)*(num1+num2) val = num1 + num2 * num1 + num2; #define SQUARE(x) (x) * (x)
제 4 절 명령 행 인자(command line argument) 이 장에서 우리는 프로그램이 처음 실행될 때 main() 함수에 인자를 전달하고 저장하는 방법을 설명한다. 인자는 main() 함수를 포함하여 임의의 함수에 전달될 수 있다.
제 4 절 명령 행 인자(command line argument) 실행 파일이 showad.exe라면 명령 행 C>showad는 showad.exe라는 프로그램을 실행시킨다. 그림 12-8 showad 프로그램 실행
제 4 절 명령 행 인자(command line argument) 세 개의 문자열 인자 three blind mice를 main() 함수에 직접적으로 전달하기를 원한다고 가정해 보자. C>showad three blind mice 그림 12-9 메모리에 저장된 명령 행
제 4 절 명령 행 인자(command line argument) 함수 인자와 같이 main() 함수에 전달된 인자는 함수 정의 시에 선언되어 있어야 한다. main() 함수에 전달될 인자를 저장하기 위해 두 개의 항목, 즉 수와 배열이 요구된다. 수는 정수이며, 일반적으로 argc(argument counter의 약어)라는 이름을 갖는다. 배열은 문자열을 저장하기 위한 일차원 배열이며, 일반적으로 argv(argument values의 약어)라는 이름을 갖는다.
제 4 절 명령 행 인자(command line argument) main() 함수에 전달된 정수, argc는 명령 행의 입력된 항목의 개수를 의미한다. 그림 12-11 argv 배열에 저장된 명령 행의 입력 항목
제 4 절 명령 행 인자(command line argument) 프로그램 12-4 #include <stdio.h> void main(int argc, char *argv[]) { int I; printf("\f2 nThe number of items on the command line is %d", argc); for (i=0; I < argc; I++) printf("The address stored in argv[%d] is %p”, I, argv[i]); printf("The character pointed to is %c", *argv[i]); }
제 4 절 명령 행 인자(command line argument) 프로그램 12-4의 실행 C>showad three blind mice 실행 결과는 다음과 같다. The number of items on the command line is 4 The address stored in argv[0] is FFDA The character pointed to is s The address stored in argv[1] is FFEB The character pointed to is t The address stored in argv[2] is FFF1 The character pointed to is b The address stored in argv[3] is FFF7 The character pointed to is m
제 4 절 명령 행 인자(command line argument) 그림 12-12 메모리에 저장된 명령 행
제 4 절 명령 행 인자(command line argument) 프로그램 12-5 /* 명령 행 인자를 출력하는 프로그램 */ #include <stdio.h> void main(int argc, char *argv[]) { int I; printf("\f2 nThe following arguments were passed to main(): "); for (i=1; I < argc; I++) printf("%s ", argv[i]); printf(""); }
제 4 절 명령 행 인자(command line argument) 프로그램 12-6 /* 명령 행 인자를 수치 자료로 출력하는 프로그램 */ #include <stdio.h> void main(int argc, char *argv[]) { int I; int value; int sum = 0; printf("\f2 nThe following numerical data of the arguments passed to main(): "); for (i=1; I < argc; I++) value = atoi(argv[i]); sum += value; printf("%d ", value); } printf("\f2 nThe sum of the numerical data is %d", sum);