정말 오랜만에 C로 코딩을 해보는 것 같다.
2005년도에 1달 잠깐 배우고서... 2009년인 지금까지 C++은 써왔어도.. C를 거의 안써왔기에.. 오랜만에 Report가 C언어로 출제된 것이 있어서 C로 필요한 코딩을 하는 중이었다.
문제는 Parameter Passing.
이게 참... 아리송한 것이 클래스의 개념을 배운 뒤로는 구조체에 대한 것을 거~의 잊고 있었다.
솔직히 구조체로 사용할 것이 있으면 클래스로 만드는 편이 아무래도 모듈의 독립성이나 구현의 편의성이 더 좋기에 구조체를 거의 안 써왔던 것이 사실이다. 그러다보니 일.부.로 구조체를 사용하려니(그것도 생각도 안하고 그냥 막 구현하려니...) 잘 될리가 있나.
정말 짜증나는 Runtime Error가 계속 뜨는 것이다.
printf문으로 각 변수가 참조하는 메모리 주소를 꼼꼼하게 체크해보니 포인터를 구조체 안에 char형 포인터를 선언해두고 구조체 밖에서 초기화를 리터럴 상수를 이용해서 했다.
예를 들자면...
struct a
{
char *c;
};
....
main()
{
a.c = "abcde";
}
이런 식으로 구조체의 멤버변수를 초기화를 했는 데, 출력은 아주 잘 되었다. 그래서 나는 아무런 의심조차 하지 않고 다음 단계로 넘어갔다.
프로그래밍언어의 parameter passing에 대한 Report라서, Call by Value로 다른 함수에 넘기고서 구조체 멤버변수의 char형의 문자값들의 위치를 변동시키려고 하니 compile Error는 발생하지 않는데, 실행 중에 자꾸 에러가 뜨는 것이다.
예를 들자면...
main()
{
...
a.c = "abcde";
...
sub(a);
}
sub(a value)
{
value.c[0] = "G";
...
}
이런 식으로 구조체의 멤버변수 중 char형 포인터가 가리키는 메모리의 값을 바꾸려고 한 것이었는데, 원인을 몰라 printf문으로 각 변수가 위치한 메모리의 주소를 체크해보니 분명히 sub로 넘긴 value는 a라는 구조체의 copy본 일텐데(왜냐하면 parameter passing을 call by value로 하였기에..), 이상하게도 a.c나 value.c나 같은 위치를 참조하고 있는 것이 아닌가? 그래서 담배를 피면서 곰곰히 생각을 해보니...
아주 간단한 문제였다.
char *abc = "simplism";
이런 방식으로 문자열을 저장하면, 위의 simplism이라는 문자열은 컴파일러가 메모리의 임의위치에
리터럴 상수로 배정하고서 포인터로 연결을 하는 것이다. 하지만 이것은 상수이기에 값에 변화를 줄 수 없는 것이다. 그래서
값에 변화를 주려고 하니 실행시간(runtime)에 에러가 발생하는 것이다.
아주 기초 중의 기초적인 문제였는데, 코딩 상의 편의와 문자열 저장을 위한 배열의 사이즈를 고정시키지 않기 위해서 포인터를 이용했겄만 깊게 생각하지 않은 죄값으로 아까운 시간만 낭비한 셈이 되었다. 이 Report자체는 어려운 것이 없는데, Report를 작성하는 과정 동안 나 자신의 코딩에 대한 기초적인 지식이 부족하다는 것을 깨닳게 해준 것 같다.
결국 배열의 사이즈를 고정하는 매크로를 하나 만들고, 고정사이즈 배열로 구조체 멤버변수를 선언한 뒤에 하니 잘 작동한다.
앞으로 계속 C/C++을 해야할텐데, 군대에 다녀온 2년간 꼭꼭 숨어버린 언어에 대한 기초지식을 조금 불러와야겠다.