2017-02-02 17 views
9

Tôi đã nhìn thấy một câu hỏi tương tự được hỏi wrt C++, Does redeclaring variables in C++ cost anything?Xác định lại các biến trong C

Nhưng còn C thì sao? Sẽ redeclaring một biến trong C có bất kỳ ảnh hưởng đáng chú ý? Điều này thường được coi là tổ chức mã xấu?

for(;;) { 
    int y = 1 + 2 + 3; // some kind of repeated redeclaration? 
} 

EDIT:

Tăng cường hỏi của tôi.

Nếu tôi có vòng lặp trong hàm, sẽ gọi 'int y = 1 + 2 + 3;' hơn và hơn nữa được phép? Nó có gây ra vấn đề không? Nó làm gì, khai báo y một lần?

+0

không rõ bạn đang hỏi gì. Nếu câu hỏi của bạn cho dù tuyên bố int y trong một vòng lặp chi phí nhiều hơn bên ngoài vòng lặp - không, nó không. –

+0

@CinCout tất nhiên bạn có thể. –

+0

Bạn có thể đặt biến trong phạm vi cục bộ có cùng tên với biến trong phạm vi toàn cục. Trong trường hợp này, bạn sẽ không thể truy cập vào biến toàn cầu y bên trong vòng lặp – bruceg

Trả lời

5

C ngôn ngữ có khái niệm về biến phạm vi. Tóm lại, mỗi cặp {} giới thiệu phạm vi mới và các biến được ràng buộc với các phạm vi đó. Bạn có thể khai báo các biến có cùng tên, miễn là chúng nằm trong các phạm vi khác nhau.

Đó là lý do tại sao bạn đó là hợp lệ:

if(...) { 
    int y; # y is valid here 
}   # end of scope, y is not valid here 
if(...) { # new scope 
    int y; # That's another y 
} 

Và đó là không hợp lệ:

if(...) { 
    int y; 
    int y; # error, redeclaration 
} 

Hơn nữa khai là một tài sản mã nguồn, không phải thời gian chạy sở hữu chương trình.

Vì vậy, nếu bạn viết:

for(;;) { 
    int y = 1 + 2 + 3; 
} 

Bạn khai báo ylần (vì bạn đã viết nó một lần), không phải vô số lần.

4

Hầu hết các trình biên dịch C tối ưu hóa mọi thứ mà họ có thể.

Nếu bạn muốn thực sự tìm ra biên dịch với cờ để xem mã lắp ráp và xem nó đang làm gì. Giống như ai đó đã nói nếu đó là kiểu đơn giản (không có hàm tạo), và đặc biệt nếu bạn đang sử dụng tất cả các chữ, trình biên dịch có thể sẽ di chuyển một giá trị cố định vào sổ đăng ký mỗi lần lặp hoặc thậm chí không bận tâm nếu không có gì thay đổi giữa các lần lặp

Tôi vừa kiểm tra ví dụ của bạn như được hiển thị bên dưới và cũng thay đổi nó để sửa đổi biến trong vòng lặp và bạn có thể xem mã lắp ráp đã tạo thay đổi như thế nào.

Trong ví dụ đầu tiên, lưu ý vòng lặp tại LBB0_1, đó chỉ là lệnh movl.

Trong ví dụ thứ 2, nó vẫn còn khá đơn giản, nhưng mặc dù kết quả không được sử dụng, nó vẫn lưu mọi thứ trên ngăn xếp. Tôi đã thêm một số ý kiến ​​để giải thích những gì vòng lặp đang làm.

$ cc -fno-không đồng bộ-Thư giãn-bảng -S dummy.c

int main(void) { 
    for(;;) { 
     int y = 1 + 2 + 3; 
    } 
} 

$ cat dummy.s

.section __TEXT,__text,regular,pure_instructions 
    .macosx_version_min 10, 12 
    .globl _main 
    .align 4, 0x90 
_main:         ## @main 
## BB#0: 
    pushq %rbp 
    movq %rsp, %rbp 
    movl $0, -4(%rbp) 
LBB0_1:         ## =>This Inner Loop Header: Depth=1 
    movl $6, -8(%rbp) 
    jmp LBB0_1 

.subsections_via_symbols 

$ cc -fno-asynchronous- relax-tables -S dummy.c

int main(void) { 
    int i = 0; 
    for(;;) { 
     int y = i + 2 + 3; 
     i++; 
    } 
} 

$ cat dummy.s

 .section  __TEXT,__text,regular,pure_instructions 
     .macosx_version_min 10, 12 
     .globl _main 
     .align 4, 0x90 
_main:         ## @main 
## BB#0: 
     pushq %rbp 
     movq %rsp, %rbp 
     movl $0, -4(%rbp)    
     movl $0, -8(%rbp)   ## i = 0 
LBB0_1:         
     movl -8(%rbp), %eax   ## y = i 
     addl $2, %eax    ## y += 2 
     addl $3, %eax    ## y += 3 
     movl %eax, -12(%rbp)   ## -12(rbp) = y 
     movl -8(%rbp), %eax   ## eax = i 
     addl $1, %eax    ## i++ 
     movl %eax, -8(%rbp)   ## -8(rbp) = i 
     jmp  LBB0_1 

.subsections_via_symbols 
+0

Cảm ơn- điều này rất hữu ích để biết cách thực hiện. – visc

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