본문 바로가기

C 스타일의 문자열 기호적 상수 (C-style string symbolic constants) 본문

💘 C++/행렬, 문자열, 포인터, 참조

C 스타일의 문자열 기호적 상수 (C-style string symbolic constants)

Hyonii 2022. 7. 11. 13:52

문자열 기호적 상수 (C-style string symbolic constants)

지난 포스팅에서 C 스타일 문자열을 만들고 초기화하는 방법에 대해 배웠다. 

 

"Hyoni Hyoni"라는 문자열을 name이라는 배열에 넣어주고 있다.

그렇다면 이전에 array 하고 포인터는 호환이 된다고 했으니까 이렇게 해도 될까?

이렇게 하면 아예 빌드가 되지 않는다.

왜냐하면 오른쪽에 있는 "Hyoni Hyoni"는 리터럴이고 왼쪽에 있는 것은 그냥 only 포인터다.

실제로 리터럴이 담길 메모리를 어디서 만들 것인가에 대한 아무런 정보가 없다.

포인터를 사용하실 때 주의해야 할 개념 중 하나이다.

 "Hyoni Hyoni"는 리터럴이라서 임시로 어딘가에 잠깐 담길 수는 있겠지만

이걸 배열에 담는 것도, 변수에 담는 것도 아니다.

포인터는 메모리의 주소만 가리키기만 하니까 포인터에도 담을 수 없다.

 

C++은 또한 포인터를 이용해서 C스타일 문자열 기호 상수를 만드는 방법도 지원한다.

 

그럼에도 불구하고  "Hyoni Hyoni"라는 리터럴을 기호적인 상수처럼 사용할 수 있다.

앞에다가 const를 붙여주면 된다.

 

실행시켜 보면 "Hyoni Hyoni"를 컴파일러가 쥐고 있다.

메모리를 없애지 않고 name을 통해서 access 할 수 있도록 특별히 도와주고 있는 것이다.

 

그렇다면 예를 들어서 name2를 만들어서 똑같은 리터럴  "Hyoni Hyoni"를 넣어보자.

그리고 주소를 찍어보자

지금 문자의 포인터를 바로 출력안하고 바로 주소를 int로 변환해서 찍어보고 있는데 그 이유는 추후 설명하겠다.

실행시켜보면 놀랍게도 주소가 같게 나온다.

이것은 우리가 지금까지 배운 내용으로만은 설명이 되지 않는다.

이건 마치 컴파일러가 "너네 둘이 같으니까 메모리 좀 같이 써라"라고 한 것과 같다.

 

그렇다면 한 글자만 살짝 바꿔서 주소를 찍어보자.

 

실행시켜 보면 이번엔 다르게 나온다.

이번에는 "너네 둘이 다르니까 다른 메모리에 대해서 주소를 가져"라고 한 것과 같다.

이때 주의사항은 반드시 앞에 const가 붙어야지만 기호적 상수처럼 사용할 수 있다는 것 항상 기억하기!

 

그리고 const char 얘네는 return 타입으로도 쓸 수 있다.

 

이런식으로 쓸 수 있다.

이번에도 같은 것들 이니까 주소가 같게 나온다.

 


std::cout and char pointers

이번에는 문자 포인터의 특성에 대해서 설명드리겠다.

 

int의 array, char의 name 은 포인터니까 이것도 array라고 볼 수 있다.

실행시켜보면

 

int array는 주소가 나오고 밑에는 문자열이 나왔다. 그 밑에도 문자열이 나왔다

이것도 지금까지 배운 것으로는 설명이 되지 않는다.

이것은 cout에서 문자열은 특별히 처리한다고 생각해야 한다.

 

cout에서 문자의 포인터가 들어오면 "이건 문자열이 아닐까?"라고 가정을 하는 것이다.

실전에서 포인터 자체를 cout 하는 경우는 많지 않다. 포인터 주소는 사람에게 별 의미가 없기 때문이다.

그러니까 cout을 만든 사람은 문자의 포인터는 C 스타일의 문자열일 가능성이 높다.

문자의 배열일 가능성이 높다고 생각하고 주소를 출력하는 것이 아니라 그냥 '\0'을 만날 때까지 array를 쭉 출력하는 것이다.

이것은 cout이 특별히 처리하게 되어있기 때문에 외워야 하는 부분이다.


마지막으로 예제 한 가지 더 살펴보자

 

c 에다가 Q라는 글자 하나 넣었다.

그다음 c의 주소를 cout에 넣어보았다.

 

위에서 말씀드린 대로 문제가 생길 수 있다.

실행시켜보면

 

Q는 나왔는데 뒤에 이상한 글자들이 같이 나왔다.

이건 위 예제와 똑같은 문제이다.

c의 주소가 들어가니까(메모리 주소, 포인터가) cout에 들어가니까 

아 얘는 문자열인가 보다 생각한 것이다.

문자열을 출력하는 예제를 앞에서 해보셨다면

문자열을 출력할 때는 '\0'이 나올 때까지 계속 찍는다.

그래서 cout이 c가 문자열이라고 가정하고 '\0'이 나올 때 까지 쭉 출력을 한 것이다.

'\0'이 어디에 있을지는 모른다.

왜냐하면 Q뒤에 부분은 뭐가 있을지 우리는 알 수 없기 때문이다.

위험성이 있다는 것을 알아두면 된다.

 

만약 다시 de-referencing을 한다면 그냥 정상적으로 Q가 출력되고 끝났을 것이다.

 

de-referncing 하면 정상적으로 출력된다.

여기까지 문자열의 기호적 상수를 C 스타일로 어떻게 사용하는지 말씀드렸다.

이 부분은 컴파일러가 예외적으로 '이렇게 하면 프로그래머들이 편하겠지?'라는 생각으로 구현해 놓은 것들이라

우리가 이론적으로 배운 것과 맞지 않는 부분이 있다.

뒤에 갈수록 std::array 하던지 std::vector 등 배우게 되면 

이런 세세한 것들을 신경 쓰지 않고 편하게 쓸 수 있다.

 

 

Comments