2013-07-10 34 views
19

nguồn kernel Linux có rất nhiều literals mảng như thế này:chỉ mục rõ ràng trong các mảng chữ C?

enum { 
    FOO, 
    BAR 
}; 

static const char* const names[] = { 
    [FOO] = "foo", /* wtf is this? */ 
    [BAR] = "bar", 
}; 

Ở đây mỗi dòng chỉ ra một cách rõ ràng các chỉ số trong mảng các giá trị cung cấp thay vì dựa vào trật tự.

Tôi không biết cụm từ cần tìm kiếm - điều này được gọi là gì? Tiêu chuẩn nào định nghĩa nó? (Hoặc nó là một phần mở rộng GNU?) Tôi có thể làm điều này trong C + + hoặc chỉ đơn giản C? Thử nghiệm với gcc, tôi tìm thấy với trên trong test.c,

$ gcc --version 
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 
Copyright (C) 2011 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE 

các lệnh này trở thành công:

$ gcc -Wall -c test.c 
$ gcc -Wall -c --std=c90 test.c 
$ gcc -Wall -c --std=gnu90 test.c 
$ gcc -Wall -c --std=iso9899:1990 test.c 
$ gcc -Wall -c --std=c1x test.c 

và các lệnh này thất bại với khiếu nại khác nhau về lambdas và operator=:

$ g++ -Wall -c test.c 
$ g++ -Wall -c --std=c++98 test.c 
$ g++ -Wall -c --std=gnu++98 test.c 
$ g++ -Wall -c --std=c++0x test.c 
$ g++ -Wall -c --std=gnu++0x test.c 

Điều đó cho thấy điều này là hợp lệ C (chỉ là về bất kỳ phương ngữ) nhưng không C + +. Nhưng tôi hoài nghi. Tôi không nhớ việc nhìn thấy điều này được sử dụng ở bất cứ đâu, nhưng nhân Linux. Tôi cũng không thấy nó được mô tả trong, ví dụ, this list of constructs valid in C but not C++.

+1

Nếu bạn thêm '-pedantic' vào các dòng trình biên dịch của mình, bạn sẽ thấy rằng nó đã được thêm vào C99. – caf

+0

Cảm ơn mọi người! –

Trả lời

11

Đó là một phần của tiêu chuẩn C (C99 và mới hơn), được gọi là "khởi tạo được chỉ định".

Từ 6.7.9 Khởi, đoạn 6:

Nếu một vấn thiết kế có dạng

[ constant-expression ] 

sau đó các đối tượng hiện tại ... có kiểu mảng và sự biểu hiện được một biểu thức hằng số nguyên. Nếu mảng có kích thước không xác định, thì mọi giá trị không âm đều hợp lệ.

Và đoạn 33:

VÍ DỤ 9 Mảng có thể được khởi tạo tương ứng với các yếu tố của một điều tra bằng cách sử dụng định danh:

Theo answers at this question, C++ không hỗ trợ cùng một hành vi. Trình biên dịch của bạn có thể cung cấp các phần mở rộng.

lẽ hữu ích hơn đối với bạn (và một câu trả lời trực tiếp câu hỏi của bạn) là GCC documentation, mà nói:

Trong ISO C99 bạn có thể cung cấp cho các thành phần trong bất kỳ thứ tự, xác định các chỉ số mảng hoặc lĩnh vực cấu trúc tên chúng được áp dụng, và GNU C cho phép điều này như là một phần mở rộng trong chế độ C90. Phần mở rộng này không được thực hiện trong GNU C++.

+0

Tôi không biết bạn có phiên bản nào, nhưng với g ++ 4.8.1 cú pháp thành viên ('[member] = ...') hoạt động tốt. –

+0

@AlexisWilke, chắc chắn, nhưng đó là một phần mở rộng trình biên dịch, mặc dù. –

10

Đây là c99 initializer chỉ định.

Trình khởi tạo chỉ định cho phép bạn khởi tạo một mảng hoặc cấu trúc theo bất kỳ thứ tự nào.Các phần tử được thừa nhận được khởi tạo như thể chúng là các đối tượng tĩnh.

int bla[16] = {[5] = 42, [9] = 42}; 

này khởi tố bla[5]bla[9]-42 và tất cả các yếu tố còn lại để 0. Ký hiệu là một biểu thức hằng số nguyên giữa [].

enum { 
    FOO, 
    BAR 
}; 

static const char* const names[] = { 
    [FOO] = "foo", /* wtf is this? */ 
    [BAR] = "bar", 
}; 

Ở đây chỉ định là hằng số enum. Điều này được cho phép dưới dạng hằng số enum được coi là biểu thức hằng số nguyên trong C.

Tính năng này là tính năng C và không có trong C++.

+0

Hmm ... Tôi luôn nghĩ đó là một phần mở rộng GCC ... – 0x499602D2

+2

@ 0x499602D2, bạn có thể nghĩ đến một thời gian trước khi hành vi này được chuẩn hóa, hoặc có thể về bộ khởi tạo kiểu dải, là phần mở rộng của GNU. Một cái gì đó như '[1 ... 6] = 12'. Liên kết: http://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html#Designated-Inits –

+0

@CarlNorum Đó * là * những gì tôi đang nghĩ đến. :) Cảm ơn các liên kết! – 0x499602D2

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