반응형
Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
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
Archives
Today
Total
관리 메뉴

테크매니아

'Pointers On C, C 포인터 완벽가이드' 를 읽고 - 1 본문

카테고리 없음

'Pointers On C, C 포인터 완벽가이드' 를 읽고 - 1

SciomageLAB 2024. 9. 18. 08:35
반응형

새로 알게된 용어 및 내용, 잊을 뻔 했던 내용

scanf, gets, fgets

scanf는 지정된 형식지정 맞는 입력만을 읽어들이고 입력 후에 오는 공백문자(스페이스, 탭, 엔터)를 종료로 받아들이기 때문에 앞의 공백문자는 다 무시하고, 뒤의 공백문자는 만나자마자 종료한다. 따라서 공백포함된 문자열은 gets나 fgets를 써서 입력받는다.

그러나 gets의 경우 오로지 문자 포인터 하나만을 받는다. 할당받은 메모리 이상 입력이 오면 프로그램이 중단된다. 무한정 입력받아버리기 때문에.따라서 fgets에서는 포인터와, ?포인터 크기, 입력 스트림 세가지를 인수로 받아서 오버플로우를 방지할 수 있도록 한다. ?여담으로 scanf는 입력 문자열 끝에 입력된 \n 대신에 널문자를 넣어주지만 fgets는 \n문자를 그냥 둔다. 이걸 몰라서 쉘 짤 때, 엄청 해맸다...ㅠ_ㅠ또 쓰다보니 생각난 이슈인데 키보드로 입력시에 입력 버퍼에는 엔터까지 들어간다. 근데 scanf의 %c나 getchar 으로 입력을 받아올 시에는 한문자씩 가져온다. 입력에선 입력마다 \n을 동원하기 때문에 실제로 버퍼에는 2문자가 들어간다. 따라서 a와 b 두개의 문자를 입력했을때

사용자 생각 : a b
버퍼에 들어간 입력 : a \n b \n

위와 같은 차이가 난다. %c와 getchar는 한문자만을 입력함으로

scanf(%c, &a) ; // 또는 a = getchar();
b = getchar(); // 또는 scanf(%c ,&b);

라는 코드에서 컴퓨터는 버퍼는 a와 \n을 읽어오지 a와 b를 읽어오지 않는다. 따라서 버퍼를 비워줘야 하는데 I/O 스트림은 운영체제마다 다른 부분으로 버퍼 비움 함수 역시 운영체제 별로 다르다. 윈도우에선 fflush를 쓰면 되지만 리눅스에서는 fflush가 먹히지 않는다.

사소한 이슈지만, 어떤 플랫폼에서든 독립성을 갖추기 위해 getchar()를 이용한 비움을 할 것인지, 버퍼 비움 함수를 사용할 것인지 선택을 해야될 때도 있기에 알아두는 것이 좋겠다.나는 윈도우 프로그래밍을 하는 경우가 아니면 모든 개발을 리눅스에서 했는데 클라이언트들은 윈도우를 쓰는 경우가 많았다. 그래서 암 생각 없이 fflush를 써서 리눅스 상에서 버퍼 비움이 안되 프로그램이 오작동한 경우가 있었는데 그때 이런 이슈를 알게 되었다.

호스트 환경과 프리스탠딩 환경

호스트 환경과 프리스탠딩 환경의 차이는 운영체제가 있느냐 없느냐의 차이이다. 프리스탠딩 환경의 경우 임베디드 시스템에서 볼 수 있다. 프리스탠딩 환경의 경우 운영체제가 없으므로 프로그래머가 애초에 펌웨어를 직접 ROM에 올리게 된다. 프리스탠딩 환경의 경우 startup routine이 실행에 필요한 인수들을 모아 프로그램에 전달하고 그 후에 main 함수가 구동되는 방식을 취한다.

트라이그래프

특정 문자를 나타내는 일련의 문자들을 나타낸다. C언어에서 사용하는 #, ?\ 등의 ?문자를 해당 시스템에서 지원할 수 없는 경우 저 문자들을 기존에 있는 문자들 조합으로 나타내는 문자조합을 트라이 그래프라고 한다.

궁금해서 비주얼 스튜디오로 찍어봤는데, 범용적인 환경이라 그런지 제대로 출력되었다. 저자가 이런 트라이그래프를 고려하지 않는 코드를 작성하지 말라고 그랬으나 책은 2004년도에 발행한 책이었고 난 2017년에 보고 쓰고 있으니 트라이그래프를 신경쓸 만한 환경이 아예 없을것이다 라고는 할 수 없지만 중요해 보이지 않았다.

mnemonic value

'인간이 암기하기 쉬운 형태로 간략화한 코드'. 시스템 프로그래밍이나 어셈블리어 파트를 보면 등장하는 단어이기도 한데, 가령 001011 바이너리 코드가 분기 명령을 수행하는 코드라면 jmp 라고 알기 쉽도록 정하는 것을 말한다. jmp가 001011의 니모닉이 된다.

