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주일