C

    [C] 함수의 포인터 / 배열 매개변수

    함수의 매개변수로 배열 사용법 배열을 함수의 전달 인자로 사용하려면 배열의 변수명은 첫 번째 원소의 주소값이기 때문에 매개변수의 타입은 포인터가 되어야 한다. void 함수명(int* arr) { } 둘 다 동일한 의미를 지닌다 void 함수명(int* arr) { } void 함수명(int arr[]) { } #include #define Size 10 void Arrprint(int *Arr); void Arrprint2(int Arr[]); int main () { int i_arr[Size] = {1,2,3,4,5,6,7,8,9,10}; Arrprint(i_arr); Arrprint2(i_arr); return 0; } void Arrprint(int *Arr){ for(int i = 0; i

    [C] 복합 대입 / 증감 연산자

    복합 대입 연산자와 증감 연산자는 연산식을 간단하게 표현할 수 있는 특별한 연산자다. #include int main () { int a = 3, b = 2; printf ( "%d %d \n", ++a, b–); a + 1; b -= 1; printf ( "%d %d \n", a, b); } 4행에서 정수형 변수 a와 b를 선언하고, 각각 3과 2로 초기화한다. 5행에서 a의 값을 1만큼 증가시키는 연산자 ‘++’에 의해 a의 값이 4가 된다. 그러나 b의 값을 1만큼 감소시키는 연산자’–‘는 다음 번 b의 값을 이용할 때까지 연산을 보류시킨다. 6행에서 ‘a+=1’은 a값을 1만큼 증가시키는 ‘a=a+1’을 줄인 표현이며, ‘b-=1’도 b 값을 1만큼 감소시키는 ‘b=b-1’을 줄인 표현이다. 따라..

    [C] 버퍼 오버플로 (buffer overflow)

    프로그램이 데이터를 버퍼(buffer)에 저장할 때, 버퍼가 가득 차 넘치게 되어 프로그래머가 지정한 부분 바깥에 덮어 씌워버리는 취약점, 버그, 이를 이용한 공격 방법을 말한다. 넘쳐난 데이터는 원래 데이터를 밀어내거나 이상한 곳에 저장하는 것이 아니라 덮어 씌우는 것이다. 덮어 씌워진 메모리에는 다른 데이터가 이미 포함되어 있을 수 있고, 이 때문에 메모리 접근 오류, 프로그램 종료, 시스템 보안 취약점 등이 발생할 수 있다. 버퍼 오버플로는 보통 데이터를 저장하는 과정에서 그 데이터를 저장할 메모리 위치가 유효한지를 검사하지 않아 발생한다. 이러한 경우 데이터가 담긴 위치 근처에 있는 값이 손상되고 그 손상이 프로그램 실행에 영향을 미칠 수도 있다. 특히, 악의적인 공격으로 인해 프로그램에 취약점이..

    [C/C++] 메모리 오류에 대하여

    1. C/C++에서 메모리 오류의 종류 일단 메모리 공간에 따라 크게 Heap Memory 에러와 Stack (local variables) Memory 에러가 있다. Heap 메모리 영역에서 발생가능한 에러는 이미 해제된 메모리 다시 해제 할때 할당된적도 없는 메모리 해제 할라고 할때 이미 해제된 메모리 영역에 뭔가 데이터를 쓰려고 할때 할당된 적이 없는 메모리에 뭔가 데이터를 쓰려고 할때 메모리 할당 에러 동적으로 할당된 메모리 배열에서 초과된 index의 위치를 읽거나 쓰려고 할때 1,2 번과 3,4번을 묶어서 볼 수 있는데 해제시에 발생하는 문제 vs 데이터 입력시 발생하는 문제로 볼 수 있다. 스택 메모리 영역에서 발생가능한 에러들로는 정적 배열에서 초과된 index의 위치를 읽거나 쓰려고 할때..

    [C] 함수 포인터 사용법 & 예제 총 정리

    함수의 주소 변수를 선언하면 메모리 공간이 할당되고 그 공간의 위치가 주소로 존재하듯이 함수를 선언해도 변수와 마찬가지로 메모리에 공간이 할당되며 그 위치를 표현하는 주소가 생겨난다. C언어 코드는 컴파일이 되면 기계어로 변경되고 프로그램이 실행되면 코드 세그먼트라는 메모리 영역에 위치하게 된다. 즉, 함수의 형태는 변경되겠지만 결국 메모리에 저장되기 때문에 주소를 가지게 된다는 의미다. #include void print_hello() { printf("Hello, world!\n"); } int main() { // 메모리 상에 저장된 함수의 주소값 printf("함수의 주소값 : %p\n", print_hello); // & 생략 가능 return 0; } 포인터 변수란? 위에서 설명했듯 포인터는 ..

    [C] 쓰레기값과 초기화

    쓰레기 값이란? C언어에서 변수를 선언하면 어떠한 메모리 공간을 할당받는 것이다. 그렇다면 그 메모리 공간 안의 상황은 할당받을 당시 어떤 상황일까? 어디서 어떠한 의도로 그 메모리 공간이 사용되고 있었는지 모르기 때문에 그 안에는 의미 없는 값이 들어가 있는데 이러한 값들을 바로 쓰레기 값이라고 한다. 실제로 쓰레기 값이 들어있는지 한번 확인해 보도록 하자 int main() { int a; printf("%d\n", a); return 0; } 다음과 같은 에러가 발생한다. 왜 쓰레기 값이 존재하는가? 사용자들이 생각하기에는 그렇다면 변수를 선언과 동시에 초기화를 시킨다면 쓰레기값이 없을 텐데 왜 C언어에서는 그런 방향을 만들지 않았을까 하는 의문이 생길 수 있습. 이 이유는 연산의 증가가 발생하기 ..

    [C] gets 함수는 사용하지 말아야 한다.

    프로그래밍을 하는 고수 프로그래머의 대부분(아니 거의 전부) 는 다들 gets 함수를 사용하지 말라고 조언한다. 그 이유에 대해서 1988년 엄청난 피해를 입혔던 모리스 웜(Morris Worm) 에 대해 언급하고자 한다. 컴퓨터 해킹의 역사에서 엄청나게 굵고 큰 한 획을 그었던 Morris Worm 의 컴퓨터 파괴 원리는 바로 버퍼 오버플로우이다. 요즘의 언어인 JAVA나 Python 같은 언어는 메모리를 자체적으로 관리하기 때문에 버퍼 오버플로우에 대해서는 안전할 수 있겠지만, 프로그래머에게 엄청난 자유를 선사하는 어셈블리어, C, C++ 등은 시스템에 매우 밀접하게 동작하므로 버퍼 오버플로우에 대한 고려를 프로그래머가 직접 해야 한다. Morris Worm은 바로 C 언어의 표준 함수 중 버퍼 오버..

    [C] 서식 지정자의 모든것 (서식문자)

    서식 지정자란? printf, scanf, sprintf, fprintf 등의 여러 API 에서 가변인자를 받아서 처리하기 위한 데이터 포맷이다. 가변인자를 처리하는 API 함수 내부에서 어떤 인자를 어떤식으로 처리할지 지정하기 위해서 사용한다. 여러 API 에서 가변인자를 서식 지정자를 통해 처리하는데 printf 와 scanf 만 비교해봐도 서식 지정자로 특정할 수 있는 자료형의 스펙이 조금씩 다르다. printf 는 타입을 전달받아 데이터를 출력하기 때문에 형변환(type casting) 및 형승격(type promotion) 을 통해 크기가 다른 타입에 대해서 유연한 메모리 처리가 가능하지만, scanf 는 포인터를 전달받아 입력받은 데이터를 저장하기 때문에 서식 지정자에 의존하여 메모리 처리를 ..

    [C] min max 매크로함수

    1. The old C macro way 매크로 원형 /* min */ #define min(a, b) (((a) (b)) ? (a) : (b)) 단점 : double-evaluation side effect 발생 /* Input */ #include #define min(a, b) (((a) (b)) ? (a) : (b)) int main(int argc, char * argv[]) { int a = 2, b = 3; printf("%d\n", min(a, b)); printf("a : %d b : %d\n\n", a, b..

    [C] 문자열에서 공백을 제거하는 함수

    문자열 중앙에 있는 공백도 제거하는 함수가 필요해서 만들었다. 아래의 DeleteSpace함수는 인수로 받는 문자열에서 문자열에서 앞, 뒤, 가운데에 있는 모든 공백을 제거해서 제거된 문자열을 반환하는 함수다. 사용법: char *str = DeleteSpace("공백이 있는 문자열"); char str[] = DeleteSpace("공백이 있는 문자열"); #include #include char* DeleteSpace(char s[]) { char* str = (char*)malloc(sizeof(s)); int i, k = 0; for (i = 0; i < strlen(s); i++) if (s[i] != ' ') str[k++] = s[i]; str[k] = '\0'; return str; } i..