[Network Basic] 기본 C 문법 I ~ II

Chapter 01 ~ 02 기본 문법 I ~ II


01 변수와 자료형

필요성 : 이후 네트워크 패킷을 담기 위한 공간을 만들 때 불필요한 공간을 낭비하지 않기 위해 공부한다.

문제 01-01

char, short, int, long, float, double 그리고 포인터의 크기는 얼마일까?

소스 코드

#include <stdio.h>

int main(void)
{
    printf("char \t: %lu\n", (unsigned long)sizeof(char));
    printf("short \t: %lu\n", (unsigned long)sizeof(short));
    printf("int \t: %lu\n", (unsigned long)sizeof(int));
    printf("long \t: %lu\n", (unsigned long)sizeof(long));
    printf("float \t: %lu\n", (unsigned long)sizeof(float));
    printf("double \t: %lu\n", (unsigned long)sizeof(double));
    printf("point \t: %lu\n", (unsigned long)sizeof(void*));

    return 0;
}

출력

char 	: 1
short 	: 2
int 	: 4
long 	: 8
float 	: 4
double 	: 8
point 	: 8
Press <RETURN> to close this window...
Data Type (unsigned long) Size [byte]
char 1 byte [ 00 ]
short 2 byte [ 00 00 ]
int 4 byte [ 00 00 00 00 ]
long 8 byte [ 00 00 00 00 00 00 00 00 ]
float 4 byte [ 00 00 00 00 ]
double 8 byte [ 00 00 00 00 00 00 00 00 ]
POINTER( * ) 8 byte [ 00 00 00 00 00 00 00 00 ]

∗ 실행 운영체제(OS)의 32/64 bit 차이 혹은 컴파일러의 차이 별로 다른 결과를 반환 할 수 있다.

∗ 위와 같은 차이 때문에 버그가 발생할 가능이 있어서 C99에서는 비트 길이를 고유하게 정의한 데이터 형식을 추가하여 헤더 파일 <stdin.h>를 정의하였다.

stdint.h

자료형 비트 바이트 표현 범위
int8_t 8 1 -128 ~ 127
int16_t 16 2 -32,768 ~ 32,767
int32_t 32 4 -2,147,483,648 ~ 2,147,483,647
int64_t 64 8 263 ~ 263 – 1
uint(bit)_t (bit) (bit) / 8 0 ~ 2bit

참고, 위와 같은 자료형은 typedef "기존 자료형" "새로운 자료형" 형식으로 재정의 한 것 이다.

Typedef를 이용한 자료형 재정의

소스 코드

#include <stdio.h>
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int int16_t;
typedef unsigned short int uint16_t;

int main(void)
{
    int8_t a = 1;
    uint8_t b = 2;
    int16_t c = 3;
    uint16_t d= 4;

    printf("int8_t(signed char)\t:%lu\n", (unsigned long)sizeof(a));
    printf("uint8_t(signed char)\t:%lu\n", (unsigned long)sizeof(b));
    printf("int16_t(signed char)\t:%lu\n", (unsigned long)sizeof(c));
    printf("uint16_t(signed char)\t:%lu\n", (unsigned long)sizeof(d));

    return 0;
}

출력

int8_t(signed char)	:1
uint8_t(signed char)	:1
int16_t(signed char)	:2
uint16_t(signed char)	:2
Press <RETURN> to close this window...

02 연산자

대입 연산자, 나머지 연산자, 형변환 연산자, 복합 대입 연산자, 증감 연산자는 패스

비트 연산자

연산자 사용 예 설명
~ ~a 1의 보수 ( 비트 반전 )
& a & b b에 대한 AND 연산
| a | b a와 b에 대한 OR 연산
^ a ^ b a와 b에 대한 XOR 연산
<< a << 1 1비트를 좌측으로 이동
>> a >> 1 1비트를 우측으로 이동

 소스 코드

#include <stdio.h>

int main(void)
{
    int a = 1;
    int b = 2;

    int c = 3;
    unsigned int d = 3;

    printf(" 0x%08x | 0x%08x = 0x%08x\n", a, b, a|b);
    printf(" 0x%08x & 0x%08x = 0x%08x\n", a, b, a|b);
    printf(" 0x%08x ^ 0x%08x = 0x%08x\n", a, b, a|b);
    printf("~0x%08x = 0x%08x\n", a, ~a);

    printf(" signed int : 0x%08x >> 1 = 0x%08x\n", c, c >> 1);
    printf(" signed int : 0x%08x << 1 = 0x%08x\n", c, c << 1);
    printf(" signed int : 0x%08x >> 1 = 0x%08x\n", ~c, ~c >> 1);

    printf(" unsigned int : 0x%08x >> 1 = 0x%08x\n", d, d >> 1);
    printf(" unsigned int : 0x%08x << 1 = 0x%08x\n", d, d << 1);
    printf(" unsigned int : 0x%08x >> 1 = 0x%08x\n", ~d, ~d >> 1);

    return 0;
}

출력

 0x00000001 | 0x00000002 = 0x00000003
 0x00000001 & 0x00000002 = 0x00000003
 0x00000001 ^ 0x00000002 = 0x00000003
~0x00000001 = 0xfffffffe
 signed int : 0x00000003 >> 1 = 0x00000001
 signed int : 0x00000003 << 1 = 0x00000006
 signed int : 0xfffffffc >> 1 = 0xfffffffe
 unsigned int : 0x00000003 >> 1 = 0x00000001
 unsigned int : 0x00000003 << 1 = 0x00000006
 unsigned int : 0xfffffffc >> 1 = 0x7ffffffe
