Trong C, tôi có thích hằng số hơn định nghĩa không? Gần đây tôi đã đọc rất nhiều mã và tất cả các ví dụ đều sử dụng nhiều định nghĩa.Tôi có muốn các hằng số xác định không?
Trả lời
Không, nói chung bạn không nên sử dụng các đối tượng đủ điều kiện trong C để tạo các hằng số tên. Để tạo hằng số có tên trong C, bạn nên sử dụng macro (#define
) hoặc enums. Trong thực tế, ngôn ngữ C không có hằng số, theo nghĩa bạn có vẻ ngụ ý.(C là khác nhau đáng kể từ C++ trong lĩnh vực này)
Trong ngôn ngữ C các khái niệm của liên tục và liên tục biểu được định nghĩa rất khác so với C++. Trong C hằng số có nghĩa là giá trị bằng chữ, như 123
. Dưới đây là một số ví dụ về hằng trong C
123
34.58
'x'
hằng số trong C có thể được sử dụng để xây dựng biểu thức hằng số. Tuy nhiên, vì các đối tượng đủ điều kiện của bất kỳ loại nào không phải là một hằng số trong C, chúng không thể được sử dụng trong các biểu thức liên tục, và do đó, bạn không thể sử dụng các đối tượng đủ điều kiện.
Ví dụ, sau đây không phải là một hằng số
const int C = 123; /* C is not a constant!!! */
và kể từ khi trên C
không phải là một hằng số, nó không thể được sử dụng để khai báo một kiểu mảng trong phạm vi tập tin
typedef int TArray[C]; /* ERROR: constant expression required */
Nó không thể được sử dụng làm nhãn trường hợp
switch (i) {
case C: ; /* ERROR: constant expression required */
}
Nó không thể được sử dụng làm bit-fi chiều rộng lĩnh
struct S {
int f : C; /* ERROR: constant expression required */
};
Nó không thể được sử dụng như một initializer cho một đối tượng với thời gian lưu trữ tĩnh
static int i = C; /* ERROR: constant expression required */
Nó không thể được sử dụng như một enum initializer
enum {
E = C /* ERROR: constant expression required */
};
tức là nó không thể được sử dụng bất cứ nơi nào cần có hằng số.
Điều này có vẻ phản trực giác, nhưng đây là cách C ngôn ngữ được xác định.
Đây là lý do tại sao bạn thấy rất nhiều #define
-s trong mã bạn đang làm việc. Một lần nữa, trong ngôn ngữ C const-đủ điều kiện đối tượng có sử dụng rất hạn chế. Về cơ bản chúng hoàn toàn vô dụng như "hằng số", đó là lý do tại sao trong ngôn ngữ C bạn về cơ bản buộc phải sử dụng #define
hoặc enums để khai báo hằng số thực. Tất nhiên, trong các tình huống khi một đối tượng đủ điều kiện làm việc cho bạn, tức là nó làm những gì bạn muốn nó làm, nó thực sự vượt trội so với các macro theo nhiều cách, vì nó là phạm vi và gõ. Bạn có lẽ nên thích các đối tượng như vậy khi áp dụng, tuy nhiên trong trường hợp chung bạn sẽ phải tính đến các hạn chế trên.
+1 cho sự hiểu biết và khớp đúng với sự khác biệt C/C++, một điểm dường như bị mất trên nhiều người. – asveikau
Câu trả lời hay. Cảm ơn bạn đã nêu bật vấn đề với các biến 'đủ điều kiện để khai báo kích thước mảng. –
+1 Wow, câu trả lời tuyệt vời – helpermethod
Các hằng số nên được ưu tiên hơn define
s. Có một số ưu điểm:
Loại an toàn. Trong khi C là một yếu kém kiểu languaged, sử dụng một
define
mất tất cả các loại an toàn, mà sẽ cho phép trình biên dịch để nhận các vấn đề cho bạn.Dễ gỡ lỗi. Bạn có thể thay đổi giá trị hằng số thông qua trình gỡ lỗi, trong khi
define
s được tự động thay đổi trong mã bằng bộ xử lý trước thành giá trị thực tế, có nghĩa là nếu bạn muốn thay đổi giá trị cho mục đích thử nghiệm/gỡ lỗi, bạn cần phải biên dịch lại.
Tôi đã tìm thấy rằng nhiều trình biên dịch sẽ bake 'const static ints' vào các hằng số opcode ngay lập tức, giống như #defines, làm cho chúng không thể thay đổi trong trình gỡ rối. – Crashworks
@Crashworks - điều đó có phụ thuộc vào mức tối ưu hóa không? – LeopardSkinPillBoxHat
ngay cả khi tối ưu hóa trình biên dịch bị vô hiệu hóa? –
Nếu nó không được xác định theo chương trình, tôi sử dụng #define
. Ví dụ: nếu tôi muốn tất cả các đối tượng giao diện người dùng của mình có cùng khoảng cách giữa chúng, tôi có thể sử dụng #define kGUISpace 20
.
Xác định là một phần của ngôn ngữ dài hơn hằng số, vì vậy nhiều mã cũ hơn sẽ sử dụng chúng vì xác định cách duy nhất để hoàn thành công việc khi mã được viết. Đối với mã gần đây hơn, nó có thể chỉ đơn giản là một vấn đề của thói quen lập trình viên.
Hằng số có loại cũng như giá trị, vì vậy chúng sẽ được ưu tiên khi giá trị của bạn có giá trị, nhưng không phải khi giá trị không có kiểu (hoặc đa hình).
Có lẽ tôi đã sử dụng chúng sai, nhưng ít nhất trong gcc, bạn không thể sử dụng hằng số trong trường hợp báo cáo.
const int A=12;
switch (argc) {
case A:
break;
}
xác định có thể được sử dụng cho nhiều mục đích (rất lỏng lẻo) và nên tránh nếu bạn có thể thay thế bằng const, xác định biến và bạn có thể làm được nhiều hơn.
Trong những trường hợp như dưới đây, xác định phải được sử dụng
- chỉ thị chuyển đổi
- thay vào dòng nguồn của bạn
- macro đang
Một ví dụ mà bạn phải sử dụng định nghĩa trên const là khi bạn có số phiên bản nói 3 và bạn muốn phiên bản 4 bao gồm một số phương thức không có sẵn trong phiên bản 3
#define VERSION 4
...
#if VERSION==4
................
#endif
Rất nhiều người ở đây đang cung cấp cho bạn lời khuyên "kiểu C++". Một số thậm chí nói rằng các đối số C++ áp dụng cho C. Đó có thể là một điểm công bằng. (Cho dù đó là hoặc không cảm thấy loại chủ quan.) Những người nói const
đôi khi có nghĩa là một cái gì đó khác nhau trong hai ngôn ngữ cũng chính xác.
Nhưng đây chủ yếu là những điểm nhỏ và cá nhân, tôi nghĩ sự thật có hậu quả tương đối nhỏ để đi theo một trong hai cách.Đó là vấn đề về phong cách, và tôi nghĩ rằng những nhóm người khác nhau sẽ cho bạn những câu trả lời khác nhau.
Về mặt sử dụng phổ biến, mức sử dụng lịch sử và phong cách phổ biến nhất, trong C, sẽ điển hình hơn khi xem #define
. Sử dụng C++ isms trong mã C có thể đi ra như là lạ đối với một phân đoạn hẹp nhất định của C coders. (Bao gồm cả tôi, vì vậy đó là nơi thiên vị của tôi nằm.)
Nhưng tôi ngạc nhiên không ai đề xuất giải pháp nền tảng trung bình, "cảm thấy đúng" ở cả hai ngôn ngữ: nếu nó phù hợp với một nhóm hằng số nguyên, sử dụng an enum
.
Ngoài những lý do tuyệt vời do AndreyT đưa ra để sử dụng DEFINES thay vì các hằng số trong mã "C", có một lý do thực dụng khác để sử dụng DEFINES.
DEFINES dễ định nghĩa và sử dụng các tệp tiêu đề (.h), là nơi mà bất kỳ trình mã hóa C có kinh nghiệm nào mong đợi tìm các hằng số được xác định. Việc xác định các const trong các tệp tiêu đề không hoàn toàn dễ dàng như vậy - nhiều mã hơn để tránh các định nghĩa trùng lặp, v.v.
Các đối số "typesafe" là hầu hết các trình biên dịch sẽ nhận các lỗi rõ ràng như assing string và int, hoặc , sẽ "làm điều đúng" trên một chút không khớp như gán một số nguyên cho một phao.
Macro (định nghĩa) có thể được sử dụng bởi bộ xử lý trước và tại thời gian biên dịch, hằng số không thể.
Bạn có thể thực hiện kiểm tra thời gian biên dịch để đảm bảo macro nằm trong phạm vi hợp lệ (và #error hoặC#fatal nếu không). Bạn có thể sử dụng giá trị mặc định cho macro nếu macro chưa được xác định. Bạn có thể sử dụng macro trong kích thước của một mảng.
Một trình biên dịch có thể tối ưu hóa với các macro tốt hơn so với những gì có thể với các hằng số:
const int SIZE_A = 15;
#define SIZE_B 15
for (i = 0; i < SIZE_A + 1; ++i); // if not optimized may load A and add 1 on each pass
for (i = 0; i < SIZE_B + 1; ++i); // compiler will replace "SIZE_B + 1" with 16
Hầu hết các công việc của tôi là với các bộ xử lý nhúng mà không có trình biên dịch tối ưu hóa tuyệt vời. Có thể gcc sẽ xử lý SIZE_A như macro ở cấp độ tối ưu hóa nào đó.
Mặc dù câu hỏi này là cụ thể cho C, tôi đoán nó là tốt để biết điều này:
#include<stdio.h>
int main() {
const int CON = 123;
int* A = &CON;
(*A)++;
printf("%d\n", CON); // 124 in C
}
công trình trong C, nhưng không phải trong C++
Một trong những lý do để sử dụng #define
là để tránh những điều như vậy để làm rối tung mã của bạn, đặc biệt nó là sự kết hợp giữa C và C++.
+1 Mẹo hay, không biết điều đó. – helpermethod
Không sử dụng con trỏ để thay đổi chỉ đọc int trong C undefined hành vi? –
- 1. Có thể định nghĩa các hằng số trong css không?
- 2. Xác định hằng số lớp trong PHP
- 3. Lỗi xác định hằng số trong Delphi
- 4. Xác định các hằng số quá tải trong Isabelle
- 5. Xác định lại các hằng số trong PHP
- 6. Lỗi OSX Homebrew: hằng số không xác định MACOS
- 7. Có hằng số xác định giá trị cực đại của số nguyên dài hay không?
- 8. Tại sao 'được xác định() || xác định 'cú pháp trong việc xác định một hằng số
- 9. Xác định hằng số ứng dụng trong Codeigniter
- 10. Xác định TRACE Hằng số trong .NET/Visual Studio
- 11. Cách xác định hằng số thành viên loại trong F #?
- 12. Tại sao tôi có thể thay đổi các hằng số?
- 13. Lỗi PHP - Hằng số DB_HOST đã được xác định?
- 14. Tên chuẩn không có các hằng số được đặt tên
- 15. Bạn có thể xác định hoặc thay đổi một hằng số trong PHP không?
- 16. Kiểm tra xem hằng số đã được xác định chưa
- 17. Có phải tiêu chuẩn cho #if để giả sử các hằng số biểu tượng không xác định là 0 không?
- 18. Các tham số hàm mặc định có phải là hằng số trong C++ không?
- 19. Tôi có thể có macro C chấp nhận số tham số không xác định không?
- 20. Làm thế nào để tôi tìm được một hằng số được xác định trong Ruby?
- 21. Lưu ý: Sử dụng hằng số không xác định ENT_HTML5 - giả định 'ENT_HTML5'
- 22. Lưu ý: Sử dụng hằng số không xác định STDOUT - giả định 'STDOUT'
- 23. Nếu tôi muốn xác định định dạng tệp, tôi sẽ làm như thế nào?
- 24. Định lượng hằng số Haskell chi tiết
- 25. Xác định hằng unichar trong mã
- 26. C++ cách tốt nhất để xác định các hằng số thập phân
- 27. Lớp với các giá trị hằng số tĩnh được xác định trong Mục tiêu-C
- 28. Làm cách nào để xác định các hằng số trong một tệp riêng biệt trong Perl?
- 29. Làm thế nào để xác định lại một hằng số Ruby mà không cần cảnh báo?
- 30. Kiểm tra xem hằng số có được xác định tại thời gian chạy theo Obj-C
Hãy cảnh giác với hội chứng Stockholm! – Potatoswatter
[Câu trả lời này] (http://stackoverflow.com/a/1674459/2235567) có liên quan. –
có thể trùng lặp của ["const tĩnh" và "#define" trong C] (http://stackoverflow.com/questions/1674032/static-const-vs-define-in-c) –