330 likes | 479 Views
Chapter 15. Bitwise Operators, Macros. 데이터의 각 비트를 조작함 32 비트 워드이면 32 비트 각각을 조작함 and(&), inclusive or(|), exclusive or(^), one’s complement(~) 32 비트를 주로 32 를 Octal, Hexadecimal 로 표시하여 사용하며 , 논리비트 연산자를 이용하여 masking 하여 값을 가져오거나 바꾼다 . 자질값 등을 한두 비트로 표현하여 메모리 사용량을 줄이고 , 관리를 쉽게 함
E N D
Chapter 15 Bitwise Operators, Macros
데이터의 각 비트를 조작함 32비트 워드이면 32비트 각각을 조작함 and(&), inclusive or(|), exclusive or(^), one’s complement(~) 32비트를 주로 32를 Octal, Hexadecimal로 표시하여 사용하며, 논리비트 연산자를 이용하여 masking하여 값을 가져오거나 바꾼다. 자질값 등을 한두 비트로 표현하여 메모리 사용량을 줄이고, 관리를 쉽게 함 사용례: 사전정보 저장 등 논리 비트 연산자들
#include <stdio.h> #include <string.h> /* Prototype Declarations */ char *makeBin16 (unsigned short dec, char *strNum); int main (void) { /* Local Definitions */ char strNum[17]; short num1 = 0257; /* Octal 0257-Binary 010101111 */ short num2 = 0463; /* Octal 0463-Binary 100110011 */ short res; /* Statements */ res = num1 & num2; printf("First Number : %s\n", makeBin16(num1, strNum)); printf("Second Number: %s\n", makeBin16(num2, strNum)); printf ("AND Result : %s\n", makeBin16(res, strNum)); return 0; } /*main */ and
/* ==================== makeBin16 ==================== Convert a decimal to binary. Pre dec is a positive decimal number Post returns 17-byte string in binary format */ char *makeBin16 (unsigned short dec, char *strNum) { /* Local Definitions */ char str[17] = "0000000000000000"; int bitLocn; /* Statements */ bitLocn = sizeof(str) - 2; while (dec > 0) { if (dec % 2) *(str + bitLocn--) = '1'; else *(str + bitLocn--) = '0'; dec /= 2; } /* while */ strcpy (strNum, str); return strNum; } /* makeBin16 */ 출력프로그램
/* Run results: First Number : 0000000010101111 Second Number: 0000000100110011 AND Result : 0000000000100011 */ 결과
/* Run results: First Number : 0000000010101111 Second Number: 0000000100110011 OR Result : 0000000110111111 */ /* Run Results First Number : 0000000010101111 Second Number: 0000000100110011 XOR Result : 0000000110011100 */ /* Results: Original Num : 0000000010101111 Complemented Num: 1111111101010000 */ or, xor, one’s complement
이동연산자 • Bitwise Shift-Left Operator • num << shift-횟수 • 1번 shift하면 숫자는 2배가 된다. 2번이면 …
#include <stdio.h> int main (void) { int num = 49U; int res; res = num << 1; printf("Original value: %3d\n", num); printf("Shifted 1 left: %3d\n", res); res = num << 2; printf ("Shifted 2 left: %3d \n", res); res = num << 4; printf ("Shifted 4 left: %3d \n", res); return 0; } /* main */ 프로그램 예 /* Results: Original value: 49 Shifted 1 left: 98 (times 2) Shifted 2 left: 196 (times 4) Shifted 4 left: 784 (times 16) */
Bitwise Shift-right 연산자 • num >> shift-횟수 • 1번 shift하면 숫자는 1/2배가 된다. 2번이면 1/4번…
#include <stdio.h> int main (void) { /* Local Definitions */ int num = 64; int res; /* Statements */ res = num >> 1; printf("Original value: %3d\n", num); printf("Shifted right 1:%3d\n", res); res = num >> 2; printf("Shifted right 2:%3d\n", res); res = num >> 4; printf("Shifted right 4:%3d\n", res); return 0; } /* main */ 프로그램 예 /* Results: Original value: 64 Shifted 1 right: 32 (divide by 2) Shifted 2 right: 16 (divide by 4) Shifted 4 right: 4 (divide by 16) */
Bitwise Use • 이진 표시 문자를 비트로 표시 • Masking: 변수(워드 또는 바이트)에서 특정 비트 또는 몇 비트의 값을 바꾸거나 알아내기 위한 일종의 필터링 작업 • shift를 이용할 수도 있고, 논리비트연산을 할 수도 있다.
One-bit masks Two-bit masks Setting bit range masks Complement masks Masking #define FLAG1 0 #define FLAG5 0 char mask, mask1, mask2; mask = 1 << FLAG5; // 1bit masking mask1 = 1 << FLAG1; mask2 = 1 << FLAG5; mask = mask1 | mask2; // 2bits masking mask = ‘\0’; for (i=3; i<=6; i++) { temp = 1 << i; mask = mask | temp; } // setting bit range masking mask = 1 << FLAG1; mask = ~ mask; // complement masking
Using Masks - Turning bits off #include <stdio.h> #define CASE 5 int main (void) { char word[81]; char *pStr = word; char mask; printf("Please enter a word (alpha characters only)\n"); fgets (word, sizeof(word) - 1, stdin); printf("\nOriginal string: %s\n", word); mask = 1 << CASE; mask = ~mask; /* mask 11011111 */ while (*pStr != '\n') { *pStr = *pStr & mask; pStr++; } /* while */ printf("Modified string: %s\n", word); return 0; } /*main */ /*Results Please enter a word (alpha characters only) computers Original string: computers Modified string: COMPUTERS */
Using Masks - Turning bits on #include <stdio.h> #define CASE 5 int main (void) { char string [81]; char *pStr = string; char mask; printf("Please enter a word with upper & lower case: "); fgets (string, sizeof(string) - 1, stdin); printf("Original string: %s\n", string); mask = 1 << CASE; /* mask 00100000 */ while (*pStr != '\n') { *pStr = *pStr | mask; pStr++; } /* while */ printf("Revised string: %s\n", string); return 0; } /* main */ /*Results Please enter a word with upper & lower case: cOmPuTErs Original string: cOmPuTErs Revised string: computers */
Using Masks – Flipping bits #include <stdio.h> #define CASE 5 int main (void) { char word [81]; char *pStr = word; char mask; printf("Please enter a word: "); fgets (word, sizeof(word) - 1, stdin); printf("\nOriginal word: %s\n", word); mask = 1 << CASE; /* mask: 00100000 */ while (*pStr != '\n') { *pStr = *pStr ^ mask; pStr++; } /* while */ printf("Revised word : %s\n", word); return 0; } /* main */ /*Results: Please enter a word: Computers Original word: Computers Revised word : cOMPUTERS */
순환: 왼쪽으로 순환하면 빠져나온 비트가 오른쪽으로 삽입, 오른쪽으로 순환하면 반대 예 0100 0000 0010 1100 1000 0000 0000 0000 mask = data << 13; data = data >> 3; data = data | mask; 비트 순환
data = data | x00f0 data = data & x00f0 data = data ^ x00f0 실제 쓰이는 예 단어가 명사, 동사 등을 구별하는 데 8비트, 사용빈도 상중하 2비트, 동사이면 자동사냐 타동사냐 1비트, 명사이면 사람, 동물 등 구별 8비트 등으로 표현할 때를 생각해보면 효과적임. 다른 예로 색인어(검색엔진)가 문서에서, 제목에서, 링크를 따라 나왔는지를 각각 1워드에 넣어서 표현할 때 남/여 1비트, 나이 8비트, 결혼 여부 1비트 등으로 압축하여 쓸 때 일반적으로 바로 masking한 후 0인지 아닌지를 가지고 1비트면 바로 비교 다른 방법
컴파일 전에 대치 따라서 ‘;’을 쓰지 않음 상수선언에서 일부 보았음. 추후 Macro로 확대 Preprocessor
#include <stdio.h> 주로 라이브러리에 적용 #include “filename.h” 주로 소스코드가 들어있는 라이브러리의 헤더파일 #include “K:PROJECT\SOURCE\HEADER.H” 파일 포함시키기
일반적으로 함수문보다 처리가 빠름 프로그램 길이는 매크로를 확장하면 커짐 간단한 함수 정의에 사용됨 #define name tokens(s) Macros
#define SIZE 9 #define TRUE 1 #define OF_MSG “Err 304 : Overflow.” #define LIMIT (234) #define FLUSH while (getchar() != ‘\n’) 단순명령
#define name(par1, par2, …) replacements-token #define SUM(x, y) x+y x= SUM(a,5); x=a+5; y= SUM(a,b); y=a+b; 매개변수 사용
#define PRODUCT(x,y) x*y z = PRODUCT(a,b); z=a*b; 조심!!! z= PRODUCT(a+1, b+1); a+1*b+2; !!! #define PRODUCT(x,y) (x)*(y) z= PRODUCT(a+1, b+1); (a+1)*(b+2); 다른 예
#define PRODUCT(a,b) (a)*(b) #define SQUARE(a) PRODUCT(a,a) x= SQUARE(5); x=PRODUCT(5) x = (5)*(5) 단, 재귀적으로 매크로를 정의할 수 없다. 중첩 매크로
원칙적으로 매크로는 한 줄에 코딩되어야 하지만 ‘\’를 이용하여 줄을 넘길 수 있다. #define ADD(a,b) \ a+b 문자열 안에서 사용할 때 토큰(파라미터)와 문자를 구별할 수 있어야 하므로, 문자열 안에서는 #변수이름으로 쓴다. #define test(a) “This is #a” 토큰을 병합하려면 ‘##’을 쓴다. #define FORM(T,N) T##N int FORM(A,1) = 1; int A1=1; 변경은 바로 하지 못하고, undefine한 후 함 #define SIZE 20 ….. #undef SIZE #define SIZE 40 추가
#include <stdio.h> #define PRINT_INT(a) \ printf("The variable '" #a "' contains: %d\n", a); int main (void) { /* Local Declarations */ int legalAge = 21; /* Statements */ PRINT_INT (legalAge); return 0; } /* main */ /* Results: The variable 'legalAge' contains: 21 */ 프로그램 예
조건에 따라 프로그램 일부를 포한시키거나 제외하는 데 사용 #if : 조건식이 참이면 다음에 오는 코드 수행 #endif : 조건식 종료 #else : 조건식이 거짓일 때 수행 #elif : 조건식이 거짓일 때 다음 조건식 지정 #ifdef : 매크로가 #define에 의해 지정되어 있으면 다음 문장 처리 #ifndef : 매크로가 지정되어 있지 않으면 다음 문장 처리 조건부 컴파일
#include <stdio.h> #define DEBUG 1 #define PRINT_INT(a) \ printf("The variable '" #a "' contains: %d\n", a); int main (void) { /* Local Definitions */ int totalScore = 0; /* Statements */ printf("DEBUG is %d\n\n", DEBUG); #if (DEBUG) PRINT_INT (totalScore); #endif printf("\nEnd of Test\n"); return 0; } /* main */ 예I
#include <stdio.h> #define Denver 0 #define Phoenix 0 #define SanJose 1 #define Seattle 0 #if (Denver) /* Denver unique initialization */ #include "Denver.h" #elif (Phoenix) /* Phoenix unique initialization */ #include "Phoenix.h" #elif (SanJose) /* San Jose unique initialization */ #include "SanJose.h" #else /* Seattle unique iniitalization */ #include "Seattle.h" #endif int main (void) { /* Statements */ printf("Does nothing.\n"); return 0; } /* main */ 예II
오류나 일단 쓰지 않는 코드를 제외하려고 하지만 코드에 주석이 있을 때 주석문을 사용하는 코드 일부를 제외 #if 0 /* Locate … */ ….. /* …. */ #endif /* process part */ ….. 코드 제외
프로그램을 수행할 때 일부 명령을 주려고 할 때 ls, ls –l UNIX의 예 sort –r file.dat file.sort argc(argument count)와 argv(argument vector)를 이용함 argv는 string array를 가리키는 포인터 argc는 array 크기(프로그램 이름 포함) 명령 인자
#include <stdio.h> #include <string.h> #include <stdlib.h> int main (int argc, char *argv[]) { /* Local Definitions */ int i; /* Statements */ printf ("The number of user elements: %d\n", argc); printf ("The name of the program: %s\n", argv[0]); for ( i = 1 ; i < argc ; i++ ) printf ("User Value No. %d: %s\n", i, argv[i]); return 0; } /* main */ 예 /*Results: (UNIX) $ PApI-01 "To err is human" Pope The number of user elements: 3 The name of the program: PApI-01 User Value No. 1: To err is human User Value No. 2: Pope $ */
30번 정수에서 특정 비트를 바꾸는 프로그램 bitset(n,b)를 작성하라. 여기서 n은 비트 위치, b는 0또는 1이다. 매크로, 조건부 컴파일, 명령인자가 들어가는 프로그램을 작성하라. 자유로이!!! 실습