[C] 정리 (2)
C에서 문자열을 다룰 때는 char타입의 배열을 사용하고, 배열의 마지막에는 문자열의 끝을 의미하는 \0 (널 문자)가 들어간다.
즉, char배열의 크기와 문자열의 길이는 다를 수 있다. 널 문자를 적절히 사용해 문자열을 효과적으로 다루자.
-
scanf를 사용해 문자열을 저장할 때 배열의 최대치를 넘어가는 경우를 방지하기 위해 "%48s"처럼 최대 몇 글자까지만 입력하라는 제한을 설정할 수 있다.
-
gets()와 puts()를 통해 문자열만을 입력받고 출력받을 수 있다,
줄 단위로 입력받고 줄 단위로 출력받을 수 있어 공백이나 탭을 문자열에 포함할 수 있다.
gets 대신 fgets를 사용해 배열의 크기를 초과하지 않도록 설정할 수 있다.
-
모든 배열은 1차원배열로 생각될 수 있고, 모든 요소가 연속적으로 분포되어있다.
다차원 배열에서 제일 높은 차원의 길이는 생략할 수 있다.
-
문자열 배열은 2차원의 char타입 배열로 구현할 수 있고, 2차원 문자열 배열은 3차원 char타입 배열로 구현할 수 있다.
-
함수 내부에서 선언된 변수들은 그 함수 내부에서만 사용할 수 있다. (지역변수)
C의 컴파일러는 위에서 아래로 한번만 읽기 때문에 함수의 선언부가 함수의 호출보다 앞서야 한다.
-
함수를 호출할 때 사용하는 값들을 인수(argument), 함수를 선언할 때 사용하는 값들을 매개변수(parameter)라고 한다.
-
표준 라이브러리의 헤더파일은 <>로 처리하고, 기 외 사용자가 정의한 헤더파일은 ""로 처리한다.
<> 와 "" 안에는 경로를 붙여 준다.
-
#은 전처리기 지시자로, 컴파일 직전에 수행된다. include 혹은 define에 사용된다.
-
지역변수는 {} 블럭 안에서만 유효하고, 중첩된 변수에서는 가장 가까운 블럭이 우선한다.
정적 변수는 전역변수와 같은 특징을 가지지만, 유효범위만 자신이 선언된 소스파일 내부이다. (전역변수보다 좁음)
다중 소스파일 환경에서는 차이가 발생하지만, 단일 소스파일로 이루어진 프로그램에서는 차이가 없다.
정적 변수를 함수 내부에 선언한 경우, 프로그램이 시작될 때 한 번만 초기화 되고, 그 함수의 끝까지 유효한 성질을 지니게 된다. 즉, 유효 범위를 줄이기 위해서 사용됐다.
-
typedef는 기존의 타입을 새로운 이름으로 정의할 수 있도록 해 준다.
struct와 함께 사용해 구조체를 간결하게 사용한다.
-
포인터는 값을 위한 저장공간의 주소이다.
이 때 주소는 저장된 범위의 시작 주소를 의미한다.
포인터 타입의 크기는 4바이트이다. (부호 없는 정수 타입과 같다)
-
포인터 타입의 변수에 부호 없는 정수를 저장할 수 있지만, 운영체제의 입장에서 매우 위험하다.
포인터를 기본형으로 변환하는건 괜찮다.
-
포인터도 변수이기에, 포인터가 다른 포인터를 가리키게 할 수 있다.
포인터의 포인터를 사용하는 대신 포인터를 하나만 사용하도록 할 수 있지만, 이 경우 * 연산자를 한 번만 사용할 수 있다.
즉, * 연산을 여러 번 수행하려고 포인터의 포인터의 포인터의 포인터의 포인터의... 포인터를 사용한다.
-
int const * ptr , const int * ptr // *ptr변수를 변경할 수 없다. *ptr = 200 불가능!
int* const ptr // 포인터가 다른 대상을 가리킬 수 없다. ptr++ 불가능!
*ptr++ 는 *ptr -> ptr++ 와 같다.
원하는 값만큼 연산하려면 char*타입으로 형변환 후 진행하기.
-
포인터가 같다는건, 가리키는 대상이 같다는 것을 의미한다.
[i]연산자는 배열 연산자로, i만큼 떨어진 요소에 저장된 값을 반환하는 역할을 한다.
즉, 포인터에서도 사용할 수 있다.
-
메모리 주소는 변경할 수 없고, 메모리 저장공간은 변경할 수 있다.
-
void포인터는 타입이 정해져 있지 않음을 의미. 어떤 종류의 포인터의 값도 형변환 없이 대입할 수 있다.
함수에 배열을 사용할 때는 포인터를 대신해서 사용하는 편이 합리적이다. (리턴 타입도 마찬가지)
-
동적할당은 메모리를 효율적으로 사용하는 대신, 반대급부로 시간지연이 발생해 성능이 떨어질 수 있다.
동적으로 할당받은 저장공간에는 포인터를 통해서만 접근할 수 있다.
-
동적할당 후 free로 할당을 해제하면 해당하는 포인터는 댕글링 포인터라고 한다. (dangling pointer)
그러니 free함수를 실행한 후에는 해당 포인터를 NULL로 초기화하도록 하자.
배열의 배열 형태로 할당받으면 각 요소들을 먼저 해제한 후 배열을 해제해야 한다.
-
calloc은 malloc으로 동적할당 후 요소를 0으로 초기화 해 준 것과 같다.
크기를 늘릴 때 realloc을 사용하면 malloc을 사용할 때 보다 편리하다.
-
함수의 주소를 가리키는 변수를 함수 포인터라고 한다.
int add(int a, int b) { ... } -> int (*asdf) (int, int) = add 와 같이 사용한다. (함수의 이름도 상수이다.)
함수 포인터를 호출할 때는 *연산자를 써도 되고 안써도 된다.
함수 포인터 역시 형변환이 가능하고, 방법은 포인터에서와 같다.
함수 포인터는 타입이 같은 함수들을 자유롭게 처리할 수 있어서 편리하다. 배열로 묶어서 사용할 때 효과적이다.
-
구조체에 대한 포인터도 존재한다. 일반 포인터와 동일한 방법으로 다룰 수 있다.
포인터로 구조체의 멤버에 접근할 경우는 (*p).kor 로 사용한다. ( *p.kor == *(p.kor) 이다. )
간단하게 사용하려면 p->kor 로 사용할 수 있다. ( .와 ->는 *과 &보다 우선순위가 높다)
-
구조체의 멤버로 다른 구조체를 가질 수는 있지만, 자기 자신을 구조체로 가지는 건 불가능하다.
하지만, 자기 자신 타입의 포인터를 멤버로 가질 수는 있다. (이유는 메모리 할당 이슈)
링크드리스트를 구현할 때 사용된다.
-
함수에서 함수 내부에 선언된 구조체 변수의 주소를 반환하는건 문제가 된다. (사라지니까)
하지만 구조체 자체르르 반환하는건 문제가 되지 않는다. 복사된다고 생각하면 된다.
'Programming Language > C' 카테고리의 다른 글
[C] typedef / Union (0) | 2022.05.26 |
---|---|
[C] 구조체 (0) | 2022.05.26 |
[C] 동적 메모리 (0) | 2022.05.23 |
[C] Stack / Heap (0) | 2022.05.23 |
[C] 배열 포인터 / 포인터 배열 정리 (0) | 2022.05.11 |
댓글
이 글 공유하기
다른 글
-
[C] typedef / Union
[C] typedef / Union
2022.05.26 -
[C] 구조체
[C] 구조체
2022.05.26 -
[C] 동적 메모리
[C] 동적 메모리
2022.05.23 -
[C] Stack / Heap
[C] Stack / Heap
2022.05.23