프로그래밍언어론

선언과 정의

winwin-k9 2023. 4. 9. 19:35

선언 순서

객체 X가 블록 B의 어딘가에서 선언되었다고 가정하자.
X의 범위는 B의 선언 전 부분도 포함될까??
또한 그 부분에서 X가 사용될 수 있을까??
즉, 코드상 수식A에서는 속한 현재 범위에서 선언된 모든 이름을 참조할 수 있을까 아니면 범위의 A앞에서 선언된 이름만 참조할 수 있을까?

초기 언어들은 범위 제일 앞에 선언이 나와야 했다.

C는 이름에 대해 선언 후 사용의 원칙을 가지는데, C++과 자바는 사용전 선언의 요구를 많은 경우에 지키지 않아도 되도록 규칙을 더욱 완화시켰다. 클래스의 메소드 내부에서는 뒤에 나오는 선언의 멤버를 볼 수 있다. 그러나 지역변수는 자바에서도 선언 후 사용해야 한다.

선언과 정의

선언

  • 이름과 범위를 표시하는 역할
  • 세부적은 정보가 일부 생략될 수 있다.

정의

  • 객체의 모든 세부 사항을 명시

재귀 타입이나 재귀 함수 호출은 이름이 사용되기 전에 선언되어야 하는 언어에서는 문제가 생길 수 있다.

C와C++은 이를 해결하기 위해 선언과 정의를 구별한다.
선언은 이름과 범위를 나타내고 구현의 세부사항은 생략될 수 있다.
정의는 이름이 결합되어 있는 대상을 컴파일러가 구현할 수 있을 정도로 충분히 자세하게 기술하는 것이다. 선언이 정의가 될 만큼 충분히 완전하지 않다면 별도의 정의부가 범위 내 어딘가에 있어야 한다.

전방선언을 통해 미리 이름(타입, 함수)을 선언
자바는 전방선언을 하지 않는다.

C에서는 구조체 manager를 다음과 같이 선언만으로 표시할 수 있다.

 struct manager; /* declaration only - 전방선언 */ 
 struct employee { 
	 struct manager *boss; 
	 struct employee *next_employee;
	  ... };
 struct manager { 
	 /* definition */ 
	 struct employee *first_employee; ..
void list_tail(follow_set fs); /* declaration only */ 
void list(follow_set fs) { 
	switch (input_token) { 
		case id : match(id); 
		list_tail(fs); ... 
	}
void list_tail(follow_set fs) /* definition */ 
{ 
	switch (input_token) {
		 case comma : match(comma); list(fs); ...
	}
}

최초의 manager 선언은 이름만 소개하는 것으로 충분한데 왜나하면 모든 포인터는 동일한 크 기를 가지고 컴파일러는 employee의 구현을 위해 manager의 세부적인 것을 알 필요가 없기 때문 이다. 반면에 list_tail의 전방 선언은 반환형과 매개변수 리스트를 모두 기술해야만 컴파일러가 list에서 그 함수가 올바르게 호출되었는가를 확인할 수 있기 때문이다.

자바는 클래스 내에서는 모든 필드와 메소드 이름이 선언되기 전에 사용가능하므로 이러한 문제가 생기지 않는다.

728x90