2012-05-31 39 views
58

Ví dụ, nếu somestruct có ba thành viên số nguyên, tôi đã luôn luôn nghĩ rằng đó là OK để làm điều này trong C (hoặc C++) chức năng:C và C++: khởi tạo một phần của cấu trúc tự động

somestruct s = {123,}; 

Đầu tiên thành viên sẽ được khởi tạo đến 123 và cuối cùng sẽ được khởi tạo là 0. Tôi thường làm điều tương tự với mảng tự động, viết int arr[100] = {0,}; để tất cả các số nguyên trong một mảng được khởi tạo bằng không.


Gần đây tôi đọc trong GNU C Reference Manual rằng:

Nếu bạn không khởi tạo một biến cấu trúc, hiệu ứng phụ thuộc vào cho dù đó là có lưu trữ tĩnh (xem Storage Class Specifiers) hoặc không. Nếu có, các thành viên với các kiểu tích phân được khởi tạo với 0 và thành viên trỏ được khởi tạo thành NULL; nếu không, giá trị của các thành viên của cấu trúc là không xác định.


Ai đó có thể xin vui lòng cho tôi biết những gì các tiêu chuẩn C và C++ nói về cấu trúc tự động một phần và khởi tạo mảng tự động? Tôi làm mã trên trong Visual Studio mà không có một vấn đề nhưng tôi muốn được tương thích với gcc/g + +, và có lẽ trình biên dịch khác là tốt. Cảm ơn

+1

