2017-03-28 58 views
6

Tôi gặp phải một trường hợp khó hiểu khi tôi đang thực hiện phân tích ngữ nghĩa cho khóa học trình biên dịch của mình.Không phải là phần tử khởi tạo không đổi?

#include <stdio.h> 

int a = "abcd"[2]; 

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

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

    return 0; 
} 

GCC nói "lỗi: yếu tố khởi tạo không cố định" cho biến "a".

Tại sao?

+2

Trông giống như một cuộc trốn thoát gcc - [tiếng kêu khá hài lòng với nó] (https://godbolt.org/g/0CPrpX), và do đó là [ICC của Intel] (https://godbolt.org/g/JGL3nL). –

+1

@PaulR Từ khi nhìn vào lắp ráp, clang không coi nó như là một biểu thức liên tục mặc dù (giá trị được tính ở đầu của chính và sau đó được lưu trữ trong biến). Vì vậy, có vẻ như clang đã giảm yêu cầu của tiêu chuẩn mà các trình khởi tạo toàn cục cần phải tĩnh. – sepp2k

+0

nó được biên dịch cho tôi so với và in 99 c –

Trả lời

5

Ngôn ngữ C yêu cầu bộ khởi tạo cho các biến toàn cầu là biểu thức không đổi. Động lực đằng sau điều này là cho trình biên dịch có thể tính toán biểu thức tại thời gian biên dịch và ghi giá trị được tính vào tệp đối tượng đã tạo.

The C standard cung cấp quy định cụ thể đối với một biểu thức hằng là gì:

  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.

Như bạn thấy không trong các trường hợp bao gồm một biểu thức truy cập mảng hoặc một dereference con trỏ. Vì vậy, "abcd"[2] không đủ điều kiện như là một biểu thức liên tục theo tiêu chuẩn.

Bây giờ tiêu chuẩn cũng nói:

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

Vì vậy, nó sẽ không vi phạm tiêu chuẩn cho phép "abcd"[1] như một biểu thức hằng số, nhưng nó cũng không đảm bảo được cho phép.

Vì vậy, tùy thuộc vào bạn có cho phép trong trình biên dịch của bạn hay không. Nó sẽ tương thích chuẩn (mặc dù cho phép nó hoạt động nhiều hơn khi bạn cần một trường hợp khác trong kiểm tra isConstantExpression và bạn cần thực sự có thể đánh giá biểu thức tại thời gian biên dịch, vì vậy tôi sẽ không chấp nhận nó).

0

int a = "abcd" [2];

a là biến toàn cục được khởi tạo tại thời gian biên dịch nhưng "abcd" [2] được tính theo thời gian chạy.

char b = "abcd" [2];

tại đây b là biến cục bộ và nó khởi động vào thời gian chạy sau khi tính toán "abcd" [2].

Các vấn đề liên quan