2015-10-01 20 views
40

Mã này biên dịch, nhưng tôi có một lỗi thời gian chạy trong Visual Studio:Sử dụng một biến có cùng tên trong không gian khác nhau

Run-time thất bại kiểm tra # 3 - biến 'x' đang được sử dụng mà không cần được khởi tạo ...

int x = 15; 
int main() 
{ 
    int x = x; 
    return 0; 
} 

tôi không hiểu hành vi đó ... trong hộp lỗi khi tôi nhấp tiếp tục chương trình sơ yếu lý lịch và x có hàm hỏng (như -8556328 thay vì 15).

Tại sao mã này hoạt động mà không có sự cố và mảng int được khai báo tốt?

const int x = 5; 
int main() 
{ 
    int x[x] = {1,2,3,4}; 
    return 0; 
} 
+17

Bạn đã gắn thẻ cả C và C++. Bạn đã biên dịch cái nào? –

+3

Một số sự kiện thú vị: 'gcc 4.8.4', biên dịch và chương trình này có thể chạy với' -Wall -Wextra -pedantic' được bật. 'clang 7.0.0' biên dịch nó, và có thể chạy như vậy. Tuy nhiên nếu 'printf ("% d \ n ", x);' được thêm vào sau 'int x = x;' (tôi đoán bất kỳ cách sử dụng thực tế nào của 'x'), trình biên dịch đưa ra cảnh báo thân thiện hơn:' warning: variable 'x' được uninitialized khi được sử dụng trong khởi tạo riêng của nó [-Wuninitialized] '. 'gcc' vẫn biên dịch và chạy nó ngay cả với' printf' và in '0'. Tuy nhiên chạy chương trình thông qua valgrind cho phép 'nhảy có điều kiện hoặc di chuyển phụ thuộc vào giá trị uninitialised (s)' – Joakim

+0

@Joakim: Thú vị; cảm ơn cho kết quả.GCC và Clang có thuộc quyền của họ, tức là hành vi này không được xác định theo kiểu kinh điển? –

Trả lời

51

x được định nghĩa ở bên trái của =.

như vậy trong x[x], [x] tham khảo một toàn cầu,

trong khi ở x = x;, x giấu toàn cầu x và khởi từ bản thân -> UB.

35

Khi bạn khai báo một biến mới, tên của nó trở nên rõ ràng ngay tại đây

int x = 
//  ^- there 

vì nó là tại thời điểm đó biến được đầy đủ tuyên bố, và như vậy; tên của nó có nghĩa là một cái gì đó. Tại thời điểm này, bất kỳ biến nào khác (được khai báo trước đây) trong phạm vi xung quanh sẽ bị ẩn đi.

5

Không có hành độ phân giải phạm vi trong C, do đó bạn sẽ không thể sử dụng

int x = x; 

trong chương trình của bạn.

+7

OP dường như không biết họ có muốn câu trả lời cho C hay cho C++ hay không. Sau này không hỗ trợ độ phân giải phạm vi. –

+0

Tôi nghĩ rằng nó biên dịch tôi đã kiểm tra nó trong ideone.com với trình biên dịch C ... – Aminos

+0

@underscore_d, có C + + hỗ trợ và C không. – Adi

1

hãy sử dụng SRO (Toán tử độ phân giải phạm vi: :) để cho trình biên dịch biết x là x thật trong tâm trí của bạn. Như người dùng định nghĩa tên là đọc sai (Tên được trang trí) một cái gì đó như thế này để tránh sự mơ hồ ở mức của nó, đây là những chỉ là tên được sử dụng bởi trình biên dịch phù hợp nhất với nó

int x = 15;// Real name = gui_x 
int main() 
{ 
    int x = x;// lui_x 
    return 0; 
} 

Bằng cách này chạy thời gian sẽ biết phiên bản bạn đang sử dụng nhưng để tránh sự mơ hồ, nó mong đợi từ bạn để sử dụng tên cụ thể. Đôi khi ở trên vấn đề phát sinh, nơi bạn không biết rằng bạn đang sử dụng tên đã được sử dụng. Đối với C++ này đã tạo ra SRO.
Bây giờ trong trường hợp mảng x là địa chỉ & không phải là số nguyên lưu trữ thứ gì đó, đó là lý do tại sao trình biên dịch không bị xáo trộn. Bạn cần phải viết

namespace abc //now all global variables are belongs to this ns abc 
int x = 15;// Real name = gui_x 
int main() 
{ 
int x = abc::x;// lui_x 
return 0; 
} 
Các vấn đề liên quan