Đối với C++ - một phần của câu hỏi, [câu hỏi này] (http://stackoverflow.com/questions/1613341/) có thể bạn quan tâm. –

Trả lời

84

Các tài liệu liên quan gcc không nói chuyện của Khởi tạo ra một khoảng nó chỉ nói về (Hoàn thành) Khởi hoặc Không khởi.

Khởi tạo một phần là gì?

Các tiêu chuẩn không xác định khởi tạo một phần đối tượng, hoặc là Hoàn thành khởi tạo hoặc Không khởi tạo. Khởi tạo một phần là thuật ngữ không chuẩn thường đề cập đến một tình huống mà bạn cung cấp một số trình khởi tạo nhưng không phải tất cả nghĩa là: Ít khởi tạo hơn kích thước của mảng hoặc số phần tử cấu trúc được khởi tạo.

Ví dụ:

int array[10] = {1,2};     //Case 1:Partial Initialization 

(Hoàn thành) Khởi tạo hoặc Không khởi là gì?

Khởi tạo có nghĩa là cung cấp một số giá trị ban đầu cho biến được tạo cùng lúc khi tạo. tức là: trong cùng một câu lệnh mã.

Ví dụ:

int array[10] = {0,1,2,3,4,5,6,7,8,9}; //Case 2:Complete Initialization 
int array[10];       //Case 3:No Initialization 

Đoạn trích dẫn mô tả các hành vi cho Case 3.

Các quy tắc liên quan đến một phần khởi tạo (Case 1) được xác định rõ bởi tiêu chuẩn và các quy tắc này không phụ thuộc vào loại lưu trữ của biến được khởi tạo.
AFAIK, Tất cả các trình biên dịch chính thống đều tuân thủ 100% các quy tắc này.


Ai đó có thể xin vui lòng cho tôi biết những gì các tiêu chuẩn C và C++ nói về cấu trúc tự động một phần và khởi tạo mảng tự động?

Các tiêu chuẩn C và C++ đảm bảo rằng ngay cả khi một mảng số nguyên nằm trên lưu trữ tự động và nếu có ít initializers trong một danh sách cú đúp kín sau đó các yếu tố chưa được khởi tạo phải được khởi tạo để 0.

C99 Chuẩn 6.7.8.21

Nếu có ít initializers trong một danh sách cú đúp kín hơn có những yếu tố hoặc thành viên của một tổng hợp, hoặc các ký tự ít trong một chuỗi chữ sử dụng để khởi tạo một mảng kích thước đã biết hơn là có các phần tử trong mảng, phần còn lại của tổng hợp sẽ được khởi tạo hoàn toàn giống như các đối tượng có thời gian lưu trữ tĩnh.


Trong C++, quy tắc được nêu với một chút khác biệt.

C++ 03 Chuẩn 8.5.1 Uẩn
Para 7:

Nếu có ít initializers trong danh sách hơn là có những thành viên trong tổng hợp, sau đó mỗi thành viên không được khởi tạo một cách rõ ràng phải là giá trị được khởi tạo (8.5). [Ví dụ:

struct S { int a; char* b; int c; }; 
S ss = { 1, "asdf" }; 

khởi ss.a với 1, ss.b với "asdf", và ss.c với giá trị của một biểu thức có dạng int(), có nghĩa là, 0. ]

Trong khi giá trị khởi tạo được định nghĩa trong,
C++ 03 8,5 Initializers
Para 5:

Để giá trị khởi tạo một đối tượng kiểu T có nghĩa là:
- nếu T là một loại lớp (điều 9) với một hàm tạo do người dùng khai báo (12.1), sau đó hàm khởi tạo mặc định cho T được gọi (và khởi tạo bị hỏng nếu T không có hàm khởi tạo mặc định có thể truy cập );
- nếu T là một loại không phải là công đoàn mà không có một hàm tạo do người dùng khai báo, thì mỗi thành phần dữ liệu không thành phần và thành phần cơ bản của T được khởi tạo giá trị;
- nếu T là một loại mảng, thì mỗi phần tử được khởi tạo giá trị;
- nếu không, đối tượng được zero-khởi

+0

Cảm ơn câu trả lời kỹ lưỡng này. Về việc khởi tạo giá trị, bạn có biết rằng nếu trong C++ một biểu thức của biểu mẫu DWORD() được đảm bảo bằng 0 không? Björn nhận xét về câu hỏi của tôi và liên kết một câu hỏi liên quan đến giá trị khởi tạo, nhưng nó không rõ ràng cho tôi hay không Visual Studio hỗ trợ đó bởi vì nó là C++ 98, không C++ 03. – loop

+0

@test: AFAIK, trong C++ 98 chỉ có hai kiểu khởi tạo, * Không khởi tạo * và * Khởi tạo mặc định *, C++ 03 được thêm * Giá trị khởi tạo *, 'DWORD()' trong C++ 98 sẽ được đánh giá là * Không khởi tạo *. –

+0

Ok cảm ơn lần nữa – loop

0

Nếu biến là toàn cầu và tĩnh, nó phân bổ trong khu vực toàn cầu của mã nhị phân được khởi tạo bằng không. Nếu biến là địa phương, nó phân bổ trong ngăn xếp, trình biên dịch không khởi tạo bộ nhớ trong ngăn xếp (một số phiên bản gỡ lỗi có thể khởi tạo, nhưng phiên bản phát hành không bao giờ làm điều đó)

Nếu biến được phân bổ trong Heap, trình biên dịch cũng không khởi tạo nó.

15

Trong C, đối tượng là không bao giờ được khởi tạo một phần - nếu có phần nào được khởi tạo, toàn bộ đối tượng (và tất cả các đối tượng phụ đệ quy) được khởi tạo. Nếu không có trình khởi tạo rõ ràng nào được cung cấp thì các phần tử được khởi tạo thành "số không của loại thích hợp".

Trích dẫn trong câu hỏi của bạn đề cập đến khi trình khởi tạo cho toàn bộ đối tượng bị bỏ hoàn toàn, không phải khi đối tượng phụ thiếu trình khởi tạo. Ví dụ, giả định rằng arr có thời gian lưu trữ tự động, thì đây:

int arr[100] = { 123 }; 

initialises arr[0]-123 và mọi phần tử khác của arr-0. Trong khi điều này:

int arr[100]; 

để mọi thành phần của arr không được khởi tạo. Đây là trường hợp thứ hai mà báo giá là tham chiếu đến.

4

phiên bản gcc mới nhất cũng cho phép "một phần" khởi tạo và zeromem cùng một lúc:

typedef struct{ 
    int a,b,c; 
}T; 

T s = {0, .b=5}; 

các thành viên struct bây giờ sẽ có các giá trị: a=0, b=5, c=0

tôi không có bất kỳ thông tin về cho dù các trình biên dịch khác cho phép điều này hay không: p

+3

Đây là tính năng C99, không phải đặc biệt mới. Nó được gọi là "initializer được chỉ định" và được hỗ trợ rộng rãi. Nó không phải là một tính năng C++, mặc dù. C++ sử dụng các hàm tạo. – MSalters

0
// You can use something like this: 
typedef struct { 

    ...; 

    ...; 

} somestruct; 

// Declaration of struct 
somestruct st; 

// Initialising with 0. It does not depend on the size of the 
// structure and the number of elements in it. 
// memset() initialisation doesn't care if struct is static or dynamic. 
// but don't forget to use st instead &st to dynamic. 
memset(&st, 0, sizeof(somestruct)); 
Các vấn đề liên quan