2015-01-07 12 views
7

Hành vi được xác định cho một cái gì đó như sau?Biến có tên giống như điều tra

#include <stdio.h> 

typedef enum { 
    ENUM_VAL_1 = 1, 
    ENUM_VAL_2 = 2 
} TEST_ENUM; 

int main() { 
    TEST_ENUM testVar1 = ENUM_VAL_1; 
    TEST_ENUM ENUM_VAL_1 = ENUM_VAL_1; 
    TEST_ENUM testVar2 = ENUM_VAL_1; 

    printf("ENUM_VAL_1 = %u\n",ENUM_VAL_1); 
    printf("testVar1 = %u\n",testVar1); 
    printf("testVar2 = %u\n",testVar2); 

    return 0; 
} 

Từ thử nghiệm của tôi với cả GCC và MSVC trình biên dịch, hành vi của việc này là testVar1 sẽ được thiết lập bằng giá trị liệt kê "ENUM_VAL_1" hoặc 1. Tuy nhiên, báo cáo kết quả tiếp theo sẽ cố gắng thiết lập các ENUM_VAL_1 biến bằng giá trị riêng của nó, tất nhiên là hiện tại chưa được khởi tạo và do đó rác, thay vì thiết lập biến ENUM_VAL_1 bằng giá trị điều tra ENUM_VAL_1. Sau đó, tất nhiên, testVar2 cũng sẽ nhận được cùng một giá trị rác như biến ENUM_VAL_1.

Hành vi được xác định là gì theo tiêu chuẩn C hoặc hành vi không xác định này? Dù nó có được xác định hay không, tôi đoán loại ví dụ này là thực hành tồi tệ ít nhất là do sự mơ hồ.

Cảm ơn!

+1

Bạn nên cập nhật tiêu đề của chủ đề bằng cách thay thế liệt kê từ cho điều tra từ. –

Trả lời

6

Theo C chuẩn (6.2.1 Lĩnh vực định danh)

  1. ... Nếu một định danh chỉ định hai thực thể khác nhau trong không gian cùng tên, phạm vi có thể chồng lên nhau. Nếu vậy, phạm vi của một thực thể (phạm vi bên trong) sẽ kết thúc nghiêm ngặt trước phạm vi của thực thể khác (phạm vi bên ngoài). Trong phạm vi bên trong, mã định danh chỉ định đối tượng được khai báo trong phạm vi bên trong; đối tượng được khai báo trong phạm vi bên ngoài bị ẩn (và không hiển thị) trong phạm vi bên trong .

7 Cấu trúc, công đoàn, và đếm thẻ có phạm vi mà chỉ bắt đầu sau khi sự xuất hiện của thẻ trong một Bộ xác định kiểu khai báo thẻ . Mỗi hằng số liệt kê có phạm vi bắt đầu ngay sau khi xuất hiện của điều tra xác định của nó trong danh sách điều tra viên.Bất kỳ số nhận dạng khác có phạm vi mà bắt đầu ngay sau khi hoàn thành declarator nó

Vì vậy, trong tuyên bố này

TEST_ENUM ENUM_VAL_1 = ENUM_VAL_1; 

declarator ENUM_VAL_1 được coi là hoàn thành trước dấu =. Vì vậy, nó giấu điều tra.

Thực tế nó được khởi tạo bởi chính nó và có giá trị không xác định.

Điều này cũng có giá trị trong C++ (3.3.2 Point kê khai)

1 Điểm kê khai cho một tên là ngay sau khi declarator hoàn chỉnh của nó (khoản 8) và trước khi khởi tạo của nó (nếu có), ngoại trừ được ghi chú bên dưới. [Ví dụ:

int x = 12; 
{ int x = x; } 

Ở đây x thứ hai được khởi tạo với giá trị (không xác định) của riêng mình. —dí dụ ví dụ]

+0

Câu trả lời rất đầy đủ và toàn diện - cảm ơn bạn! –

3

Tôi đã mong đợi đường dây TEST_ENUM ENUM_VAL_1 = ENUM_VAL_1; không thể biên dịch được, nhưng thực tế. Tôi đã thay đổi giá trị được gán thành ENUM_VAL_2 và sau đó in cho ENUM_VAL_1 = 2, testVar1 = 1testVar2 = 2, vì vậy ENUM_VAL_1 là một biến cục bộ.

Đây thực sự là vấn đề về phạm vi thông thường; nó có nghĩa là khai báo biến trong main() tô bóng khai báo bên ngoài — và nếu typedef nằm trong phạm vi main(), mã sẽ không biên dịch. Thêm -Wshadow vào các tùy chọn biên dịch của bạn để xem hình bóng. Sau khi đặt testVar1, ENUM_VAL_1 có nghĩa là biến cục bộ, không phải là hằng số liệt kê. Khởi tạo một biến với chính nó không thực sự khởi tạo biến; nó sao chép rác không xác định vào giá trị.

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