-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathdecinit.tex
1285 lines (1111 loc) · 53.6 KB
/
decinit.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\chapter{Declarations and Initializations} \label{chap:decinit}
% chapter 1: decinit
C 언어의 선언 문법은 (declaration syntax) 그 자체가 하나의 프로그래밍
언어라고 할 수 있습니다. 선언은 다음과 같이 여러 부분으로 구성되어 (꼭
모든 부분을 다 가져야 할 필요는 없습니다.) 있습니다: storage class,
base type, type qualifier, 그리고 declarator (declarator는
initializer를 포함할 수 있습니다.) 각 declarator는 새 identifier를
선언하는 것 이외에, identifier가 배열인지, 포인터인지, 함수인지, 또는
어떤 복잡한 타입인지를 알려줍니다. 따라서 선언이 실제 identifier가
어떻게 쓰일 것인지를 (declaration mimics use) 알려 줍니다 (질문 \ql{1.21}은 이
`declaration mimics use' 관계를 자세하게 다룹니다.)
\section{Basic Type} \label{sec:bastype}
프로그래머들은 종종 C 언어가 충분히 저수준 언어이면서도, C 언어의
type system이 상당한 수준으로 추상화되어 있다는 것에 놀라곤 합니다;
기본 타입들의 크기와 표현 방법이 언어 자체에 정확히 정의되어 있지 않습니다.
\begin{faq}
\Q{1.1} % 1.1 COMPLETE
어떤 타입의 정수를 쓸 것인지 어떻게 결정하죠?
\A
큰 값 (32,767 이상이거나 -32,767 이하)이 필요한 경우, \TT{long}을
쓰기 바랍니다. 차지하는 공간이 매우 중요하다면 (큰 배열이나 많은
구조체를 쓸 경우), \TT{short}를 쓰기 바랍니다. 이런 경우가 아니라면
\TT{int}를 쓰는 것이 가장 좋습니다. 오버플로우 문제가 중요시되고
음수가 필요하지 않는 경우라면, 또는 비트를 다룰 때 부호
확장\footnote{sign-extension}에서 문제가 발생하는 것을 원치 않는다면
적절한 크기를 가진 형의 \TT{unsigned} 형을 쓰는 것도 좋습니다.
(하지만 수식에서 \TT{signed} 형과 \TT{unsigned} 형을 섞어 쓰는
것은 좋지 않습니다.)
문자 타입도 (특히 \TT{unsigned char}) ``작은'' 정수타입으로 쓰일 수
있지만, 예상치 못한 부호 확장이나 코드의 크기를 증가시킬 수 있기
때문에 바람직하지 않습니다. (\TT{unsigned char} 타입을 쓰는 것이
도움이 될 경우도 있습니다;
관련된 문제는 질문 \ql{12.1}를 참고하기 바랍니다.)
비슷한 크기/빠르기 문제가 \TT{float}과 \TT{double}에서 발생할 수
있습니다. 변수의 주소가 필요하고 어떤 특별한 타입이 필요한 경우라면
위의 규칙들은 모두 적용되지 않습니다.
C 언어에서 각각의 type들이 정확한 크기를 가지도록 정의되어 있다고
착각하기 쉬운데, 사실은 그렇지 않습니다. C 언어에서 정의하고 있는
것은 다음과 같습니다:
\begin{itemize}
\item
\TT{char} type은 127 이상을 저장할 수 있다;
\item
\TT{short int} type과 \TT{int} type은 32,767까지 저장할 수 있다;
\item
\TT{long int}는 2,147,483,647까지 저장할 수 있다;
% TODO: insert a sentence for long long int.
\item
따라서 다음 규칙을 적용할 수 있다:
\begin{verbatim}
sizeof(char) <= sizeof(short) <= sizeof(int) <=
sizeof(long) <= sizeof(long long)
\end{verbatim}
\end{itemize}
이 규칙은 \TT{char}가 적어도 8 bit가 되어야 한다는 것과,
\TT{short int}와 \TT{int}는 적어도 16 bit여야 한다는 것과,
\TT{long int}는 적어도 32 bit가 되어야 한다는 것을
뜻합니다. (각각 type의 signed와 unsigned version은 같은 크기를
가진다고 보장되어 있습니다.)
ANSI C에서 특정 machine에서
각각 type의 최소값과 최대값은 \verb+<limits.h>+에 정의되어 있으며,
요약하면 다음과 같습니다:
\begin{center}
\begin{tabular}{lrrrr} \hline
Base type & Min. size & Min. value & Max. value & Max. value \\
& (bits) & (signed) & (signed) & (unsigned) \\ \hline
\TT{char} & 8 & -127 & 127 & 255 \\
\TT{short} & 16 & -32,767 & 32,767 & 65,535 \\
\TT{int} & 16 & -32,767 & 32,767 & 65,535 \\
\TT{long} & 32 & -2,147,483,647 & 2,147,483,647 & 4,294,967,295 \\
\hline
\end{tabular}
\end{center}
이 표는 표준이 보장하는 최소값들을 보여줍니다.
많은 implementation이 이보다 더 큰 값을 제공하지만,
portable한 프로그램을 만들고 싶다면 이러한 것에 의존해서는 안됩니다.
어떠한 이유에서 \BF{정확한} 크기가 필요한 경우라면 --- 이런 경우로는
외부 저장 배치(externally-imposed stroage layout)가 필요한 경우를 들
수 있습니다.
질문 \ql{20.5}를 참고하기 바랍니다 ---
적절한 \TT{typedef}를 쓰시기 바랍니다. (아래 Note 참고)
\R
\mbox{\cite{kr1} \S\ 2.2 \page{34};} \\
\cite{kr2} \S\ 2.2 \page{36}, \S\ A4.2 \Page{195--6},
\S\ B11 \page{257} \\
\cite{c89} \S\ 5.2.4.2.1, \S\ 6.1.2.5 \\
\cite{hs} \S\ 5.1,5.2 \Page{110--114}
\T
C99 표준은 새 정수 타입인 \TT{long long int}를 추가했습니다.
이 타입은 최소 64 bit이며, 다음과 같은 특징을 지닙니다.
\begin{center}
\begin{tabular}{l|r} \hline
Base type & long long \\
Min. size (bits) & 64 \\
Min. value (signed) & -9,223,372,036,854,775,807 \\
Max. value (signed) & 9,223,372,036,854,775,807 \\
Max. value (unsigned) & 18,446,744,073,709,551,615 \\ \hline
\end{tabular}
\end{center}
또한, 정확한 크기를 요구하는 정수 타입을 선언하기 위해, C99
표준은 \verb+<stdint.h>+를 통해 여러 가지 정수 타입을 제공합니다.
여기에 관한 것은 \ql{11.I}를 참고하기 바랍니다.
\R
\cite{c99} \S\ 5.2.4.2.1 \Page{22--23}, \S\ 6.2.5
\end{faq}
\begin{faq}
\Q{1.2} % 1.2 COMPLETE
왜 표준에서는 각 type의 크기를 정확히 정의하지 않나요?
\A
다른 high-level 언어에 비해 C 언어가 확실히 저 수준 언어이기는
하지만, object의 정확한 크기는 implementation이 결정할 문제입니다.
(C 언어에서 여러분이 bit의 갯수를 지정할 수 있는 유일한 곳은
structure 안에서 bitfield를 쓸 때입니다.; 질문 \ql{2.25}와 \ql{2.26}을
참고하기 바랍니다.) 대부분의 프로그램에서는 크기를 정확히
지정할 필요가 없습니다; 크기를 정확히 지정하는 많은 프로그램들은
지정하지 않도록 프로그램을 작성했을 때, 더 낫습니다.
\TT{int} type은 컴퓨터의 가장 자연스러운 word size를 나타내는 것으로
알려져 있으며, 대부분의 정수를 저장할 때 가장 적당한 type입니다.
질문 \ql{1.1}의 guideline을 보기 바랍니다;
\seealso{\ql{12.42}, \ql{20.5}}
\T
C99에서 새로 제공하는 정수 타입들은 개발자가 원하는 크기를 만족시킬
수 있습니다. \seealso{\ql{11.I}}
\end{faq}
\begin{faq}
\Q{1.3} % 1.3 COMPLETE
C 언어가 size를 정확히 정의하지 않기 때문에, 저는 \TT{int16},
\TT{int32}와 같은 \TT{typedef} 이름을 씁니다. 그래서
컴퓨터에 따라서 \TT{int}, \TT{short}, \TT{long} 등을 써서
만듭니다. 이 방법이 모든 문제를 해결해 줄 수 있을 것 같은데,
맞습니까?
\A
정확히 size를 제어할 필요가 있다면, 좋은 방법입니다.
그러나 다음과 같은 사항을 주의해야 합니다:
\begin{itemize}
\item
정확한 크기 제어가 불가능할 수도 있습니다 (예를 들면,
대부분의 36-bit machine)
\item
\TT{int16}이나 \TT{int32}를 쓰는 목적이 ``적어도 이 정도의 크기를
보장''하는 것이라면 전혀 쓸모가 없습니다. 왜냐하면 \TT{int}와
\TT{long} type의 정의 자체가 각각 ``적어도 16 bit'', ``적어도
32 bit''를 뜻하기 때문입니다.
\item
Typedef는 byte-order 문제를 해결해 주지 못합니다.
(예를 들어 여러분이 data를 교환(interchange)하려 하거나,
외부적으로 고정된 저장 형식에 맞추려고\footnote{conforming
to externally imposed storage layouts} 하는 경우)
\end{itemize}
\seealso{\ql{10.16}, \ql{20.5}}
\R
\cite{c89} \S\ 7.18.1.1
\T
C99에 따르면 \verb+<inttype.h>+를 포함시켰을 때, 정확한 크기를 갖는
데이터 타입을 위한 \verb+int16_t+, \verb+int32_t+등을 쓸 수
있습니다. 자세한 것은 질문 \ql{11.I}를 참고하기 바랍니다.
표준에 따라 정확히 말하면, \verb+int_16_t+, \verb+int32_t+등이
정의된 헤더 파일은 \verb+<stdint.h>+에 정의되어 있습니다.
다시, 표준에 따르면, \verb+<inttype.h>+는 \verb+<stdint.h>+를
포함하게 되며, 부가적인 사항들을 제공합니다.
% TODO: hs5와 iso를 좀 더 보고 여기에 채워 넣을 것.
% TODO: <inttype.h>에 있는 PRI*, SCN* 매크로에 대한 질문 추가하고 ref 달 것.
\R
\cite{c99} \S\ 7.18
\end{faq}
\begin{faq}
\Q{1.4} % 1.4
64-bit를 지원하는 컴퓨터에서 64-bit 타입을 쓸 수 있는 방법이 있나요?
\A
골치아픈 문제입니다. 다음과 같이 세 가지 방식으로 이 문제를
생각할 수 있습니다.
\begin{itemize}
\item 현존하는 16, 32-bit 시스템에서 세 정수 타입에서
(\TT{short}, \TT{int}, \TT{long}) 두 타입이 일반적으로
같은 크기를 가집니다. 64-bit 시스템에서는 세 타입이 모두
다른 크기를 가질 수 있습니다. 따라서 어떤 vendor들은
64-bit \TT{long int}를 제공합니다.
\item 아쉽게도, 현존하는 많은 코드들이 \TT{int}와 \TT{long}이
같다고 예상하고 쓰여져 있거나, 둘 중 하나가 32 bit라고 가정한
상태에서 쓰여져 있습니다. 이러한 코드를 그대로 유지시킬 수
있게 어떤 vendor들은 새로운, 비표준인 64-bit \TT{long long}
(\verb+__longlong+, 또는 \verb+__very long+등) 타입을
지원합니다.
\item 64-bit 시스템에서 \TT{int}가 64 bit이어야 한다는
논의도 있었습니다. 왜냐하면 보통 \TT{int}는 시스템이
표현하는 가장 자연스러운 word 크기를 가지기 때문입니다.
(``the machine's natual word size'')
\end{itemize}
따라서, 64-bit 타입을 쓰고자 하는 개발자는 적절한 typedef를 써서
코드를 작성해야 합니다. (또 이식성이 높은 코드를 만들기 위해서,
16, 32-bit 시스템을 위해 64-bit를 일일히 수동으로 처리할 수 있는
코드도 만들어야 할 것입니다.) Vendor들은 또, ``정확히 64 bit인
타입''보다 (현재 C 표준에 존재하지 않는)
``적어도 64 bit 이상인 타입''을 소개해야 합니다.
\T
\cite{ansi} \S\ F.5.6 \\
\cite{c89} \S\ G.5.6
\A
% TODO: book version과 상당한 차이가 있음. 체크 바람
다가오는 C 표준(C9X)에서는 \TT{long long} 타입이 적어도 64 비트
이상이 될 것을 명시하고 있습니다. 그리고 이 타입은 이미 여러
컴파일러에 의해 지원되고 있습니다 (어떠한 컴파일러는
\verb+__longlong+ 타입으로 지원합니다.)
또 대부분의 컴파일러들은 \TT{short int}를 16 비트로,
\TT{int}를 32 비트로, \TT{long int}를 64 비트로 지원하고 있으며,
이와 다르게 할 이유가 없습니다.
질문 \ql{18.15d}를 참고하시기 바랍니다.
\R
\cite{c9x} \S\ 5.2.4.2.1, \S\ 6.1.2.5.
\T
최신 C 표준, C99에서는 적어도 64 bit 이상인, \TT{long long} 타입을
지원합니다. 질문 \ql{1.1}, \ql{1.3}을 참고하기 바랍니다.
\R
\cite{c99} \S\ 5.2.4.2.1 \Page{22--23}, \S\ 6.2.5
\end{faq}
\section{Pointer Declarations} \label{sec:pointerdec}
% from 1.5
포인터에 관한 것은 Chapter~\ref{chap:pointer}부터
Chapter~\ref{chap:memalloc}까지
설명되어 있지만, 여기에서는 선언에 관련된 것만 다룹니다.
\begin{faq}
\Q{1.5} % 1.5 COMPLETE
다음 선언에서 무엇이 잘못되었나요?
\begin{verbatim}
char *p1, p2;
\end{verbatim}
\TT{p2}를 쓰려고 할 때 에러가 납니다.
\A
위의 선언에서 잘못된 점은 없습니다 --- 여러분이 원하는 작업을
해 주지 못한다는 것을 제외하면 말입니다.
Pointer 선언에서 \TT{*}는 `base type'의 일부분이 아닙니다;
\TT{*}는 선언할 이름으로 구성된 \EM{declarator}의 일부분입니다
(질문 \ql{1.21} 참고). 선언을 쓸 경우에 공백 문자의 구분은 의미가
없습니다. 따라서 첫번째 declarator는 ``\TT{* p1}''이며,
\TT{*}를 포함하고 있기 때문에, \TT{p1}은 `a pointer to \TT{char}',
즉 \TT{char}를 가리키는 pointer가 됩니다.
그러나 \TT{p2}의 declarator는 \TT{p2} 이외에 다른 것을 가지고
있지 않으므로, (여러분이 원하는 바가 아니겠지만) 간단히
\TT{char} type이 됩니다. 한 선언에서 두 개의 pointer를 선언하려면,
다음과 같이 해야 합니다:
\begin{verbatim}
char *p1, *p2;
\end{verbatim}
\TT{*}가 declarator의 일부분이기 때문에, 위에 쓴 것처럼 공백 문자를
쓰는 것이 좋습니다; \TT{char*}와 같이 쓰는 것은 실수를 내기 쉬우며,
혼동을 가져올 수 있습니다.
\seealso{\ql{1.13}}
\end{faq}
\begin{faq}
\Q{1.6} % 1.6 COMPLETE
Pointer를 선언하고 그 pointer가 어떤 공간을 할당하려고 했으나,
제대로 동작하지 않습니다. 아래 코드에 어떤 문제가 있습니까?
\begin{verbatim}
char *p;
*p = malloc(10);
\end{verbatim}
\A
여러분이 선언한 pointer는 \TT{p}이지 \TT{*p}가 아닙니다.
질문 \ql{4.2}를 참고하기 바랍니다.
\end{faq}
\section{Declaration Style} \label{sec:decstyle}
% from 1.7
변수나 함수를 선언하는 것은 단순히 컴파일러를 기쁘게? 하기 위한 것이
아닙니다; it also injects useful order into a programming project.
When declarations are arranged appropriately within a project, mismatches
and other difficulties can be more easily avoided, and the compiler
can more accurately catch any error that do occur.
\begin{faq}
\Q{1.7} % 1.7 COMPLETE
전역\trans{global} 함수와 변수를 선언 또는 정의하는 가장 좋은
방법이 무엇일까요?
\A
먼저 한 ``global'' 변수는 (여러 translation unit에서)
여러 개의 선언을 가질 수 있지만, 반드시 하나의 정의를 가져야 합니다.
Global 변수에서 정의는 공간을 할당하고, 필요하다면 초기값을 지정하는
일종의 선언입니다.
함수에서 선언은 function body를 제공하는 일종의 선언입니다.
아래는 선언의 예입니다:
\begin{verbatim}
extern int i;
extern int f();
\end{verbatim}
(\TT{extern} keyword는 함수 선언에서 option입니다; 질문 \ql{1.11}을
참고하기 바랍니다.)
아래는 정의의 예입니다:
\begin{verbatim}
int i = 0;
int f()
{
return 1;
}
\end{verbatim}
여러 소스 파일에서 변수나 함수를 공유할 필요가 있다면,
당연히 여러분은 모든 변수와 함수를 일관되게(consistent) 만들어야
합니다. 가장 좋은 방법은 각 정의를 관련된 \verb+.c+ 파일에 저장하고,
external 선언을 헤더 파일(``\verb+.h+'')에 두는 것입니다.
그리고 선언이
필요한 곳에서는 \verb+#include+를 써서 포함시키면 됩니다. 정의를
포함하는 \verb+.c+ 파일에도 같은 헤더 파일을 포함시켜야
컴파일러가 선언과 정의가 일치하는지 검사해 줍니다.
이 규칙은 매우 portability가 높은 방법입니다;
이는 ANSI C 표준의 요구에도
부합하며, ANSI 이전의 컴파일러와 링커에서도 잘 동작합니다 (UNIX
컴파일러와 링커는 최대 하나가 초기화된다는 조건 아래에 여러 개의
선언을
가능케 하는 ``common model''을 지원합니다; 이는 ANSI 표준에 의해
``common extension''으로 언급되어 있지만,
`pun\footnote{발음은 같으나 뜻이 다른 말}'은 아닙니다.
어떤 이상한 시스템에서는 외부 선언과 정의를 구별하기 위해서
반드시 초기값을 필요로 하기도 합니다.)
한 헤더 파일에 하나의 선언만 나오도록 하기 위해 다음과 같은 전처리기
트릭을 쓸 수도 있습니다:
\begin{verbatim}
DEFINE(int, i);
\end{verbatim}
그리고 어떤 매크로의 설정에 따라 이 줄이 선언이나 정의가 되도록 할 수
있지만 이는 문제를 유발할 가능성이 많으므로 추천하지 않습니다.
컴파일러가 선언이 불일치하는지 검사하기 위해서는 반드시 전역 선언을
헤더 파일에 넣는 것이 중요합니다. 특히, external 함수의
prototype을 \verb+.c+ 파일에 넣지 않도록 하기 바랍니다.
이는 정의와 일치하는 지 검사해 주지도 않으며, 만약 정의와 일치하지
않는다면 오히려 쓰지 않는 것보다 못합니다.
질문 \ql{10.6}과 \ql{18.8}을 참고하기 바랍니다.
\R
\cite{kr1} \S\ 4.5 \Page{76--7} \\
\cite{kr2} \S\ 4.4 \Page{80--1} \\
\cite{c89} \S\ 6.1.2.2, \S\ 6.7, \S\ 6.7.2, \S\ G.5.11 \\
\cite{rationale} \S\ 3.1.2.2 \\
\cite{hs} \S\ 4.8 \Page{101--104}, \S\ 9.2.3 \page{267} \\
\cite{ctp} \S\ 4.2 \Page{54--56}
\end{faq}
\begin{faq}
\Q{1.8} % 1.8 COMPLETE
C 언어에서 추상화된 data type을 만드는 가장 좋은 방법이 무엇일까요?
\A
질문 \ql{2.4}를 참고하기 바랍니다.
\end{faq}
\begin{faq}
\Q{1.9} % 1.9
``semiglobal'' 변수, 즉, 몇 소스 파일의 함수들은 볼 수 있으나,
다른 소스 파일에서는 볼 수 없는 그러한 `절반 정도의' 전역 변수를
만들 수 있을까요?
\A
C 언어에서 그런 일은 할 수 없습니다.
모든 함수를 같은 source 파일에 넣는 것이 불편하거나 불가능하다면,
아래 중 한가지 방법을 쓰시기 바랍니다:
% WORK FROM HERE..
\begin{itemize}
\item 한 라이브러리나 패키지의 모든 함수와 변수에 적당한 prefix 이름을
붙이고, 사용자에게 이 prefix를 쓰는 이름을 만들지 말라고 권장합니다.
(즉, 이 prefix로 시작하는 모든 이름은 reserved된 private한 것이라고
알립니다.)
\item 일반적인 코드에서 쓰이지 않는, 밑줄(`\verb+_+')로 시작하는
이름을 사용합니다. (질문 \ql{1.29}를 참고해서, 사용자와 시스템에서
제공하는 이름들과 충돌나지 않게 하기 바랍니다.)
\end{itemize}
\noindent 어떤, 특별한 linker를 써서, 기존의 이름들의 scope를 제한해서
충돌을 미리 방지하는 방법도 있을 수 있지만, C 언어의 범위를 넘어가는
내용이므로 여기에서 다루지 않습니다.
\end{faq}
\section{Storage Class} \label{sec:storageclass}
% from 1.10
우리는 선언의 두 가지 부분, base type과 declarator를 이미 다루었습니다.
다음 몇 질문에서는 storage class에 대한 것을 다룹니다. Storage class는
선언된 object나 함수의 visibility와 lifetime을
(각각 ``scope''와 ``duration''이라고 부르기도 합니다.) 다룹니다.
\begin{faq}
\Q{1.10} % 1.10 COMPLETE
\TT{static} 함수나 변수를 선언할 때, 항상 \TT{static}이라고 써 주어야
하나요?
\A
언어 표준에서는 항상 써 줄 것을 요구하지는 않습니다. (가장 중요한
것은 첫 선언에 \TT{static}을 써 주는 것입니다.) 하지만 규칙이 조금
복잡하게 얽혀있고, 함수냐 변수냐에 따라 조금씩 다릅니다. (게다가 이
문제에 있어서 현존하는 코드도 너무나도 다양합니다.)
따라서 가장 안전한 방법은, 모든 정의와 선언에서 항상 \TT{static}을
써 주는 것입니다.
\R
\cite{ansi} \S\ 3.1.2.2 \\
\cite{c89} \S\ 6.1.2.2 \\
\cite{rationale} \S\ 3.1.2.2 \\
\cite{hs} \S\ 4.3 \page{75}
\end{faq}
\begin{faq}
\Q{1.11} % 1.11
함수 선언에서 \TT{extern}이 의미하는 게 무엇인가요?
\A
이 함수의 정의가 다른 소스 파일에 있을 수 있다는 것을 알려주는
단순한 스타일적인 문제입니다. 따라서 다음 두 줄의 차이는 없습니다:
\begin{verbatim}
extern int f();
int f();
\end{verbatim}
\seealso{1.10}
\R
\cite{c89} \S\ 6.1.2.2, \S\ 6.5.1 \\
\cite{rationale} \S\ 3.1.2.2 \\
\cite{hs} \S\ 4.3, 4.3.1 \Page{75--6}
\end{faq}
\begin{faq}
\Q{1.12} % 1.12
\TT{auto} 키워드는 어디에 쓰이나요?
\A
전혀 쓰이지 않습니다. 이는 오래된(archaic) 문법에 쓰이는 것으로
현재에는 쓰이지 않습니다. 질문 \ql{20.37}을 참고하기 바랍니다.
\R
\cite{kr1} \S\ A8.1 \page{193} \\
\cite{c89} \S\ 6.1.2.4, \S\ 6.5.1 \\
\cite{hs} \S\ 4.3 \page{75}, \S\ 4.3.1 \page{76}
\end{faq}
\section{Typedefs} \label{sec:typedef}
% from 1.13
\TT{typedef}가 문법적으로는 storage class이지만, 이 키워드는
이름이 알려주듯, 새로운 type 이름을 정의하는 데에
쓰입니다.
\begin{faq}
\Q{1.13} % 1.13 COMPLETE
새 타입을 만들때, typedef를 쓰는 것하고, 매크로를 쓰는 것하고 무슨
차이가 있죠?
\A
일반적으로, typedef를 쓰는 것이 더 좋습니다. 왜냐하면 포인터 타입을
쓸 때 그 차이가 드러납니다:
\begin{verbatim}
typedef char *String_t;
#define String_d char *
String_t s1, s2;
String_d s3, s4;
\end{verbatim}
위의 예에서 보면, \TT{s1}, \TT{s2}, \TT{s3}는 모두 \verb+char *+
타입이지만, \TT{s4}는 \TT{char} 타입입니다. 물론 이 결과는 개발자가
원한 것이 아닙니다.
(\seealso{\ql{1.5}})
매크로가 좋은 이유는, \verb+#ifdef+를 쓸 수 있기 때문입니다.
(\seealso{\ql{10.15}}) 반면에 typedef는 또 스코프 규칙을 잘
따른다는 장점이 있습니다. (즉, 함수나 블럭의 안에서 선언되어,
그 안에서만 영향을 줄 수 있습니다.)
\seealso{\ql{1.17}, \ql{2.22}, \ql{11.11}, \ql{15.11}}
\R
\cite{kr1} \S\ 6.9 \page{141} \\
\cite{kr2} \S\ 6.7 \Page{146--7} \\
\cite{ctp} \S\ 6.4 \Page{83--4}
\end{faq}
\begin{faq}
\Q{1.14} % 1.14
Linked list 정의가 안됩니다. 다음과 같이 했는데 컴파일러는
계속 에러 메시지만 출력합니다. C 언어에서 구조체는 자신에 대한
포인터를 포함할 수 없는 것인가요?
\begin{verbatim}
typedef struct {
char *item;
NODEPTR next;
} *NODEPTR;
\end{verbatim}
\A
C 언어에서 구조체는 자신에 대한 포인터를 포함할 수 있습니다.
이 질문에서 문제는 \TT{NODEPTR}이 \TT{typedef} 이름이고, 이
이름을 사용한 시점에서 이 이름의 정의가 끝나지 않았다는 것입니다.
이 코드를 고치기 위해서, 먼저 구조체에 태그(tag, \TT{struct node})를
만들고 ``\TT{next}'' 필드를 ``\TT{struct node *}'' 타입으로
선언합니다. 또는 \TT{typedef} 선언과 구조체 정의를 분리시켜도
됩니다. 다음 코드가 해결 방법 중 하나입니다.
\begin{verbatim}
struct node {
char *item;
struct node *next;
};
typedef struct node *NODEPTR;
\end{verbatim}
이 문제를 해결하기 위해 적어도 세 가지의 다른 방법이 있습니다.
서로를 포함하는 한 쌍의 \TT{typedef}된 구조체를 정의할 때도 비슷한
문제가 발생할 수 있으며, 위와 같은 방식으로 해결할 수 있습니다.
질문 \ql{2.1}을 참고하시기 바랍니다.
\R
\cite{kr1} \S\ 6.5 \page{101} \\
\cite{kr2} \S\ 6.5 \page{139} \\
\cite{c89} \S\ 6.5.2, \S\ 6.5.2.3 \\
\cite{hs} \S\ 5.6.1 \Page{132--3}
\end{faq}
% TODO: Q 1.15
\begin{faq}
\Q{1.15} % 1.15
서로 참조하는 구조체를 만들 수 있을까요? 아래처럼 코드를
만들었는데 컴파일러가 \TT{BPTR}이 없다고 에러를 출력합니다.
\begin{verbatim}
typedef struct {
int afield;
BPTR bpointer;
} * APTR;
typedef struct {
int bfield;
APTR apointer;
} * BPTR;
\end{verbatim}
\A
질문 \ql{1.14}처럼, 이 문제는 구조체나 포인터에 있는 것이 아니라,
typedef에 관한 것입니다.
먼저, (typedef 없이) 두 구조체 tag 이름을 써서 다음과 같이 만듭니다:
\begin{verbatim}
struct a {
int afield;
struct b *bpointer;
};
struct b {
int bfield;
struct a *apointer;
};
\end{verbatim}
그러면, 컴파일러는, 아직 (자세히 말해, 아직 `incomplete'한 구조체인)
\TT{struct b}에 대해서 잘 모르지만 \TT{struct a} 안에서
\TT{struct b} 타입을 가리키는 \TT{struct b *bpointer}를 쓰는 것을
허락합니다. 때때로 다음과 같이 먼저 선언해 주는 것이 필요합니다:
\begin{verbatim}
struct b;
\end{verbatim}
This empty declaration masks the pair of structure declarations
(if in an inner scope) from a different \TT{struct b} in an outer
scope. 위와 같이 두 구조체를 tag 이름과 같이 선언한 다음, 다음과
같이 따로 typedef를 만들 수 있습니다:
\begin{verbatim}
typedef struct a *APTR;
typedef struct b *BPTR;
\end{verbatim}
멤버 포인터에 typedef 이름을 쓰기 위해, 다음과 같이 typedef 이름을
먼저 선언할 수도 있습니다:
\begin{verbatim}
typedef struct a *APTR;
typedef struct b *BPTR;
struct a {
int afield;
BPTR bpointer;
};
struct b {
int bfield;
APTR apointer;
};
\end{verbatim}
\seealso{\ql{1.14}}.
\R
\cite{kr2} \S\ 6.5 \page{140} \\
\cite{ansi} \S\ 3.5.2.3 \\
\cite{c89} \S\ 6.5.2.3 \\
\cite{hs} \S\ 5.6.1 \page{132}
\end{faq}
% TODO: Q 1.16
\begin{faq}
\Q{1.16} % 1.16 COMPLETE
다음 두 선언은 무엇이 서로 다른가요?
\begin{verbatim}
struct x1 { ... };
typedef struct { ... };
\end{verbatim}
\A
질문 \ql{2.1}을 보기 바랍니다.
\end{faq}
\begin{faq}
\Q{1.17} % 1.17 COMPLETE
``\TT{typedef int (*funcptr)();}''은 무슨 뜻인가요?
\A
typedef 이름인 \TT{funcptr}을 정의합니다. \TT{funcptr}은
여기에서, 임의의 갯수의 인자를 받고 \TT{int}를 리턴하는
함수에 대한 포인터입니다. 예를 들어 다음과 같이 하나 이상의 함수에
대한 포인터를 선언할 수 있습니다:
\begin{verbatim}
funcptr pf1, pf2;
\end{verbatim}
위 선언은 아래와 완전히 같은 뜻이지만, 좀 더 보기 쉽습니다:
\begin{verbatim}
int (*pf1)(), (*pf2)();
\end{verbatim}
\seealso{\ql{1.21}, \ql{4.12}, \ql{15.11}}
\R
\cite{kr1} \S\ 6.9 \page{141} \\
\cite{kr2} \S\ 6.7 \page{147}
\end{faq}
\section{The \TT{const} qualifier} \label{sec:const}
% from 1.18
C 언어 선언에서는 type qualifier라는 게 있으며, 이는 ANSI C에서
새로 추가된 것입니다. Qualifier에 관한 질문은 Chapter~\ref{chap:standard}에서
다룹니다.
\begin{faq}
\Q{1.18} % 1.18
I've got the declarations
\begin{verbatim}
typedef char *charp;
const charp p;
\end{verbatim}
Why is \TT{p} turning out \TT{const} instead of the characters
pointed to?
\A
질문 \ql{11.11}을 보기 바랍니다.
\end{faq}
\begin{faq}
\Q{1.19} % 1.19 COMPLETE
아래와 같이 배열을 초기화하는데 왜 \TT{const} 값을 쓸 수 없는 것인가요?
\begin{verbatim}
const int n = 5;
int a[n];
\end{verbatim}
\A
질문 \ql{11.8}을 보기 바랍니다.
\end{faq}
\begin{faq}
\Q{1.20} % 1.20
\TT{const char *p}, \TT{char const *p}, \TT{char * const p}가
서로 어떻게 다른가요?
\A
질문 \ql{11.9}, \ql{1.21}을 보기 바랍니다.
\end{faq}
\section{Complex Declarations} \label{sec:complexdec}
% from 1.21
C 언어의 선언은 엄청나게 복잡해질 수 있습니다.
일단 이 암호?를 풀어낼 방법을 배우면, 물론 이런 복잡한 선언은 거의 쓰이지
않지만, 어떤 선언이 나오더라도 두려워하지 않게 됩니다.
여러분이 프로그램을 \verb+*(*(*a[N])())()+와 같은 declarator로
암호화하려는 취미가 없다면, 질문 \ql{1.21}의 두번째와 같이 \TT{typedef}를 써서
간단하게 만들 수 있습니다.
\begin{faq}
\Q{1.21} % 1.21
문자를 가리키는 포인터를 리턴하는 함수에 대한 포인터를 리턴하는
함수에 대한 포인터 N 개로 이루어진 배열(array)을 어떻게 선언하죠?
\T
참고로 원문은 다음과 같습니다:
\begin{quote}
How do I declare an array of N pointers to functions returning
pointers to functions returning pointers to characters?
\end{quote}
\A
다음과 같이 세 가지로 답할 수 있습니다:
\begin{itemize}
\item \verb+char *(*(*a[N])())();+
\item \TT{typedef}를 써서 차례대로 만들어 가면 됩니다:
\begin{verbatim}
typedef char *pc; /* pointer to char */
typedef pc fpc(); /* function returning pointer
to char */
typedef fpc *pfpc; /* pointer to above */
typedef pfpc fpfpc(); /* function returning... */
typedef fpfpc *pfpfpc; /* pointer to... */
pfpfpc a[N]; /* array of... */
\end{verbatim}
\item \TT{cdecl} 프로그램을 쓰면 영어를 C 언어로, 또는 C 언어를 영어로
변환할 수 있습니다.
\begin{verbatim}
cdecl> declare a as array of pointer to function
returning pointer to function returning pointer
to char
char *(*(*a[])())()
\end{verbatim}
\noindent \TT{cdecl}은 복잡한 선언이나 캐스팅에 대해서도 많은 도움을
줍니다. 질문 \ql{18.1}을 참고하시기 바랍니다.
\end{itemize}
C 언어를 설명하는 좋은 책이라면 이러한 복잡한 선언에 대한 내용이
있기 마련이니 이 부분을 꼭 읽어보시기 바랍니다.
위의 예에서 쓰인 함수 포인터\trans{pointer-to-function} 선언은 파라메터
타입에 대한 정보를 포함하지 않았습니다. 만약 파라메터가 복잡한
함수라면 전체 선언은 매우 읽기 어렵습니다
(최신 버전의 \TT{cdecl}은 이 경우에도 도움이 됩니다.)
\R
\cite{kr2} \S\ 5.12 \page{122} \\
\cite{c89} \S\ 6.5ff (esp.\ \S\ 6.5.4) \\
\cite{hs} \S\ 4.5 \Page{85--92}, \S\ 5.10.1 \Page{149--50}
\end{faq}
\begin{faq}
\Q{1.22} % 1.22
같은 타입의 함수에 대한 포인터를 리턴하는 함수를 선언할 수
있나요? 저는 상태 머신\trans{state machine}을 만들고, 각 함수가
하나의 상태를 나타내게 한 다음, 이 함수가 다음 상태를 나타내는
함수 포인터를 리턴하게 하려고 합니다. 그러나 이런 함수를 선언할
방법을 찾지 못하고 있습니다.
\A 직접 할 수는 없습니다. 한가지 방법은 함수가 일반적인\trans{generic}
함수 포인터를 리턴하게 한 다음, 이를 원하는 타입으로 캐스팅하는 것과
또 다른 방법으론 함수가 어떤 구조체를 리턴하게 하고, 그 구조체에
이 타입의 함수에 대한 포인터를 저장하는 방식을 쓸 수 있습니다.
\end{faq}
\section{Array Sizes} \label{sec:arraysize}
% from 1.23
\begin{faq}
\Q{1.23} % 1.23
지역 변수나 파라메터로 배열을 선언할 때, 그 크기를 따로 인자로 받아서
선언할 수 있을까요?
\A
간단히 말해, 불가능합니다. 질문 \ql{6.15}, \ql{6.19}를 참고하기
바랍니다.
\end{faq}
\begin{faq}
\Q{1.24} % 1.24 COMPLETE
다음과 같이, 한 파일에 \TT{extern} 배열을 만들고, 다른 파일이 그
배열을 쓰려고 합니다. \TT{file2.c}에서 왜 \TT{sizeof} 연산이 안되나요?
\begin{verbatim}
file1.c:
int array[] = { 1, 2, 3 };
\end{verbatim}
\begin{verbatim}
file2.c:
extern int array[];
\end{verbatim}
\A
크기가 알려지지 않은, \TT{extern} 배열 선언은 `incomplete type'입니다.
따러서 \TT{sizeof}가 제대로 동작할 수 없습니다. 왜냐하면, 컴파일할 때,
다른 파일에 정의되어 있는 배열의 크기를 알 수 없기 때문입니다. 이 때,
사용자는 다음과 같이 세 가지 방법을 쓸 수 있습니다:
\begin{enumerate}
\item 변수 하나를 따로 두어서, 그 배열의 크기로 초기화한 다음 씁니다:
\begin{verbatim}
file1.c:
int array[] = { 1, 2, 3};
int arraysz = sizeof(array);
\end{verbatim}
\begin{verbatim}
file2.c:
extern int array[];
extern int arraysz;
\end{verbatim}
\seealso{\ql{6.23}}
\item 배열의 크기를 매크로 상수로 정의해 두고 이를 정의와
선언에 함께 사용합니다:
\begin{verbatim}
file1.h:
#define ARRAYSZ 3
\end{verbatim}
\begin{verbatim}
file1.c:
#include "file1.h"
int array[ARRAYSZ];
\end{verbatim}
\begin{verbatim}
file2.c:
#include "file1.h"
extern int array[ARRAYSZ];
\end{verbatim}
\item 배열의 마지막 요소 값으로, 어떤 특정한 값을 (sentinel
value, 일반적으로 0, -1, 또는 \TT{NULL}) 써서, (나중에 필요하면
그 값이 나올때까지 세어서 배열의 크기를 알 수 있게) 특별히 크기에
대한 것을 지정하지 않도록 합니다.
\begin{verbatim}
file1.c:
int array[] = { 1, 2, 3};
\end{verbatim}
\begin{verbatim}
file2.c:
extern int array[];
\end{verbatim}
\end{enumerate}
물론, 배열을 정의할 때, 초기값이 이미 정해져 있느냐에 따라
선택이 달라질 수 있습니다. 만약에 초기값이 위와 같이 정해져 있는
경우에는, 두번째 방식은 별로 좋지 않습니다.
\seealso{\ql{6.21}}
\R
\cite{hs} \S\ 7.5.2 \page{195}
\end{faq}
\section{Declaraction Problems} \label{sec:decproblem}
Sometimes the compiler insists on complaining about your declarations no matter
how carefully constructed you thought they were. These questions uncover some
of the reasons why. (Chapter~\ref{chap:sproblem} is a similar collection of
baffling run-time problems.)
% from 1.25
때때로 컴파일러는 여러분이 얼마나 주의깊게 선언을 만들었는지에 상관없이
불평을 하기도 합니다. 이 section의 질문들은 왜 그런지 그 이유를 설명합니다
(Chapter~\ref{chap:sproblem}에서는 실행 시간에 발생할 수 있는 이상한 문제들에
대해 설명합니다.)
\begin{faq}
\Q{1.25} % 1.25
제 컴파일러는 함수가 중복되어 정의되어 있다고 에러 메시지를
출력하지만 저는 한번만 정의했고, 한 번만 호출했습니다. 무엇이
잘못되었는지 모르겠군요.
\A 함수의 선언이, 이 함수를 호출할 때까지 나타나지 않으면, 컴파일러는
이 함수가 \TT{int}를 리턴한다고 가정합니다. 그 다음 나중에 실제
선언이나 정의가 나오고, 가정과 일치하지 않을 경우 그러한 에러가
발생합니다. 즉, \TT{int}가 아닌 다른 타입을 리턴하는 함수는 호출하기
전에 반드시 선언해야 합니다.
또는 어떤 헤더 파일에 선언되어 있는 함수 이름을 (정말로) 중복해서 다른
함수로 만들었을 경우에 이 문제가 발생할 수 있습니다.
질문 \ql{11.3}과 질문 \ql{15.1}을 참고하기 바랍니다.
\R
\cite{kr1} \S\ 4.2 \page{70} \\
\cite{kr2} \S\ 4.2 \page{72} \\
\cite{c89} \S\ 6.3.2.2 \\
\cite{hs} \S\ 4.7 \page{101}
\end{faq}
\begin{faq}
\Q{1.25b}
\TT{main()}을 선언하는 정확한 방법이 궁금합니다.
\TT{void main()}으로 해도 좋은가요?
\A
질문 \ql{11.12a}와 \ql{11.15}를 참고하기 바랍니다.
(어쨌든 \TT{void main()}은 틀린 선언입니다.)
\end{faq}
\begin{faq}
\Q{1.26} % 1.26 COMPLETE
제가 보기에는 제대로 되어 있는데, 컴파일러가 함수 prototype이 서로
다르다고 경고합니다. 왜 그럴까요?
\A
질문 \ql{11.3}을 보기 바랍니다.
\end{faq}
\begin{faq}
\Q{1.27} % 1.27 COMPLETE
파일 가장 첫 부분에서 이상한 문법 에러가 발생합니다. 왜 그럴까요?
\A
질문 \ql{10.9}를 보기 바랍니다.
\end{faq}
\begin{faq}
\Q{1.28} % 1.28 COMPLETE
다음과 같이, 큰 배열을 만들었는데, 컴파일러가 에러를 냅니다.
왜 그럴까요?
\begin{verbatim}
double array[256][256];
\end{verbatim}
\A
질문 \ql{19.23}, \ql{7.16}을 보기 바랍니다.
\end{faq}
\section{Namespace} \label{sec:namespace}
% from 1.29
이름을 짓는 것이 어려워 보이지 않을 지 몰라도, 사실 매우 어려운 문제입니다.
물론 함수나 변수의 이름을 짓는 것이 책이나 건물, 아기들의 이름을 짓는 것보다는
쉽습니다 --- 여러분은 많은 사람들이 여러분 코드의 이름들을 싫어할 지 모른다고
고민할 필요는 없습니다 --- 적어도 같은 이름이 이미 쓰이고 있는지만
조사하면 됩니다.
\begin{faq}
\Q{1.29} % 1.29
어떤 이름이 이미 예약되어 있고(reserved),
어떤 이름을 안전하게 쓸 수 있는지
알 수 있는 방법이 있을까요?
\A
Namespace management는 항상 큰 이슈가 됩니다. 이 문제는
--- 항상 확실하게 문제를 정의하는 것은 불가능하지만 ---
여러분이 선택한 이름이 시스템이 쓰고 있는 이름과 충돌나지 않게
해서 ``multiply defined''라는 에러가 발생하지 않게 하거나,
(좀 더 나쁜 상황이라 할 수 있는) 충돌이 나서, 기존 시스템에서
정의한 내용을 바꾸어 엉망이 될 수 있는 상황을 방지하자는 취지입니다.
또한, 지금은 충돌이 나지 않지만, 나중에 개발될, 시스템 라이브러리가
제공하는 이름과 충돌나지 않는다는 어떤 보증이 필요할 경우도
있습니다.\footnote{이러한 염려는, public symbol 뿐만 아니라,
시스템이 내부적으로 사용하는 internal, private symbol에도
해당합니다.}
(실제로, 새 컴파일러에서 재컴파일했을 경우에 namespace와 다른
문제들 때문에 build 실패하는 경우가 많습니다.)
그래서, ANSI/ISO C 표준은 사용자와 시스템 사이의 독립된
namespace에 대한 정의에 신경을 많이 쓰고 있습니다.
ANSI 규칙에 따라, 우리는 어떤 identifier가 예약(reserved)되어
있는지 알 수 있습니다. 먼저, 우리는 identifier에 대한 특징에 대해
알아야 합니다: 이 특징에는 scope, namespace, linkage가 있습니다.
\begin{itemize}
\item C 언어는 네 개의 scope가 있습니다. (Scope는 idenitifer의 선언이
어떤 영역에서 영향을 미치는가를 나타냅니다.):
function, file, block, 그리고 prototype으로 구분합니다.
(마지막 prototype scope는 함수 prototype 선언에서 파라메터
리스트 안에서 적용되는 것입니다. 질문 \ql{11.5}를 참고하기
바랍니다.)
\item C 언어는 네 개의 namespace가 있습니다: (\TT{goto}에서
대상을 지정할 때 쓰이는) label, (structure, union, enumeration에서
쓰이며, 이들은 이론상 충분히 각각 다른 namespace를 가질 수
있지만, 사실 하나의 namespace를 가지는) tag, (각각 structure,
union마다 독립적인) structure/union member, 그리고
이 외의 다른 데에서 쓰이는 보통의 identifier, 즉 ``ordinary
identifier''를 (예를 들어 함수, 변수, typedef
이름, enumeration constant 등) 위한 namespace. 또, 표준에
``namespace''라고 지정되어 있지는 않지만, preprocessor macro를
위한 이름들의 집합(A set of names)이 있습니다; 이 것은 컴파일러에게
전달되기 전, preprocessor에 의해 다 처리되기 때문에, 컴파일러
에게는 네 개의 namespace가 주어집니다.
\item 표준은 세 개의 ``linkage''를 정의합니다: external, internal,
그리고 none이 있습니다. (이 문제의 답변을 위해 말하면) External
linkage에 해당하는 것은 (모든 source file에 걸쳐) global,
non-static 변수와 함수입니다. Internal linkage에 해당하는 것은
file scope를 가지는 static 함수와 변수입니다. 그리고 none,
즉 ``no linkage''에 해당하는 것은, enumeration constant나
typedef 이름입니다.
\end{itemize}