일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- c언어 함수
- Tips강좌
- C언어 연산자
- c언어 시프트연산자와 비트연산자
- C언어 문자열
- c언어 static과 const
- Tipssoft
- c언어 포인터와 const 키워드
- c언어 배열
- 지식나눔강좌
- c언어 포인터
- C언어 조건문
- c언어 변수
- c언어 배열과 포인터
- Tips프로그래밍강좌
- C언어 반복문
- 김성엽
- c언어 포인터의 addressing
- c언어 표준출력함수
- c언어 지역변수와 전역변수
- C언어 상수
- c언어 포인터의 캐스팅
- c언어 printf
- c언어 포인터의 주소연산
- C언어 자료형
- c언어 void와 void 포인터
- c언어 2진수 출력
- c언어 표준입력함수
- Today
- Total
거북이와 개구리의 끄적끄적
5일차_C언어(조별과제, 포인터) 본문
5일차_C언어
이 글은 Tips 5일차 강의를 듣고 정리한 내용입니다.
잘못된 내용, 보충할 내용, 궁금한 내용 있으시다면 댓글 달아주시면 감사하겠습니다.
오늘의 목차는 아래와 같습니다.
-조별과제(정수를 2진법으로 출력하는 가장 효율적인 함수 구현)
-포인터
1.조별과제
4일차 강의가 끝나고 각 조별로 정수를 2진법으로 출력하는 과제가 주어졌습니다.
먼저 데이터는 1바이트라 가정하고, 7번비트부터 0번비트까지 순서대로 출력하는 방법을 생각했습니다.
7번비트의 값을 0번비트 위치까지 시프트하고 1과 &연산하게되면 될 것 같아 코드로 구현했습니다.
<시프트연산자와 앤드연산자 활용하기>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* 시프트연산자와 앤드연산자 이용하기 */ /* 1&1은 1이고, 0&1은 0이다. 즉, ?&1은 ?임을 이용 */ #include <stdio.h> void PrintBinary(unsigned char data){ for(int i=7; i>=0; i--) printf("%d", (data>>i) & 1); // 7번비트부터 순서대로 출력. printf("\n"); } int main(){ PrintBinary(0xAb); // 10101011 출력 PrintBinary(30); // 00011110 출력 return 0; } | cs |
시프트연산자와 비트연산자를 사용해도 2진수 출력 함수 구현은 가능합니다.
하지만 시프트 연산자가 앤드연산자보다 빠르므로 시프트 연산과 캐스팅을 이용해 구현해보겠습니다.
<시프트연산자와 캐스팅 사용하기>
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* 시프트연산자와 캐스팅 이용하기 */ #include <stdio.h> void PrintBinary(unsigned char data){ for(int i=0; i<8; i++) printf("%d", (unsigned char)(data << i) >> 7); // (7-i)번 비트부터 순서대로 출력 printf("\n"); } int main(){ PrintBinary(0xAb); // 10101011 출력 PrintBinary(30); // 00011110 출력 return 0; } | cs |
5번째 줄에서 수식을 (data << i) >> 7 이라고 하면 정상작동하지 않습니다.
data << i 의 연산결과는 레지스터에 저장되고, 레지스터는 32비트이므로 오버플로우가 발생하지 않기때문입니다.
따라서 unsigned char로 캐스팅을 해줘야 오버플로우가 발생하며 우리가 원하는 결과를 얻을 수 있습니다.
<시프트연산자만 사용하기>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* 시프트연산자 이용하기 */ /* 레지스터가 32비트임을 이용 */ #include <stdio.h> void PrintBinary(unsigned char data){ for(int i=0; i<8; i++) printf("%u", -((data << (24 + i)) >> 31)); // (7-i)번 비트부터 순서대로 출력 printf("\n"); } int main(){ PrintBinary(0xAb); // 10101011 출력 PrintBinary(30); // 00011110 출력 return 0; } | cs |
레지스터는 위에서 말했듯이 32비트이며, 부호가 있습니다.
따라서 (data << (24+i)) >> 31의 결과는 부호가 있으므로 0 또는 -1이 나오게 됩니다.
그러므로 앞에 -부호를 붙이게 되면 0 또는 1이 나오게 되는것입니다!
<가장 비효율적인 부분을 고치자 : printf>
사실 지금까지 구현한 함수 중 가장 비효율적인 부분은 printf함수가 여러번 호출된다는 점입니다.
그렇다면 printf를 한번만 호출하는 방법은 없을까요?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /* 시프트연산자 이용하기 */ /* 문자열에 저장한 후 8비트를 한번에 출력 */ /* 문자열의 각 요소는 '0' 또는 '1'이여야하고 '1' == '0' + 1이다. */ #include <stdio.h> void PrintBinary(unsigned char data){ char bit_str[9]; for(int i=0; i<8; i++) bit_str[i] = '0' - ((data << (24 + i)) >> 31); // 비트값이 1이면 '0' + 1, 비트값이 0이면 '0' + 0 printf("%s\n", bit_str); // 문자열 } int main(){ PrintBinary(0xAb); // 10101011 출력 PrintBinary(30); // 00011110 출력 return 0; } | cs |
이런식으로 문자열에 각 비트값을 저장한 후 printf의 %s를 이용하면 한번에 출력이 가능합니다!
2.포인터
<포인터란?>
<언제 사용할까?>
함수 호출관계에서 서로 다른 함수의 변수를 사용하려한다면?
스택프레임 때문에 지역변수는 사라짐 -> 포인터 필요
swap 설명
읽어주셔서 감사하고 강의 정리가 너무 늦어져서 죄송합니다.
'공부 > 팁스' 카테고리의 다른 글
7일차_C언어(프로세스와 메모리 모델, 메모리 할당, 다차원 포인터) (0) | 2018.07.24 |
---|---|
6일차_C언어(포인터의 const키워드와 주소연산과 캐스팅과 addressing, 표준입력함수, 배열과 포인터) (0) | 2018.07.19 |
4일차_C언어(시프트연산자와 비트연산자, 지역변수와 전역변수, static과 const, 배열, 문자열) (2) | 2018.07.19 |
3일차_C언어(printf,연산자,제어문[조건문,반복문]) (5) | 2018.07.05 |
2일차_C언어(상수, 변수, 함수, 표준출력함수) (2) | 2018.07.02 |