Token

토큰은 언어공부하면서, 네트워크 공부하면서 들었던 단어였는데 먼저 언어에서 사용되는 뜻은 더이상 문법적으로 분리 불가능한 요소를 말한다.

키워드, 구두점, 연산자 등이 될 수 있다.?쉘을 짜면서 접했었던 개념이었다. 쉘에서 유저가 넘긴 인수들을 명령어, 옵션 단위로 잘라 맞는 함수를 호출을 하려면 토큰나이징 함수를 만들어야 했었다.이 단어는 3학년 네트워크 시간에도 공부했었는데 네트워크 공부하면서 네트워크 모델에 관련된 파트에서 등장했다. 외부에서 들어오는 하나의 WAN을 LAN영역에서 여러명이 물어서 쓸 때, 동시 다발로 전송 요청을 보낸다면 충돌이 일어난다. 따라서 특정 시점에는 한명만 네트워크를 I/O해야 하는데 이를 해결하기 위한 여러 네트워크 모델이 존재한다. 그 중의 하나가 '토큰링 모델'로 하나의 토큰을 권한처럼 사용하여 여러명이 네트워크를 나눠쓰는 방식이다. 오직 토큰을 가진 한명만이 네트워크를 쓸 수 있고 사용이 끝난 사용자는 토큰을 다음 사용자에게 넘겨주는 방식이다.

Monocase & Case Sensitive

  • Case Sensitive : 대소문자를 구분한다.
  • Monocase : 대문자와 소문자를 동일하게 하나로 처리한다.\ddd 와 \xddd ddd는 3자리의 숫자를 나타내며 각각 8진수, 16진수로 표시된 문자를 출력한다.- ex) printf(\40); 라는 코드는 @을 출력한다.

새로 알게된 코딩 관습

  • 조건문 ( 조건식 ) , 함수원형 ( 매개변수 )과 같이 조건문과 조건식은 분리되어야 한다.저자가 얘기하길 조건문에 쓰이는 괄호는 조건식에 포함된 문장이 아니므로 조건문의 괄호와 조건식은 공백을 이용해 분리해야한다고 한다. 함수 원형 또한 마찬가지이다. 코딩을 일반 프로그램만 했을땐 몰랐는데, 수치를 많이 다루는 프로그램을 할 때 조건식이 복잡하거나 수식을 많이 쓰는 프로그램의 경우 () 안이 복잡해져 가독성이 떨어졌어서 일부러 띄어쓰긴했었다. 새로운 알게된 규칙이라기 보다 저자도 이런 추천을 하는게 반가웠던 관습이었다.

포인터 문자열 출력

char *p;
p = (char*)malloc(20);
scanf(%s, p);
printf(%s, p);
free(p);</span>

위 코드에서 p는 포인터로 어떤 주소값을 가지고 있다. 따라서 scanf는 주소에 쓰는 함수이므 3번째 라인은 맞다고 생각했다.그런데 4번째 라인에서는 p가 가지고 있는 것이 주소라 *p를 써야 한다고 생각했었는데 출력을 제대로 하기 위해선 p를 써야 했었다. 이유는 %s 는 주소값을 받아들이기 때문이란다. 다시 왜그런지 잘 생각해보니, 문자열을 표현하는 문자열 상수와, 문자 배열 모두 널문자가 나올 때까지 짚어가야 하는데, 이는 시작 메모리 주소를 알아야 가능한 것이므로 당연히 주소로 접근해야 할 것 같다.

흥미 있었던 프로그램

연습 문제로 C코드를 읽어들여 {}일치 프로그램을 작성하는 문제가 있었다.

#include<stdio.h>
#include<stdlib.h>

// 카운터를 이용한 괄호 쌍 매치
int main(void)
{
    int ch = 0, braces = 0;

    printf(check braces match. enter ther code then press enter\n\n);
    while ((ch = getchar()) != '\n')
    {
        // 열린 괄호 체크
        if (ch == '{')
            braces++;

        // 닫힌 괄호 체크
        if (ch == '}')
            if (braces == 0) // 뒤 괄호는 앞 괄호가 있을 때 유효
                printf(extra closing brace!!\n);
            else 
                braces--;
    }

    if (braces > 0)
         printf(%d unmatched\n, braces);

    return EXIT_SUCCESS;
}

처음에 무식하게 열린 괄호와 닫힌 괄호를 각각 다른 배열로 넣고 비교할라 그랬는데 더 간단하게 카운터를 이용해서 구현하는 방법을 책에서 보았다. 위 코드가 카운터 이용 방식인데 별건 아니지만 나중에 써먹을 일이 있을 것 같다. 주석, 괄호 매칭이 컴파일러 제작에서 쓰이지 않을까 한다.

반응형