int main()
{
i/*nt*/a = 10;
return 0;
}
위의 코드가 있고 토큰을 세고 싶다면 토큰이 14 개 또는 13 개입니까?
변수 이름 내에 주석을 쓰는 것이 유효합니까? 당신은 가정 수 int i
, int a
, int ia
전역으로 정의된다.
int main()
{
i/*nt*/a = 10;
return 0;
}
위의 코드가 있고 토큰을 세고 싶다면 토큰이 14 개 또는 13 개입니까?
변수 이름 내에 주석을 쓰는 것이 유효합니까? 당신은 가정 수 int i
, int a
, int ia
전역으로 정의된다.
답변:
주석은 프로그램 번역 1의 3 단계에서 제거됩니다 . 각 주석은 하나의 공백 문자로 대체됩니다. 따라서 댓글 /*nt*/
은 확실히 토큰이 아닙니다.
없음의 경우 int
, main
, i
, a
또는 return
프로그램 구문 분석 생산 매크로 전처리로서 정의된다 (14 개) 의 토큰 (되지 13) :
int
main
(
)
{
i
a
=
10
;
return
0
;
}
하지 않는 한 i
기호가있는 유형으로 정의 typedef
문 구문 오류로 거기 i a
는 C 문법의 규칙과 일치하지 않습니다.
따라서 변수 이름 안에 주석을 쓸 수 없으며 주석은 식별자를 2 개의 개별 토큰으로 분할합니다. 이것은 모든 전처리 및 C 언어 토큰 2에 해당 됩니다.
그러나 단항 연산자와 피연산자 사이 또는 #
및 전처리 지시문과 인수 사이와 같이 비정상적인 위치에 주석을 삽입 할 수 있습니다 .
/**/#/**/include/**/<stdio.h>/**///////////////////////
/**/#/**/define/**/STAT/**/(/**/a/**/)/**/-/**/1/**////
/**/#/**/ifdef/**/STAT/**//////////////////////////////
/**/int/**/main/**/(/**/)/**/{/**//////////////////////
/**/int/**/a/**/=/**/+/**/1/**/;/**////////////////////
/**/printf/**/(/**/"Hello "/**/"world!\n"/**/)/**/;/**/
/**/return/**/STAT/**/;/**/////////////////////////////
/**/}/**///////////////////////////////////////////////
/**/#/**/endif/**//////////////////////////////////////
그러나 매크로 정의 위는 매크로 같은 기능-하지만 일반 매크로 정의하지 않습니다 STAT
팽창에 그 ( a ) - 1
.
다른 토큰과 마찬가지로 변수 이름은 이스케이프 된 줄 바꿈으로 분할 할 수 있습니다. 이스케이프 된 개행은 시퀀스이거나 개행 \
바로 뒤에옵니다. 이러한 시퀀스는 프로그램 번역의 2 단계 동안 소스 코드에서 제거됩니다. 주요 목적은 긴 매크로 정의를 여러 줄로 나누는 것입니다.
다음은 동일한 14 개의 토큰을 생성 하는 코드 조각 3 입니다.
\
i\
nt\
ma\
in()
{\
i/\
*nt\
*/a \
= 10;
r\
et\
urn\
0;}
코드 colorizer가 슬라이스 및 diced 키워드 및 주석을 어떻게 놓쳤는 지 확인하십시오. :)
1)이 동작은 ANSI-C 일명 C89에서 지정되었습니다. 일부 고대 컴파일러는 토큰 붙여 넣기로 인해 미묘하게 다른 동작을 보였지만 이러한 특성은 역사적으로 만 관심이 있습니다.
2) 프로그램 번역의 6 단계에서 인접한 문자열 상수가 연결된다는 사실을 이용하여 문자열 상수 안에 주석을 거의 삽입 할 수 있습니다. printf("Hello "/* my name is Luca */"world!\n");
3)이 크리스마스 트리 프레젠테이션 스타일은 실제 프로그램에서 사용하기위한 것이 아니라 C의 입력 처리 기능을 남용하는 방법을 보여줍니다. 더 정교한 트릭이 The International Obfuscated C Code Contest 에서 우승했습니다 .
\r
하여 \n
. 그러나 이것이 역효과를 const char *path = "C:\\"; // the default path is C:\
The path is "C:\"
코드의 의미가 후행 줄 바꿈에 의존하는 것보다 더 나은 것처럼 보이는 주석을 작성하십시오 .
어휘 관점에서 주석은 공백과 동일합니다.
어휘 요소 상태에 관한 C 표준 의 섹션 6.4p3 :
... 전처리 토큰은 공백 으로 구분할 수 있습니다 . 이것은 주석 (나중에 설명) 또는 공백 문자 (공백, 수평 탭, 줄 바꾸기, 수직 탭 및 용지 공급) 또는 둘 다로 구성됩니다. ...
보다 구체적으로 설명은 단일 공간으로 번역됩니다. 이것은 섹션 5.1.1.2p3에 지정되어 있습니다.
소스 파일은 사전 처리 토큰과 일련의 공백 문자 (주석 포함)로 분해됩니다. 소스 파일은 부분 전처리 토큰이나 부분 주석으로 끝나서는 안됩니다. 각 주석은 하나의 공백 문자로 대체됩니다. 개행 문자는 유지됩니다. 줄 바꾸기가 아닌 공백 문자의 비어 있지 않은 각 시퀀스가 유지되거나 하나의 공백 문자로 대체되는지 여부는 구현에서 정의됩니다.
이를 설명하기 위해 코드를 전처리기를 통해 전달하면 다음과 같은 결과를 얻을 수 있습니다.
int main()
{
i a = 10;
return 0;
}
따라서 공백과 같은 주석은 별도의 토큰 역할을합니다.
이는 코드에 13 개가 아닌 14 개의 토큰이 포함된다는 것을 의미합니다.
코드의 형태를 확인하십시오.
int main()
{
int i/*nt*/a = 10;
return 0;
}
전처리 후 있습니다. 컴파일러 gcc -E myscript.c에 "-E"플래그를 추가하면 결과를 얻을 수 있습니다.
e.sharaborin@landau:~$ gcc -E myscript.c
# 1 "myscript.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "myscript.c"
int main()
{
int i a = 10;
return 0;
}
그리고 분명히 실수가 있다는 결론을 내릴 수 있습니다.
예, 할 수 있습니다. 컴파일러는 주석을 건너 뜁니다. 변수에 영향을주지 않습니다. 주석 태그를 끝내는 것을 잊지 마십시오.
i a
또는 ia
?
cpp -traditional
에 의해 구현 된대로ia = 10;
.