g ++로 컴파일되는 이상한 코드
다음 코드는 g ++ 4.8.1로 성공적으로 컴파일됩니다.
int main()
{
int(*)();
}
함수에 대한 포인터의 간단한 선언처럼 보입니다.
int(*f)();
clang 3.4 및 vc ++ 2013으로 컴파일되지 않습니다.
컴파일러 버그입니까 아니면 표준의 어두운 곳 중 하나입니까?
g ++ 4.8.1 (업데이트 됨)로 잘 컴파일되는 유사한 이상한 코드 조각 목록 :
int(*)();
int(*);
int(*){};
int(*());
업데이트 1 : @Ali 가 댓글에 흥미로운 정보를 추가했습니다.
4 가지 경우 모두 clang 3.5 trunk (202594)에 컴파일 오류가 발생하고 gcc 4.9 trunk (20140302)로 잘 컴파일됩니다. 동작은 이해할 수있는
-std=c++98 -pedantic
점을 제외하고 와 동일합니다int(*){};
. 확장 이니셜 라이저 목록은-std=c++11
.
업데이트 2 : 로 @CantChooseUsernames가 에서 언급 한 그의 대답 그들은 여전히 컴파일 좋은 심지어 g에 의해 그들을 위해 생성없이 조립 초기화와 ++ (어느 쪽과도 초기화없이) 심지어 어떤 활성화 최적화하지 않고 :
int(*)() = 0;
int(*) = 0;
int(*){} = 0;
int(*()) = 0;
업데이트 3 :int(*)() = "Hello, world!";
컴파일도 잘 된다는 사실에 정말 놀랐 습니다 ( int(*p)() = "Hello, world!";
물론 컴파일하지는 않습니다).
업데이트 4 : 환상적이지만 int(*){} = Hello, world!;
잘 컴파일됩니다. 그리고 다음과 같은 매우 이상한 코드도 있습니다 : int(*){}() = -+*/%&|^~.,:!?$()[]{};
( 라이브 예제 ).
업데이트 5 로 @zwol는 에서 언급 한 그의 코멘트
이것과 많은 관련 구문 문제가 gcc 버그 68265 로 추적되고 있습니다.
C ++ 표준에 따름 (섹션 7 선언의 6 페이지)
6 init-declarator-list의 각 init-declarator 는 정확히 하나의 declarator-id를 포함합니다 . 이것은 해당 init-declarator에 의해 선언 된 이름이므로 선언에 의해 선언 된 이름 중 하나입니다.
따라서 이것은 단순히 컴파일러 버그입니다.
내 MS VC ++ 2010으로 컴파일 할 수는 없지만 유효한 코드는 예를 들어 (당신이 보여준 함수 포인터 선언과는 별개로) 보일 수 있습니다.
int(*p){};
테스트에 사용중인 컴파일러가 선언자 ID없이 선언을 허용하는 것 같습니다.
섹션 8.1 유형 이름의 다음 단락도 고려하십시오.
1 형식 변환을 명시 적으로 지정하고 sizeof, alignof, new 또는 typeid 인수로 형식 이름을 지정해야합니다. 이는 유형 ID로 수행 할 수 있으며, 이는 엔티티의 이름을 생략하는 해당 유형의 변수 또는 함수에 대한 구문 선언입니다.
이것이 얼마나 도움이되는지 잘 모르겠지만 다음을 시도했습니다 (clang 3.3, g ++ 4.8.1).
using P = int(*)();
using Q = int*;
P; // warning only
Q; // warning only
int(*)(); // error (but only in clang)
int*; // error
int(*p)(); // ok
int *q; // ok
반면에 모든 것이 g ++ 4.8.2 및 4.9.0에서 잘 컴파일됩니다. 불행히도 나는 clang 3.4가 없습니다.
대략적 으로 선언 [iso 섹션 7]은 다음과 같은 부분으로 구성됩니다.
- 선택적 접두사 지정자 (예 :
static
,virtual
) - 기본 유형 (예 :
const double
,vector<int>
) - 선언자 (예를 들어
n
,*p
,a[7]
,f(int)
) - 선택적 접미사 함수 지정자 (예 :
const
,noexcept
) - 옵션 초기화 또는 함수 본문 (예를 들어,
= {1,2,3}
또는{ return 0; }
이제 선언자 대략 이름과 선택적으로 일부 선언자 연산자 [iso 8/4]로 구성됩니다.
접두사 연산자, 예 :
*
(바늘)*const
(상수 포인터)&
(lvalue 참조)&&
(rvalue 참조)auto
(후행시 함수 반환 유형)
후위 연산자, 예 :
[]
(정렬)()
(함수)->
(함수 후행 반환 유형)
위의 연산자는 표현식에서의 사용을 반영하도록 설계되었습니다. 후위 연산자 바인드 프리픽스보다 더 단단한, 괄호는 그 순서를 변경하는데 사용될 수있다 : int *f()
포인터를 반환하는 함수이다 int
반면 int (*f)()
함수 포인터 반환int
입니다.
Maybe I am wrong, but I think these operators cannot be in the declaration without the name. So when we write int *q;
, then int
is the base type, and *q
is the declarator consisting of prefix operator *
followed by name q
. But int *;
cannot appear by itself.
On the other hand, when we define using Q = int*;
, then declaration Q;
is fine by itself because Q
is the base type. Of course, because we are not declaring anything, we may get an error or a warning depending on compiler options, but this is a different error.
The above are just my understanding. What the standard (e.g. N3337) says is [iso 8.3/1]:
Each declarator contains exactly one declarator-id; it names the identifier that is declared. An unqualified-id occurring in a declarator-id shall be a simple identifier except for the declaration of some special functions (12.3 [user-defined conversions], 12.4 [destructors], 13.5 [overloaded operators]) and for the declaration of template specializations or partial specializations (14.7).
(notes in square brackets are mine). So I understand int(*)();
should be invalid and I cannot say why it has different behaviour in clang and different versions of g++.
You can use this: http://gcc.godbolt.org/ to view the assembly..
int main()
{
int(*)() = 0;
return 0;
}
Generates:
main:
pushq %rbp
movq %rsp, %rbp
movl $0, %eax
popq %rbp
ret
Which is equivalent to: int main() {return 0;}
So even with NO optimization, gcc just doesn't generate assembly for it.. Should it give a warning or error? I have no clue but it doesn't care or do anything for the unnamed func pointer.
However:
int main()
{
int (*p)() = 0;
return 0;
}
With no optimization will generate:
main:
pushq %rbp
movq %rsp, %rbp
movq $0, -8(%rbp)
movl $0, %eax
popq %rbp
ret
which allocates 8 bytes on the stack..
참고URL : https://stackoverflow.com/questions/23015482/strange-code-that-compiles-with-g
'Nice programing' 카테고리의 다른 글
ggplot의 geom_polygon 채우기에 사용자 정의 이미지 추가 (0) | 2020.11.02 |
---|---|
REST 기반 서비스를 사용하기위한 Generic Python 라이브러리가 있습니까? (0) | 2020.11.02 |
영화 상영 시간 API가 있나요? (0) | 2020.11.02 |
HashMap.clear ()에서 Arrays.fill ()이 더 이상 사용되지 않는 이유는 무엇입니까? (0) | 2020.11.02 |
OS X의 경로에서 / usr / bin 전에 / usr / local / bin을 갖는 데 문제가 있습니까? (0) | 2020.11.02 |