2012-06-15 26 views
20

Tôi đã tạo 2 dự án, một dự án đầu tiên trong C và là dự án thứ hai trong C++, cả hai đều hoạt động với cùng một hành vi.biến toàn cầu tĩnh và bên ngoài trong C và C++

C dự án:

header.h

int varGlobal=7; 

main.c

#include <stdio.h> 
#include <stdlib.h> 
#include "header.h" 

void function(int i) 
{ 
    static int a=0; 
    a++; 
    int t=i; 
    i=varGlobal; 
    varGlobal=t; 
    printf("Call #%d:\ni=%d\nvarGlobal=%d\n\n",a,i,varGlobal,t); 
} 

int main() { 
    function(4); 
    function(6); 
    function(12); 
    return 0; 
} 

++ Dự án C:

header.h

int varGlobal=7; 

main.cpp

#include <iostream> 
#include "header.h" 
using namespace std; 

void function(int i) 
{ 
    static int a=0; 
    int t=i; 
    a++; 
    i=varGlobal; 
    varGlobal=t; 
    cout<<"Call #"<<a<<":"<<endl<<"i="<<i<<endl<<"varGlobal="<<varGlobal<<endl<<endl; 
} 

int main() { 
    function(4); 
    function(6); 
    function(12); 
    return 0; 
} 

Tôi đọc mà các biến toàn cục là extern theo mặc định và trong C và tĩnh theo mặc định trong C++; vậy tại sao mã C++ hoạt động?

Ý tôi là int varGlobal = 7; giống với static int varGlobal = 7; và nếu nó tĩnh thì nó chỉ có thể được sử dụng trong tệp mà nó đã khai báo, đúng không?

+0

lưu ý đầu tiên là 'include' chỉ cần sao chép-bột nhão nội dung. Vì vậy, đối với ví dụ tập tin như vậy, nó cần được loại bỏ để đơn giản hóa. –

Trả lời

63

Biến toàn cầu không phải là extern cũng không phải static theo mặc định trên C và C++ theo mặc định. Khi bạn khai báo biến là static, bạn đang hạn chế biến đó thành tệp nguồn hiện tại. Nếu bạn khai báo nó là extern, bạn đang nói rằng biến tồn tại, nhưng được khai báo ở một nơi khác và nếu bạn không khai báo ở nơi khác (không có từ khóa extern), bạn sẽ gặp lỗi liên kết (không tìm thấy biểu tượng).

Mã của bạn sẽ bị ngắt khi bạn có nhiều tệp nguồn bao gồm tiêu đề đó, vào thời gian liên kết bạn sẽ có nhiều tham chiếu đến varGlobal. Nếu bạn khai báo nó là static, thì nó sẽ hoạt động với nhiều nguồn (ý tôi là, nó sẽ biên dịch và liên kết), nhưng mỗi nguồn sẽ có varGlobal riêng của nó.

Những gì bạn có thể làm trong C++, mà bạn có thể không trong C, là để khai báo các biến như const vào tiêu đề, như thế này:

const int varGlobal = 7; 

Và đưa vào nhiều nguồn khác nhau, mà không vi phạm điều tại thời gian liên kết. Ý tưởng là thay thế kiểu C cũ #define cho các hằng số.

Nếu bạn cần một biến toàn cục có thể nhìn thấy trên nhiều nguồn và không const, tuyên bố nó như extern vào tiêu đề, và tuyên bố nó một lần nữa, lần này mà không có sự keywork extern, trên một tập tin nguồn:

header bao gồm theo nhiều file:

extern int varGlobal; 

trong một file nguồn của bạn:

int varGlobal = 7; 
+3

Như tôi vừa phát hiện, có * là * một sự khác biệt giữa C và C++ nhưng nó chỉ áp dụng cho các đối tượng ** const **: http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp? topic =% 2Fcom.ibm.xlcpp8l.doc% 2Flanguage% 2Fref% 2Fconst_cv_qualifier.htm –

+0

Nếu bạn sắp xếp mọi thứ vào phần đầu, một số trình biên dịch/liên kết sẽ phàn nàn về các biểu tượng được định nghĩa nhân. Ví dụ: 'const int varGlobal = 7;' Bởi vì bạn khai báo nó 'const', nó có thể được coi là một hằng số toàn cầu, nhưng một số trình biên dịch không phải là thông minh. Điều gì làm việc, luôn luôn, là khai báo mọi thứ 'static const' trong tệp header, như sau:' static const int varGlobal = 7; 'Bằng cách đó ngay cả khi trình biên dịch là ngu ngốc, nó sẽ không thêm biểu tượng vào bên ngoài bảng biểu tượng và trình liên kết sẽ không bao giờ thấy các biểu tượng được nhân xác định. – steveha

+0

@steveha Khai báo hằng số là "const tĩnh" sẽ gây ra cảnh báo gây phiền nhiễu đối với các tệp bao gồm tiêu đề, nhưng không sử dụng hằng số (tất nhiên, tùy thuộc vào trình biên dịch và cảnh báo của bạn được bật). – fbafelipe

6

Khi bạn #include tiêu đề, nó chính xác như khi bạn đặt mã vào chính tệp nguồn. Trong cả hai trường hợp, biến số varGlobal được xác định trong nguồn để nó hoạt động bất kể nó được khai báo như thế nào.

Cũng như được chỉ ra trong nhận xét, biến C++ ở phạm vi tệp không nằm trong phạm vi tĩnh mặc dù chúng sẽ được gán cho bộ nhớ tĩnh. Nếu biến là một thành viên lớp, ví dụ, nó sẽ cần phải được truy cập đến các đơn vị biên dịch khác trong chương trình theo mặc định và các thành viên không phải lớp không khác nhau.

+3

Ngoài ra, OP không đúng với giả định rằng biến được khai báo trên toàn cầu là tĩnh theo mặc định trong C++. Chúng có * liên kết bên ngoài *, giống như trong C. Các biến toàn cầu có thời gian * tĩnh * trong C và C++, vì vậy điều này có thể dễ gây nhầm lẫn. – nos

+0

Vì vậy, quy tắc sẽ áp dụng cho * .c một tệp * .cpp nhưng không cho tệp * .h? Cảm ơn bạn! – Cristi

+0

Tôi đã sai ... Cảm ơn bạn! – Cristi

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