main 함수 해부하기 - 문자와 문자열

main 함수의 두번째 전달인자의 "*"가 포인터를 위한 코드라는 것, 공부했지요?
이번 강의에서는, 두번째 전달인자에서 볼 수 있는 "char *"가 어떻게 사용되는지에 대하여 조금 더 확장해서 알아볼게요.



강의들은 모두 무료입니다. 단, 저작권은 키클 코딩랩 에 있으며, 무단 복제 및 배포를 엄금합니다.
이를 어길 시, 본 사이트의 서버가 미국에 있으므로, 미국법에 의해 처벌될 수도 있습니다.




문자열 (String of characters)

원하는 폴더/디렉토리를 만들고 gedit 문서 편집기를 이용하여 "lec9_main.c"라는 이름의 C 파일을 만들어 볼게요. 그리고, 아래 줄1처럼 stdio.h을 포함시키고, 이어서 main() 함수의 골격을 코딩해 보지요.

lec9_main.c
#include <stdio.h>

int main (int argc, char *argv[ ]) {

}

줄1에서 표준입출력 라이브러리의 헤더파일(stdio.h)을 포함시킨 것은 나중에 printf 함수를 이용하기 위함이지요.
줄3에서 main() 함수의 두번째 전달인자가 "char *argv[ ]"라고 되어 있는 것은 이제 익숙하지요? "char"가 문자형 데이터타입을 의미하고 "argv"는 그저 전달인자 변수 이름이고 "[ ]"는 배열을 의미하고 "*"는 "char"와 함께 쓰여 "문자형 포인터(Pointer) 데이터타입"을 의미한다는 것, 이것들 모두 지금까지 공부해 온 것이지요?
그렇다면, 이제는 "char *"의 사용법에 대하여 한가지 더 알아보려고 하는데요, 문자형 포인터(Pointer) 데이터타입 "char *"은 문자열의 선언을 위해서도 사용될 수 있다는 것이랍니다.
"문자열"은 강의 main 함수 실행하기에서 printf()를 처음 공부할 때 간략하게 설명한 적이 있는데요, 조금 더 자세히 공부해 보지요.

[문법] 문자열 (String of characters)





문자와 문자열 코딩하기

문자열의 선언에 대해서 공부해 봤으니, 이제 직접 코딩하면서 공부한 내용을 확인해 볼게요. 문자와 문자열을 함께 코딩하면서, 두 가지의 공통점과 차이점을 눈여겨 보도록 하세요.
아래 줄4~줄10처럼 main() 함수 안에 코드를 추가해 보세요.

lec9_main.c
#include <stdio.h>

int main (int argc, char *argv[ ]) {
	char mychar = 'c';
	char *p_mychar = &mychar;
	char *mystr1 = "efg"; 

	printf("mychar=%c\n", *p_mychar);
	printf("value of null character=%d\n", '\0');
	printf("The first character of mystr1=%c\n", *mystr1);
	printf("The whole mystr1=%s\n", mystr1);
}

줄4는 mychar라는 문자형 변수를 선언하고 문자 'c'를 할당하면서 초기화했어요.
줄5는 p_mychar라는 문자형 포인터 변수(즉, 어떤 문자형 변수가 차지하는 메모리의 주소를 저장하는 변수)에 줄4에서 선언한 mychar의 메모리 주소를 할당하면서 초기화 했어요.
줄6에서는, 문자형 포인터 변수 mystr1에 "efg"라는 문자열을 할당하고 있지요. 앞에서 공부했던 것처럼, 문자열을 생성하기 위해서 쌍따옴표 " "를 이용했지요. 그리고, 역시 앞에서 공부했듯이, 문자열은 할당할 때, 맨 앞 문자의 메모리 주소를 반환하므로, 변수 mystr1에는 문자 'e'가 차지하는 메모리의 주소값이 저장되어 있겠죠.