Press <RETURN> to close this window...

03 조건문

if ~ if else ~ else, switch 패스


04 반복문

for, while, do ~ while 패스


05 무한 반복문

for( (초기화) : : (증감) ), while(1) 패스


06 break, continue

break, continue 패스


07 배열

패스


08 문자와 문자열

패스


09 함수

패스


10 기본 함수

printf(), scanf()

specifier 출력 형태
d 부호 있는 10진수 정수(int)
ld 부호 있는 10진수 정수(long)
u 부호 없는 10진수 정수(int)
lu 부호 없는 10진수 정수(unsigned long)
o 부호 없는 8진수 정수
x 부호 없는 16진수 정수
f 부호 있는 10진수 실수
e E 부호 있는 실수 (지수 표시 e/E)
c 단일 문자
s 문자열
p 16진수의 주소 값

 

11 전처리기


01 파일 포함하기

소스 코드

헤더 파일 : sum.h

int sum(int a, int b){
    return a + b;
}

메인 c 파일 : main.c

#include <stdio.h>
#include "sum.h"

int main(void)
{
    int a = 10, b = 20;
    printf("%d + %d = %d\n",a, b, sum(a,b));

    return 0;
}

출력

10 + 20 = 30
Press <RETURN> to close this window...

02 매크로 정의

정의 방법 #define "치환할 내용" "치환될 내용"

소스 코드

#include <stdio.h>
#define BUFMAX  2048
int main(void)
{
    char buffer[BUFMAX];

    printf("BUFMAX : %d\n",BUFMAX);
    printf("buffer size : %lu\n", (unsigned long)sizeof(buffer));

    return 0;
}

출력

BUFMAX : 2048
buffer size : 2048
Press <RETURN> to close this window...

∗ 미리 정의 되어 있는 매크로 목록

매크로 의미
__FILE__ 소스 코드 파일 이름
__LINE__ 현재 소스 코드 라인 번호
__DATE__ 소스 코드가 컴파일 된 날짜
__TIME__ 소스 코드가 컴파일 된 시각
__TIMESTAMP__ 소스 코드가 컴파일 된 타임 스템프

 소스 코드

#include <stdio.h>

int main(void)
{
    printf("__FILE__\t: %s\n",__FILE__);
    printf("__LINE__\t: %d\n", __LINE__);
    printf("__DATE__\t: %s\n",__DATE__);
    printf("__TIME__\t: %s\n",__TIME__);
    printf("__TIMESTAMP__\t: %s\n",__TIMESTAMP__);

    return 0;
}

출력

__FILE__	: ../main.c
__LINE__	: 6
__DATE__	: Aug  1 2016
__TIME__	: 23:49:44
__TIMESTAMP__	: Mon Aug  1 23:49:44 2016
Press <RETURN> to close this window...

03 매크로 함수

매크로 부분에 간단한 함수를 넣어 대체할 수 있으며 한 함수에서 띄어 쓰기는 허용되지 않는다.

소스 코드

#include <stdio.h>

#define MAX(x,y) (x>y)?(x):(y)
#define DOUBLE(x) x*2

int main(void)
{
    printf("MAX(3,5)\t: %d\n",MAX(3,5));
    printf("DOUBLE(5)\t: %d\n",DOUBLE(5));
    printf("DOUBLE(3+2)\t: %d\n",DOUBLE(3+2));

    return 0;
}

출력

MAX(3,5)	: 5
DOUBLE(5)	: 10
DOUBLE(3+2)	: 7
Press <RETURN> to close this window...

∗ 3번째 DOUBLE(3+2)을 보면 10이 아닌 7이 나오는데 define으로 정의된 함수는 단순 치환으로 이루어져 DOUBLE(3+2)는 3+2*2로 계산되어 7이 나오게 된다.


04 매크로 연산자 “#”

매크로에서 “#”은 해당 내용은 “”(따옴표)가 붙어서 치환되고 “##”연산자는 앞 뒤에 내용을 그대로 붙여 코드로 치환 해준다.

소스 코드

#include <stdio.h>

#define PRINT(x) printf(#x "\n")
#define SAVE(name, num, value) name##num = value


int main(void)
{
    int data1 = 0;
    int data2 = 0;

    PRINT(Hello World!);

    SAVE(data, 1, 100);
    SAVE(data, 2, 3);

    printf("data1 : %d\n", data1);
    printf("data2 : %d\n", data2);

    return 0;
}

출력

Hello World!
data1 : 100
data2 : 3
Press <RETURN> to close this window...

∗ 전 처리 전과 후

전 처리 전 전 처리 후
PRINT(Hello World!); printf(“Hello World!” “\n”);
SAVE(data, 1, 100);
SAVE(data, 2, 3);
data1 = 100;
data2 = 3;

05 조건부 컴파일

전처리기 의미
#if 조건
#ifdef 정의되었을 경우
#ifndef 정의되지 않았을 경우
#else 그 외의 경우
#elif 그 외의 조건일 경우
#endif 조건문 전처리기의 끝

∗ 이를 이용해 중복된 헤더의 선언을 막을 수 있다.


사용 도서 정보

제목 : C로 구현하는 네트워크 해킹 프로그래밍

저자 : 강익선

출판사 : 가메출판사

소스 정보 : www.kame.co.kr

공부 기간 : 최대 1주일

 

글의 문제가 있다면 댓글을 달아 주세요.

This site uses Akismet to reduce spam. Learn how your comment data is processed.