2017-03-28 1 views
6

내 컴파일러 과정에 대한 의미 론적 분석을 할 때 혼란스러운 경우가 발생했습니다.상수 이니셜 라이저 요소가 아닙니까?

#include <stdio.h> 

int a = "abcd"[2]; 

int main() 
{ 
    char b = "abcd"[2]; 

    printf("%d\n%c\n", a, b); 

    return 0; 
} 

GCC는 변수 "a"에 대해 "오류 : 초기화 요소가 일정하지 않습니다"라고 말합니다.

왜?

+2

gcc quirk - [clang은 매우 만족 스럽습니다] (https://godbolt.org/g/0CPrpX)처럼 보이며 [Intel 's ICC] (https://godbolt.org/g/JGL3nL)도 마찬가지입니다.). –

+1

@PaulR 어셈블리를 보면, clang은 그것을 (변수의 값을 메인의 시작 부분에서 계산하고 변수에 저장 한) 상수 표현으로 취급하지 않습니다. 그래서 clang이 글로벌 initializers가 정적 일 필요가있는 표준 요구 사항을 떨어 뜨린 것처럼 보입니다. – sepp2k

+0

그것은 나를 위해 컴파일 된 및 인쇄 99 c –

답변

5

C 언어에는 전역 변수의 초기화 프로그램이 상수식이되어야합니다. 이 배후의 동기는 컴파일러가 컴파일 타임에 표현식을 계산하고 계산 된 값을 생성 된 객체 파일에 쓸 수있게하는 것입니다.

The C standard은 상수 표현식이 무엇인지에 대한 특정 규칙을 제공 :

  1. An integer constant expression117) shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator .
  2. More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following:
    • an arithmetic constant expression,
    • a null pointer constant,
    • an address constant, or
    • an address constant for a complete object type plus or minus an integer constant expression.

당신이 경우 비 배열 액세스 식 또는 포인터 역 참조를 포함 볼 수 있듯이. 따라서 "abcd"[2]은 표준 당 상수 표현식으로 적합하지 않습니다.

  1. An implementation may accept other forms of constant expressions.

그래서 그것이 표준이 상수 표현으로 "abcd"[1] 수 있도록 위반하지 것이다, 그러나 또한 허용 보장 아니에요 :

이제 표준은 말한다.

그래서 컴파일러에서 허용할지 여부는 사용자에게 달려 있습니다. 어느 쪽이든 표준을 준수 할 것입니다. (여러분이 isConstantExpression 검사에서 또 다른 경우를 필요로하므로 더 많은 작업이 가능합니다. 실제로 컴파일 시간에 표현식을 평가할 수 있어야합니다. 그래서 허용하지 않을 것입니다).

0

int a = "abcd"[2];

a는 컴파일시 전역 변수 initilize이지만 "abcd"[2]는 런타임에 계산됩니다.

char b = "abcd"[2];

여기에서 b는 지역 변수이고 "abcd"[2]가 계산 된 후 실행시에 초기화됩니다.

관련 문제