거북이와 개구리의 끄적끄적

5일차_C언어(조별과제, 포인터) 본문

공부/팁스

5일차_C언어(조별과제, 포인터)

거북이가개굴개굴 2018. 7. 19. 00:58

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 설명



읽어주셔서 감사하고 강의 정리가 너무 늦어져서 죄송합니다.