2015-07-22 13 views
11

Hãy xem xét đoạn mã sau:Non-tĩnh thành viên khởi tạo của mảng char với cú đúp đưa ra một lỗi trong gcc trong khi không ở kêu vang

#include <iostream> 

class A 
{ 
    char name[40] = { "Blank" }; // note the braces here 
public: 
    const char *getName() { return name; } 
}; 

int main() 
{ 
    A a; 

    std::cout << a.getName() << std::endl; 
} 

Nó cung cấp cho một lỗi trong gcc (phiên bản mới nhất 5.2.0):

prog.cpp:5:28: error: invalid conversion from 'const char*' to 'char' [-fpermissive] 
    char name[40] = { "Blank" }; 
          ^

Nhưng nó không phải là trường hợp cho clang, mà biên dịch nó hoàn hảo với -std=c++11 -pedantic -Wall.

Có thực sự không chính xác khi đặt dấu ngoặc đơn cho trình khởi tạo không tĩnh ở đây?

AFAIR không quan trọng nếu niềng răng có mặt hay không. Ví dụ, định nghĩa của mảng, chẳng hạn như:

char text[] = "some text"; 

tương đương với:

char text[] = { "some text" }; 
+0

không phải là cùng một contraption trình biên dịch cho phép chúng tôi khởi tạo tăng :: mảng tổng hợp với chỉ một cú đúp chiều sâu thay vì hai? –

+0

Sẽ không '{" một số văn bản "}' khởi tạo một mảng các chuỗi, chẳng hạn như 'char arrayOfStrings [] [] = {" một số văn bản "};' với phần tử đầu tiên có chứa một con trỏ tới "" một số văn bản "' ? – muXXmit2X

+0

@ muXXmit2X Đó cũng là suy nghĩ đầu tiên của tôi, nhưng như câu hỏi được chỉ ra, nó không thay đổi bất cứ điều gì nếu bạn làm điều đó bên trong một chức năng. – Telokis

Trả lời

5

Vâng tiêu chuẩn không phải là rất rõ ràng trong quan điểm của tôi, nhưng tôi sẽ nói rằng Clang là đúng:

8.5.1 nói:

§2: Khi một tổng thể được khởi tạo bởi một danh sách khởi tạo, như được chỉ ra trong 8.5.4, các phần tử của danh sách khởi tạo được lấy làm khởi tạo cho các thành viên của tổng hợp, trong tăng chỉ số hoặc thành viên đặt hàng. Đó là giải thích gcc: tên là một mảng, có một dấu ngoặc-init-danh sách để yếu tố đầu tiên của mảng (char) được khởi tạo với mảng char => lỗi

Nhưng 8.5.2 rõ ràng nói: Một mảng kiểu ký tự hẹp ... có thể được khởi tạo bằng một chuỗi ký tự hẹp ...hay bởi một chuỗi một cách thích hợp, đánh máy đen kèm theo trong dấu ngoặc (nhấn mạnh mỏ)

giải thích của tôi là tiêu chuẩn consideres mảng char như đủ đặc biệt để explicitely phép một chuỗi chữ kèm theo trong dấu ngoặc là hợp lệ ngay cả khi nó đánh bại 8,5 .1 §2

4

Từ C++ Dự thảo tiêu chuẩn làm việc n4527 [dcl.init]. Một khởi có thể được viết như sau:

Initializers

initializer: 
    brace-or-equal-initializer 
    (expression-list) 

brace-or-equal-initializer: 
    = initializer-clause 
    braced-init-list 

initializer-clause: 
    assignment-expression 
    braced-init-list 
initializer-list: 
    initializer-clause...opt 
    initializer-list,initializer-clause...opt 

braced-init-list: 
    {initializer-list,opt} 
    { } 

Một tuyên bố thành viên Lớp

member-declarator: 
    declarator virt-specifier-seq opt pure-specifier opt 
    declarator brace-or-equal-initializer opt 

Từ những gì tôi đọc nó có vẻ như gcc không đáp ứng được Tiêu chuẩn. Bởi vì việc khởi tạo thành viên lớp bằng cách sử dụng dấu ngoặc được chấp nhận bởi tiêu chuẩn.

+0

Điều nào trong số này có liên quan đến ví dụ này? 'brace-or-equal-initializer'? –

+0

Cả hai. Người đầu tiên áp dụng bất cứ khi nào một biến được khởi tạo, biến thứ hai chuyên khai báo thành viên lớp. – Pumkko

+2

Tôi không thấy cách này giải quyết câu hỏi ở tất cả, vì 'gcc' không báo cáo lỗi cú pháp. Nó chấp nhận các dấu ngoặc, nhưng dường như nó có nghĩa là biểu thức đầu tiên sau đây khởi tạo phần tử đầu tiên của mảng, do đó một lỗi kiểu được báo cáo trong việc chuyển đổi một ký tự con trỏ thành một ký tự đơn. Cho dù điều này theo tiêu chuẩn hay không tôi không biết, nhưng trong mọi trường hợp không thể được suy ra từ các quy tắc cú pháp bạn trích dẫn. –

2

fwiw, g++ có một số vấn đề với khởi tạo dựa trên cú đúp và/hoặc gọi hàm dựng, bao gồm một số báo cáo gần đây.

Tuy nhiên (chỉnh sửa), như Jonathan đã chỉ ra đúng, hầu hết (tất cả?) Trong số này có thể được làm việc xung quanh dễ dàng. Tôi đã thành công thay thế cú pháp dấu ngoặc đơn cũ thành các bit bị ảnh hưởng của mã. Nó sẽ là giáo dục để nghe về một tình huống mà điều này không thể được thực hiện, nhưng may mắn tôi đã không cá nhân tìm thấy một, vì vậy g++ vẫn nổi bật có thể sử dụng cho tôi (với ý kiến ​​giải thích tại sao tôi sử dụng cú pháp cũ trong một số nơi lẻ)

+1

Tất cả các lỗi đó đều có cách giải quyết đơn giản, vì vậy có các lỗi khác mà mọi người đang làm việc trước (như trình biên dịch tiền mặt trên mã hợp lệ, hoặc lambdas làm điều sai). Và lỗi của OP đã được sửa. –

+0

Ồ, chắc chắn rồi. Với các quirks liên quan đến cú đúp tôi đã đi qua cho đến nay, nó thường đủ để sử dụng dấu ngoặc đơn thay vào đó, và may mắn thay, tôi chưa tìm thấy một tình huống mà điều này không thể được thực hiện - thật khó cho tôi để tưởng tượng một. Xin lỗi: bài đăng của tôi dường như hơi khắc nghiệt hơn tôi thực sự muốn trở thành. :) –

+0

Không vấn đề gì, tôi đã bình luận nhiều hơn cho những độc giả khác, những người có thể sử dụng câu trả lời của bạn như nhiên liệu chống GCC;) Tôi chưa từng thấy https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63151 của bạn báo cáo, tôi sẽ xác nhận nó ngay bây giờ (hoặc gần như là một sự lừa đảo nếu bạn đúng rằng nó có thể là) –

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