Biến và kiểu dữ liệu đã thảo luận. Bây giờ xem cách phân loại biến theo phạm vi và khả năng thấy.
Phạm vi (Scope): Là thuật ngữ chỉ vòng đời biến. Biến sống bao lâu và khi nào bị hủy.
Khả năng thấy (Visibility): Cho thấy từ đâu biến có thể thấy, đâu có thể dùng biến. Ví dụ biến cục bộ không dùng từ hàm/file khác, chỉ thấy trong khối.
Khối (Block): Tập các dòng giữa hai ngoặc nhọn {…}. Ví dụ:
{ //dòng1 //dòng2 //dòng3 }Đây là một khối.
| Lớp lưu trữ | Cách khai báo | Phạm vi | Khả năng thấy |
|---|---|---|---|
| auto | Toàn cục | ||
| auto | Cục bộ | Khối | Khối |
| register | Toàn cục | ||
| register | Cục bộ | Khối | Khối |
| static | Toàn cục | Chương trình | Tệp |
| static | Cục bộ | Chương trình | Khối |
| extern | Toàn cục | Chương trình | Chương trình |
| extern | Cục bộ | Chương trình | Khối |
Cú pháp cơ bản lớp lưu trữ:
<storage class> <datatype> variable_name; ví dụ: static int my_var = 0;
Lưu ý: Nếu dùng <datatype> variable_name; không chỉ định lớp lưu trữ, tự động là lớp auto.
Auto: Lớp lưu trữ mặc định cho tất cả biến cục bộ.
{
int mount;
auto int month;
}Ví dụ trên định nghĩa hai biến cùng lớp lưu trữ. 'auto' chỉ dùng trong hàm, tức biến cục bộ.
Register: Dùng cho biến cục bộ nên lưu trong thanh ghi thay vì RAM. Nghĩa là biến có kích thước tối đa bằng thanh ghi (thường một word) và không thể áp dụng toán tử '&' đơn mục (vì không có vị trí bộ nhớ).
{
register int miles;
}Register chỉ nên dùng cho biến cần truy xuất nhanh như bộ đếm. Cũng lưu ý: khai báo 'register' không đảm bảo biến lưu trong thanh ghi. Chỉ có nghĩa là nó CÓ THỂ lưu trong thanh ghi tùy phần cứng và triển khai.
Static: Lớp static yêu cầu trình biên dịch giữ biến cục bộ tồn tại suốt vòng đời chương trình thay vì tạo/hủy mỗi lần vào/ra phạm vi. Do đó, biến cục bộ static giữ giá trị giữa các lần gọi hàm.
Static cũng áp dụng cho biến toàn cục. Khi đó, nó giới hạn phạm vi biến trong tệp khai báo.
Trong C, khi static dùng trên biến toàn cục, nó khiến chỉ một bản sao thành viên được chia sẻ bởi tất cả đối tượng của lớp.
Ví dụ mã
#include <stdio.h>
/* khai báo hàm */
void func(void);
static int count = 5; /* biến toàn cục */
main() {
while(count--) {
func();
}
return 0;
}
/* định nghĩa hàm */
void func(void) {
static int i = 5; /* biến cục bộ static */
i++;
printf("i is %d and count is %d\n", i, count);
}Kết quả
i is 6 and count is 4 i is 7 and count is 3 i is 8 and count is 2 i is 9 and count is 1 i is 10 and count is 0
Extern: Lớp extern dùng để tham chiếu biến toàn cục thấy được bởi TẤT CẢ tệp chương trình. Khi dùng 'extern', biến không thể khởi tạo, nhưng nó trỏ tên biến đến vị trí bộ nhớ đã định nghĩa trước.
Khi có nhiều tệp và định nghĩa biến/hàm toàn cục dùng ở tệp khác, extern dùng ở tệp khác để tham chiếu biến/hàm đã định nghĩa. Vừa hiểu: extern khai báo biến/hàm toàn cục ở tệp khác.
Modifier extern thường dùng khi có hai hoặc nhiều tệp chia sẻ biến/hàm toàn cục như giải thích dưới đây.
Ví dụ mã (main.c):
#include <stdio.h>
int count;
extern void write_extern();
main() {
count = 5;
write_extern();
}Ví dụ mã (support.c):
#include <stdio.h>
extern int count;
void write_extern(void) {
printf("count is %d\n", count);
}Kết quả
count is 5