본문 바로가기

CERT C

(13)
[CERT C/표현식] (5) NULL 체크의 중요성 의미 NULL은 포인터 변수가 잘못된 주소를 가리키지 않도록 위험성이 없는 0 번지 주소를 가지고 있어서 초기화를 하는 데 많이 쓰이곤 한다. 문자열과 포인터를 배워오면서 NULL의 개념에 대해서는 헷갈릴 수 밖에 없다. NULL 문자 ( \0 ), NULL pointer ( NULL ), NULL string ( "" )의 차이점에 대해서도 알아보자. 표기 설명 NULL 문자 "\0" 문자열의 끝을 의미하는 문자로 아스키 코드 값 '0'이다. NULL pointer NULL 0 번지를 의미하며 대부분 플랫폼에서 Read-Only 영역이나 예약 영역으로 보호받는 주소이다. 그러므로 잘못된 주소를 가리키지 않도록 위험성이 없는 0번지 주소를 가르키도록 초기화를 하는 것이다. NULL string "" 아무..
[CERT C/표현식] (4) 함수 반환 값의 중요성 의미 여러 API와 라이브러리에서 제공해주는 함수의 반환 값은 함수가 작업을 성공 또는 실패했는지를 판단할 수 있는 지표이다. 많은 사람들이 라이브러리를 사용할 때 사용하는 많은 함수들에 리턴값이 있고 그 리턴값들이 의미하는 값들을 처리해주는 것이 프로그램을 작성할 때 매우 중요하다. 동작 방식 man 명령어 (UNIX/LINNUX의 경우) 구글링, document를 통해 함수의 반환값을 확인하고 여러 상황에서 일어날 수 있는 반환값에 대한 처리를 해주어야한다. 문제 코드 1. 함수의 리턴 값을 반드시 확인하자 출력을 예상해보기 #include void myflush(); int main() { int age; printf("Input age : "); scanf("%d", &age); myflush()..
[CERT C/표현식] (3) 포인터 연산 수행의 중요성 의미 포인터 연산은 주소에 대해서 연산을 하는 것을 의미하는데, 포인터에 더해지는 값은 자동적으로 포인터가 가리키는 데이터형으로 조정된다. 동작 방식 포인터 연산의 특징 (1) 주소상수 + 정수형 상수(n) -> 주소 상수 + (n * 주소상수에 해당하는 기억공간의 크기) (2) 주소상수 - 주소상수 -> 주소에 해당하는 기억공간 간의 첨자차이가 된다. 문제 코드 1. 단축 평가 방식을 신경써서 AND, OR 연산자를 사용하자. 출력을 예상해보기 #include #include #include #define BUFFER_SIZE 5 int getNumber(int *); int main() { int p; int buffer[BUFFER_SIZE]; int *bufptr = buffer; while(bu..
[CERT C/표현식] (2) 단축 평가 방식의 중요성 의미 단축 평가(short-circuit evaluation) 방식은 AND와 OR 논리 연산자에서 자주 사용되는 방식으로 첫 번째 피연산자로 평가가 완료되면 두 번째 피연산자는 평가하지 않고 끝내는 평가 방식이다. 동작 방식 연산자 좌측 피연산자 우측 피연산자 AND 거짓인 경우 평가 안함 OR 참인 경우 평가 안함 ※ 첫 번째 피연산자 평가가 완료가 되어서 뒤에 있는 피연산자가 실행되지 않으면서 원하지 않는 동작이 발생할 수 있다. 문제 코드 1. 단축 평가 방식을 신경써서 AND, OR 연산자를 사용하자. 출력을 예상해보기 #include #include #include #define BUF_SIZE 25 int getString(const char *, char **); int main() { i..
[CERT C/표현식] (1) 연산자 우선순위의 중요성 의미 연산자 우선순위란, C 언어에서 사용되는 수 많은 연산자들의 연산 순서를 의미한다. 보통 +, -보다 *, / 가 우선이고 비트 연산자 우선순위 정도까지 생각을 하는 분이 많을 것이라고 생각하는데 우리가 코드에서 보는 모든 기호에 우선순위가 부여되어있고 그 우선순위를 이해하다보면 포인터, 배열 등의 개념의 이해에 큰 도움이 될 것이다. 동작 방식 순위 명칭 연산자 결합방향 1 1차 연산자 () [] . -> -> 2 단항 연산자 + - ! ~ (type) sizeof ++ -- & * 4 가법 연산자 + - 5 Shift 연산자 > 6 관계 연산자 = 7 등가 연산자 == != 8 bit 곱 연산자 & 9 bit 차 연산자 ^ 10 bit 합 연산자 | 11 논리곱 연산자 && 12 논리합 ..
[CERT C/선언과 초기화] (3) 기억클래스 취약성 의미 기억클래스란 변수의 값이 어떤 종류의 메모리에 저장되는지를 지정하는 것을 의미한다. auto, register, static으로 구성되어있다. auto 변수 함수, 블록 내부에서 사용되고 흔희 local 변수라고 불린다. 기억 클래스가 명시되지 않고 선언된 변수는 모두 자동 변수이다. 스택 공간을 사용하며, 함수나 블록에서 기억 영역이 확보되고, 벗어나면 소거됩니다. ** return 문에서 return 되는 값은 외부에서 기억영역을 호가보하게된다. register 변수 CPU가 연산 시 데이터를 임시로 저장하는데 사용하는 작고 빠른 기억장소이다. 2개까지만 선언 가능하고, 초과된 변수는 AUTO 변수로 지정된다. 레지스터에는 주소가 없으므로 참조가 불가능하다. static 변수 프로그램이 종료될 ..
[CERT C/선언과 초기화] (2) 가변인자 함수 사용 시 주의할 점 의미 가변인자 함수는 인자의 개수가 정해지지 않은 함수를 의미한다. 예를들면 printf, scanf 함수가 가변인자 함수이다. int printf(const char*, ...); int scanf(const char*, ...); 동작 방식 상황에 따라 들어오는 인자의 개수가 다르므로 에 정의 되어있는 함수를 이용해서 다룬다. 1. va_list args 가변 인자 목록, 가변 인자의 메모리 주소를 저장하는 포인터이다. va_list : char *형 args : argument를 가리키는 포인터 2. va_start(args, 마지막 고정인수) 가변 인자를 가져올 수 있도록 포인터를 설정한다. 3. va_arg(args, type) 가변 인자 포인터에서 특정 자료형 크기만큼을 가져온다. 4. va_..
[CERT C/선언과 초기화] (1) 코드의 가독성을 높이기 위해 타입 정의를 사용하라 의미 C 언어 같은 경우, 함수 포인터를 이용한 함수들은 타입을 읽을 때 가독성이 떨어지는 경우가 많다. 아래 signal 함수로 예를 들어본다. void(*signal(int signum, void (*handler)(int)))(int) signal 함수를 반환하는 부분과 매개변수 부분으로 나누어보면 (1) signal 함수는 두 개의 파라미터를 가진다. signal(int signum, void (*handler)(int)) (2) signal 함수가 반환하는 값은 void (*)(int); -> 함수 포인터 형이며 반환 값이 없고 int 매개변수를 받는 함수를 가르리키는 포인터이다. 문제 코드 1. 함수의 선언이 읽기도 어렵고 이해하기 힘들다. #include int (*getFunction(in..