Đầu tiên, tôi nhận thấy rằng không thể xác định loại hằng số bằng #define, tại sao vậy?
Tại sao là gì? Nó không đúng:
#define MY_INT_CONSTANT ((int) 12345)
Thứ hai, có bất kỳ lợi ích nào khi sử dụng một trong số chúng so với một trong số chúng không?
Đúng. #define
định nghĩa một macro được thay thế ngay cả trước khi bắt đầu biên dịch. const
chỉ sửa đổi một biến để trình biên dịch sẽ gắn cờ lỗi nếu bạn cố gắng thay đổi nó. Có những ngữ cảnh mà bạn có thể sử dụng #define
nhưng bạn không thể sử dụng a const
(mặc dù tôi đang cố gắng tìm một ngữ cảnh bằng cách sử dụng clang mới nhất). Về lý thuyết, một const
chiếm không gian trong tệp thực thi và yêu cầu tham chiếu đến bộ nhớ, nhưng trên thực tế, điều này là không đáng kể và có thể được tối ưu hóa bởi trình biên dịch.
const
s thân thiện với trình biên dịch và trình gỡ lỗi hơn #define
s. Trong hầu hết các trường hợp, đây là điểm quan trọng mà bạn nên cân nhắc khi đưa ra quyết định sử dụng cái nào.
Chỉ nghĩ về một ngữ cảnh mà bạn có thể sử dụng #define
nhưng không const
. Nếu bạn có một hằng số mà bạn muốn sử dụng trong nhiều .c
tệp, với một hằng số , #define
bạn chỉ cần dán nó vào tiêu đề. Với một, const
bạn phải có định nghĩa trong tệp C và
const int MY_INT_CONST = 12345;
extern const int MY_INT_CONST;
trong tiêu đề. MY_INT_CONST
không thể được sử dụng làm kích thước của mảng phạm vi tĩnh hoặc toàn cục trong bất kỳ tệp C nào ngoại trừ tệp được định nghĩa trong đó.
Tuy nhiên, đối với các hằng số nguyên, bạn có thể sử dụng một enum
. Trên thực tế, đó là điều mà Apple gần như luôn làm. Điều này có tất cả các ưu điểm của cả #define
s và const
s nhưng chỉ hoạt động đối với các hằng số nguyên.
enum
{
MY_INT_CONST = 12345,
};
Cuối cùng, cách nào hiệu quả hơn và / hoặc an toàn hơn?
#define
là hiệu quả hơn về mặt lý thuyết mặc dù, như tôi đã nói, các trình biên dịch hiện đại có lẽ đảm bảo có rất ít sự khác biệt. #define
an toàn hơn ở chỗ nó luôn là lỗi trình biên dịch khi cố gắng gán cho nó
#define FOO 5
FOO = 6;
const
s có thể bị lừa để được gán mặc dù trình biên dịch có thể đưa ra cảnh báo:
const int FOO = 5;
(int) FOO = 6;
Tùy thuộc vào nền tảng, việc gán vẫn có thể không thành công trong thời gian chạy nếu hằng số được đặt trong phân đoạn chỉ đọc và hành vi chính thức không được xác định theo tiêu chuẩn C.
Cá nhân, đối với các hằng số nguyên, tôi luôn sử dụng enum
s cho các hằng số kiểu khác, tôi sử dụng const
trừ khi tôi có lý do chính đáng để không.