줄8에서는, * 포인터 연산자를 이용하여 p_mychar에 저장되어 있는 주소가 가리키는 메모리(크기는 문자형이니 1바이트이지요)에 접근하고 그 안에 있는 'c'를 출력하고 있지요. 문자를 출력하기 때문에 format specifier(서식 지정자)로 %c를 이용했다는 것 잊지마세요.
줄9에서는 null character(널 문자) '\0'의 ASCII Code를 출력해서 그 값이 정말 0인지 확인하고자 해요. ASCII Code 값은 정수형이기 때문에 서식지정자는 %d를 사용했답니다.
줄10에서는, * 포인터 연산자를 이용하여 mystr1에 저장되어 있는 주소가 가리키는 메모리(크기는 문자형이니 1바이트이지요)에 접근하고 그 안의 내용을 출력하고자 해요. 그런데, 변수 mystr1에는 문자열의 맨 처음 문자인 'e'가 저장되어 있는 메모리의 주소가 저장된다고 했지요? 그러므로, *mystr1를 통해서 출력되는 것은 문자열 "efg"가 아닌, 문자 'e'가 된답니다. 그래서, 서식지정자도 %c를 사용했지요.

그렇다면, 문자열 "efg"는 어떻게 출력하느냐? 줄11에서 그 답을 알려주고 있어요. 문자열을 출력할 때에는, 그저 문자열의 맨 처음 문자가 저장되어 있는 메모리의 주소를 전해 주면 된답니다. 그래서, 줄10처럼 * 포인터 연산자 없이, mystr1만 printf()에 전달해 주고 있는 것이지요. 그렇다면, 문자열의 맨 처음 문자가 저장되어 있는 메모리의 주소만 전달해 주는데, 어떻게 문자열 "efg" 전체를 출력하느냐? 바로, 서식지정자 %s를 사용하기 때문이랍니다. 서식화된 문자열(formatted string)에 서식지정자 %s가 있으면, printf() 함수는 %s에 대응하는 변수인 mystr1에 저장된 메모리 주소가 가리키는 메모리에서부터 시작하여 널문자(\0)를 만날때까지 연속되어 저장된 문자들을 하나씩 읽어 온답니다. 그리고, 널문자(\0)를 만나기 직전까지 읽었던 문자들의 모임, 즉, 문자열 "efg",을 %s의 위치에 삽입하게 되는 것이죠.





컴파일 후 실행하기

이제, 강의 첫 대면..main 함수에서 했던 것처럼, 파일을 저장하고 gedit 편집기 닫기를 하세요.
그리고, 아래 줄1처럼 터미널에서 "gcc lec9_main.c"을 실행하여 컴파일하세요.

.../my_folder$ gcc lec9_main.c
.../my_folder$ ls
a.out  lec9_main.c
.../my_folder$

컴파일이 잘 되었다면, 줄2에서처럼 터미널 명령어 ls를 실행하면, 줄3에서처럼, a.out이라는 실행파일이 생성된 것을 볼 수 있지요.

이제, 아래 줄3처럼 "./a.out"라고 명령하여 프로그램을 실행하면, 줄4~줄7과 같은 출력 결과를 얻을 수 있답니다. 출력 결과들이 모두 위에서 예상했던 것과 같은 것을 확인할 수 있지요.

.../my_folder$ ls
a.out  lec9_main.c
.../my_folder$ ./a.out
mychar=c
value of null character=0
The first character of mystr1=e
The whole mystr1=efg
.../my_folder$

강의에서 작성된 소스 코드 (source code)를 다운받으려면, 다음 링크를 클릭하세요: lec9_main.c

혹시, 이해가 잘 안되는 부분에 대한 질문이 있거나 다루어 줬으면 하는 주제가 있으면, 화면 오른쪽 하단에 "질문하기" 버튼을 이용해 주세요.






발자취

2019-09-11 "키클 코딩랩 - 미국 공학박사 아빠의 코딩 연구소"로 이름 변경
2019-06-28 코딩 교실 공개
2019-03-18 코딩 교실 제작 시작

바로가기
Python 배움터
C/C++ 배움터
About
Contact
Privacy Policy
강의목록
질문하기
처음으로