왜 C99까지 선언과 코드를 혼합하는 것이 금지되었습니까?
저는 최근에 주로 C를 가르치는 대학 과정의 조교가 되었습니다.이 코스는 C90에서 표준화되어 있습니다.주로 컴파일러의 폭넓은 서포트에 의한 것입니다.이전 Java 경험을 가진 C newbies에게 매우 혼란스러운 개념 중 하나는 변수 선언과 코드가 블록(콤포지트 스테이트먼트) 내에 혼재되지 않을 수 있다는 규칙입니다.
이 제한은 C99로 마침내 해소되었습니다만, 애초에 왜 거기에 있었는지 아는 사람이 있을까요?가변 범위 분석을 단순화할 수 있습니까?프로그래머가 새로운 변수를 위해 스택을 확장해야 하는 프로그램 실행 지점을 지정할 수 있습니까?
나는 언어 디자이너들이 전혀 목적이 없다면 그러한 제한을 추가하지 않았을 것이라고 생각한다.
C의 초기 단계에서는 사용 가능한 메모리와 CPU 리소스가 매우 부족했습니다.따라서 최소한의 메모리 요구로 매우 빠르게 컴파일해야 했습니다.
따라서 C언어는 컴파일이 빠른 매우 단순한 컴파일러만을 필요로 하도록 설계되어 있습니다.그 결과, 「싱글 패스 컴파일러」의 개념이 됩니다.컴파일러는 소스 파일을 읽고 가능한 한 빨리 모든 것을 어셈블러 코드로 변환합니다(보통 소스 파일을 읽는 동안).예를 들어 다음과 같습니다.컴파일러가 글로벌 변수의 정의를 읽으면 적절한 코드가 즉시 출력됩니다.
이 특성은 현재까지 C에서 볼 수 있습니다.
- C는 모든 것에 대해 "전향 선언"을 요구합니다.멀티패스 컴파일러는 동일한 파일 내의 변수 선언을 스스로 예측하고 추론할 수 있다.
- 하면 「 」가 됩니다.
*.h
필요한 파일입니다. - 함수를 컴파일할 때는 가능한 한 빨리 스택프레임의 레이아웃을 계산해야 합니다.그렇지 않으면 컴파일러는 함수 본문을 여러 번 통과해야 합니다.
많은 중요한 최적화를 한 번의 경로로 수행할 수 없기 때문에 오늘날에는 심각한 C 컴파일러가 여전히 "싱글 패스"가 아닙니다.위키피디아에서 조금 더 많은 것을 찾을 수 있다.
표준 바디는 기능 바디에 대한 "싱글 패스" 포인트를 완화하기 위해 꽤 오래 머물렀다.다른 것들이 더 중요했을 것 같아요.
최적화되지 않은 컴파일러가 이렇게 효율적인 코드를 생성하는 것이 더 쉬울 것입니다.
int a;
int b;
int c;
...
3개의 다른 변수가 선언되어 있지만 정렬 등의 전략을 최적화하지 않고 스택 포인터를 한 번에 증가시킬 수 있습니다.
비교 대상:
int a;
foo();
int b;
bar();
int c;
스택 포인터를 1회만 증가시키려면 고도의 최적화가 필요하지만, 이것은 일종의 최적화가 필요합니다.
게다가 문체적인 문제로서 첫 번째 접근법은 모든 국소 변수를 한 곳에서 보고 최종적으로 그것들을 전체적으로 검사할 수 있게 함으로써 보다 규율 있는 코딩 방식을 장려한다(Pascal도 이를 시행하는 것은 당연하다).이를 통해 코드와 데이터를 보다 명확하게 구분할 수 있습니다.
복합계산서의 시작 부분에 변수 선언이 나타나도록 요구하는 것은 C89의 표현성을 손상시키지 않았다.중간 블록 선언을 사용하여 합법적으로 수행할 수 있는 모든 작업은 선언 전에 오픈 브레이스를 추가하고 둘러싸인 블록의 클로징 브레이스를 두 배로 늘리면 가능합니다.이러한 요건은 때때로 추가적인 개폐괄호를 사용하여 소스코드를 혼란스럽게 만들 수 있지만, 이러한 중괄호는 단순한 노이즈가 아니라 변수의 범위의 시작과 끝을 표시했을 것입니다.
다음 두 가지 코드 예를 생각해 보겠습니다.
{do_something_1();{내부 foo;foo = something1();(foo) do_something_1(foo)인 경우; }{int 바막대 = something2();(bar) do_something_2(bar)인 경우; }{내부 boz; boz = something3();(boz)가_something_3(boz)하는 경우; }}
그리고.
{do_something_1(); 내부 foo;foo = something1();(foo) do_something_1(foo)인 경우; int 바막대 = something2();(bar) do_something_2(bar)인 경우; 내부 boz; boz = something3();(boz)가_something_3(boz)하는 경우; }
에서 보면 는 '이러한 컴파일러'가 '이러한 컴파일러'인지 아닌지는 않을 foo
.do_something3()
그 스테이트먼트 전에 보유하고 있던 값이 그 후에 사용되지 않는 것을 판단할 수 있기 때문입니다.한편, 프로그래머에게 최적화 컴파일러가 없을 때 차선의 코드를 생성하는 방식으로 선언문을 쓰도록 권장하는 것은 매력적인 개념이 아니다.
혼합 것은가 이러한수 것이다), 것이라도 은 더 .가들이 그러한 구성을 허용하기를 원했다면 1970년대 컴파일러도 할 수 있었을 것입니다), 만약 혼합된 선언을 포함하는 블록이 또한 다음을 포함한다면 상황은 더 복잡해집니다.goto
★★★★★★★★★★★★★★★★★」case
의 선언과 은 너무 복잡해서 가 없다고 생각했을 이다.C의 창안자들은 아마도 변동 선언과 그 밖의 문구를 혼합하는 것을 허용하는 것은 그 기준이 너무 복잡해서 효익을 얻을 가치가 없다고 생각했을 것이다.
항상 그렇게 해왔기 때문에 컴파일러 작성이 조금 더 쉬워졌고, 아무도 다른 방법으로 쓸 생각을 하지 못했기 때문입니다.이윽고 사람들은 컴파일러 라이터보다 언어 사용자들의 삶을 쉽게 만드는 것이 더 중요하다는 것을 깨달았다.
나는 언어 디자이너들이 전혀 목적이 없다면 그러한 제한을 추가하지 않았을 것이라고 생각한다.
언어 디자이너가 언어를 제한하기 시작했다고 가정하지 마십시오.종종 이런 제약은 우연과 상황에 의해 발생한다.
Dennis Ritchie가 작업하던 시절에는 컴퓨터(예: PDP-11)의 메모리가 매우 한정되어 있었고(예: 64K 워드), 컴파일러는 작아야 했기 때문에 매우 적은 것만을 최적화해야 했습니다.그리고 그 당시(나는 1986-89 시대에 Sun-4/110의 C에서 코드화) 레지스터 변수를 선언하는 것은 컴파일러에게 매우 유용했습니다.
오늘날의 컴파일러는 훨씬 더 복잡합니다.예를 들어 GCC의 최신 버전(4.6)에는 500만 행 또는 1000만 행 이상의 소스 코드가 있으며(측정 방법에 따라 다름), 첫 번째 C 컴파일러가 등장했을 때는 없었던 많은 최적화가 이루어집니다.
그리고 오늘날의 프로세서도 매우 다릅니다(오늘날의 기계가 1980년대의 기계와 같다고는 할 수 없지만 수천 배 더 빠르고 수천 배 더 많은 RAM과 디스크를 가지고 있다고 가정할 수 없습니다).오늘날 메모리 계층은 매우 중요합니다.캐시 미스란 프로세서가 가장 많이 하는 작업입니다(RAM에서 데이터를 기다리는 작업).그러나 1980년대에는 메모리에 대한 액세스가 단일 기계 명령을 실행하는 것보다 거의 빠릅니다(또는 현재의 기준으로는 느림).이것은 오늘날 완전히 잘못된 것입니다.RAM 모듈을 읽기 위해서는 프로세서가 수백 나노초 동안 기다려야 하는 반면 L1 캐시 내의 데이터에서는 1 나노초당 1개 이상의 명령을 실행할 수 있습니다.
C를 하드웨어에 매우 가까운 언어로 생각하지 마십시오.이것은 1980년대에도 있었지만, 현재는 잘못된 것입니다.
오, 하지만 선언과 코드를 혼재시킬 수 있지만, 새로운 변수를 선언하는 것은 블록의 시작에만 국한되었습니다.예를 들어, 다음은 유효한 C89 코드입니다.
void f()
{
int a;
do_something();
{
int b = do_something_else();
}
}
언급URL : https://stackoverflow.com/questions/7859424/why-was-mixing-declarations-and-code-forbidden-up-until-c99
'sourcecode' 카테고리의 다른 글
긴 Epoch 시간(밀리초)에서 Java 8 LocalDate를 작성하려면 어떻게 해야 합니까? (0) | 2022.08.09 |
---|---|
vuex에서 vue 라이프사이클 후크에서 비동기/대기 기능을 사용하는 방법 (0) | 2022.08.09 |
스트림을 사용하여 맵을 생성할 때 중복 무시 (0) | 2022.08.09 |
vuex를 사용하여 Axi에서 기사 ID 가져오기 (0) | 2022.08.09 |
최초의 C 컴파일러는 어떻게 작성되었습니까? (0) | 2022.08.09 |