Even Idiots Can Make Game

포인터를 어떻게 선언해야 할까

Date/Lastmod
Section
DEV
Categories
C++

#1 포인터 선언 관습의 차이

C++ 코드를 보다 보면 포인터 변수를 다음과 같이 선언하는 것을 볼 수 있다.

int* p;

반면, C 언어를 주로 사용해 온 경험 많은 프로그래머들은 다음과 같은 방식으로 선언하는 경우가 많다.

int *p;

즉, * 기호를 변수명 앞에 붙이느냐, 자료형 뒤에 붙이느냐의 차이가 존재한다.

#1 C++ 프로그래머들의 멘탈 모델

int* p는, a의 타입을 int*라는 한 덩어리로 간주하여 코드의 가독성을 높이겠다는 의도를 반영한 표현이다. 이는 얼핏 보면 타당한 방식처럼 보인다.

하지만 다음과 같은 상황에서는 어떨까?

int* a, b;

원래 한 줄에 두 개 이상의 변수를 선언하는 것은 좋지 않은 습관이지만, C++ 프로그래머들이 제시하는 멘탈 모델에 따르면, 위 코드는 int* 형식의 변수 ab를 선언한 것이 되어야 할 것이다.

하지만 실제로는 aint* 형식이지만, bint 형식이다.

배열 선언에서도 비슷한 문제가 발생한다.

int a[10];

위 선언은 크기 10의 int 배열을 생성한다. a의 형식은 int[10] 이다. 그런데 C++ 프로그래머의 멘탈 모델을 따른다면 다음과 같이 작성해야 할 것 같다:

int[10] a;

하지만 이는 문법적으로 유효하지 않으며, 컴파일 오류를 발생시킨다. 포인터 선언과 배열 선언에서의 일관성이 존재하지 않는다.

즉, 이러한 멘탈 모델에 뭔가 문제가 있다는 뜻이다.

#1 선언의 문법적 구조

C/C++에서 선언(Simple Declaration)은 Specifier와 Declarator의 조합으로 이루어진다. 구체적인 구조는 cppreference에서 볼 수 있으며, 간단히 요약하면 다음과 같은 구조이다:

// 단순 선언의 구조 (Simple Declaration):

[Specifier의 목록] [Declarator의 목록];

Specifier

Specifier에 해당하는 것들은 정말 많은 것들이 있다. const, volatile, static과 같은 키워드들이 여기에 속하며, int, float과 같은 자료형의 이름들 또한 여기에 속한다.

우리가 선언의 좌측에서 으레 기대하는 것들이 여기에 속한다고 보면 된다.

Declarator

Declarator는 변수의 이름을 포함하며, *[]같은 문법 요소 또한 Declarator의 일부이다. 이 요소들은 해당 요소가 어떻게 접근될지를 나타낸다.

여기에서 C++ 프로그래밍 식 멘탈 모델에 문제가 문법적으로 드러난다.

*int이 모두 동일한 문법적 토큰인 줄 알았는데, 사실 아니었다. *는 Declarator이고, 식별자의 이름과 동일한 소속이다. 반면 int는 Specifier 소속이다.

#1 새로운(?) 멘탈 모델!

왜 이러한 괴리가 발생할 것인지 감히 추측해보건데, 다른 고수준 언어들의 영향이 아닐까 싶다.

C# 에서는 다음이 문법상 아무런 문제가 없다.

int[] a1, a2;

a1a2는 모두 int[]라는 완전한 형식이다.

Java 에서는 두 방식을 모두 허용한다.

int a1[], a2[];
int[] a1, a2;

여기서도 a1a2는 모두 int[]라는 완전한 형식이다.

C#과 Java와 같은 고수준 언어들은 자료형을 보다 추상적인 개념으로 캡슐화하고 있으며, 선언 방식에서도 일관성을 유지하려고 한다.

반면, C/C++는 보다 저수준의 메모리 제어를 중시하며, 값이 메모리에 어떻게 배치되어 있는지를 강조하는 문법적 구조를 가지고 있다. 즉, *[]와 같은 요소들은 자료형의 일부가 아니라, 해당 변수에 어떻게 접근할지를 나타내는 표기법이다.

예제 분석

int *p 라는 선언은 다음과 같은 의미이다. p라는 식별자를 지금부터 선언 할 것인데, 이 식별자와 연관이 있는 메모리 블록의 값은* 연산자를 통해 접근할 수 있으며, int 형식으로 메모리 블록을 읽어야 유의미한 값이 나온다.

추가적인 예를 보자.

const int **p, a; // (1)
float fa[10]; // (2)
bool bar(int, int); // (3)

이처럼 C/C++의 선언 방식은 단순히 자료형을 묶는 것이 아니라, 변수의 접근 방식까지 고려하는 구조로 이루어져 있다.

#1 결론

C++ 스타일의 int* p 표기법은 고수준 언어 트렌드에 영향을 받아 가독성을 높이려는 의도를 가지고 있지만, 문법적으로 완벽한 일관성을 갖추고 있지는 않다.

반면, int *p 표기법은 C/C++의 기본적인 선언 규칙과 더 잘 부합하며, C/C++의 핵심 중 하나인 메모리의 저수준 제어를 드러내는 표기법이라고도 볼 수 있다.

하지만 이러한 표기법을 포함한 전체적인 코딩 스타일에 대해서는 일관성을 유지하는 것이 가장 중요하며, 특정 스타일을 따르더라도 팀에서 합의된 코딩 스타일 가이드를 준수하는 것이 우선이라고 볼 수 있겠다.

#1 Reference

comments powered by Disqus