2012-04-09 41 views
7

Tôi hiện đang nghiên cứu bài kiểm tra cuối khóa của khóa học CS và tôi đã gặp phải vấn đề nhỏ (có thể là lớn?) Liên quan đến cú pháp của C++ #ifndef.#ifndef cú pháp cho bao gồm bảo vệ trong C++

Tôi đã nhìn vào cú pháp cho #infndef khi sử dụng nó như là một bảo vệ #include, và hầu hết trên web dường như nói:

#ifndef HEADER_H 
#define "header.h" 
... 
#endif 

Nhưng slide hướng dẫn lớp học của tôi hiển thị ví dụ như:

#ifndef __HEADER_H__ 
#define "header.h" 
... 
#endif 

Tôi đã tự hỏi điều gì (nếu có) sự khác biệt giữa hai người. Bài kiểm tra rất có thể sẽ yêu cầu tôi viết một bảo vệ bao gồm, và tôi biết sự khôn ngoan thông thường là chỉ cần đi với những gì các giáo sư/giảng viên nói, nhưng nếu có một sự khác biệt trong quá trình biên dịch tôi muốn biết.

+5

Xem [tại đây] (http://stackoverflow.com/questions/228783) để thảo luận về các quy tắc mà gia sư của bạn đang vi phạm và [ở đây] (http://stackoverflow.com/questions/3345159) cho một Ví dụ những gì có thể đi sai nếu bạn phá vỡ chúng. Ngoài ra, bao gồm cả bảo vệ đi * bên trong * tiêu đề. –

+0

Vì nó là, mã inculded không có ý nghĩa: bạn không thể '# define' một chuỗi chữ. Ý của bạn có phải là '#include 'header.h" '(từ gốc) hay' #define HEADER_H' (những gì thường nằm trong phần đầu của phần đầu)? – Attila

Trả lời

17

Thực hành thông thường là không thực hiện và đặt bảo vệ bao gồm vào bên trong tệp tiêu đề, vì nó làm giảm sự lặp lại. ví dụ .:

header.h

#ifndef HEADER_H 
#define HEADER_H 

// Rest of header file contents go here 

#endif 

chính xác những gì bạn sử dụng như tên macro là xuống đến tiêu chuẩn mã hóa cụ thể của bạn. Tuy nhiên, có các quy tắc tinh tế khác nhau trong tiêu chuẩn C và C++ ngăn bạn sử dụng số nhận dạng bắt đầu bằng dấu gạch dưới, vì vậy bạn nên tránh __HEADER_H__, chỉ để an toàn.

Điều đáng nói là bạn nên chọn thứ gì đó không có khả năng đụng độ với bất kỳ điều gì khác trong codebase của bạn. Ví dụ: nếu bạn tình cờ có một biến được gọi là HEADER_H ở nơi khác (không, tôi nhận ra), thì bạn sẽ kết thúc với một số lỗi đáng lo ngại.


1. Xem ví dụ: phần 7.1.3 của tiêu chuẩn C99.

+1

... và nếu đó không phải là tệp tiêu đề triển khai, nó sẽ tránh các số nhận dạng chứa dấu gạch dưới theo sau là một dấu gạch dưới hoặc chữ cái viết hoa khác. –

+0

@JerryCoffin: "chứa" hoặc "bắt đầu bằng"? –

+0

Đối với C, bắt đầu. Đối với C++, có chứa một dấu gạch dưới tăng gấp đôi là verboten là tốt (nhưng gạch dưới theo sau là cap được cho phép miễn là nó không phải lúc đầu). –

1

Không có sự khác biệt nếu bạn không sử dụng gạch dưới trong tên biến ở bất kỳ nơi nào khác, nó chỉ là quy ước đặt tên.

Bạn chỉ cần đặt thứ gì đó độc đáo.

+4

Không đúng sự thật. Tên bắt đầu bằng hai dấu gạch dưới được dành riêng cho việc triển khai (trong C99, ít nhất). –

+1

+1: Thực sự trả lời câu hỏi của OP thay vì nêu rõ cách "thông thường" của việc làm. –

+4

Nó không chỉ là một quy ước. Sử dụng từ định danh bắt đầu bằng '__' làm cho hành vi của mã của bạn không được xác định. Việc thực hiện (hoặc trình biên dịch hoặc thư viện chuẩn) là miễn phí để sử dụng tên '__HEADER_H__' cho mục đích riêng của nó; nếu nó làm như vậy, sử dụng của riêng bạn của định danh đó có thể có nghĩa là * bất cứ điều gì *. –

5

Tên bắt đầu bằng dấu gạch dưới kép được dành riêng cho việc triển khai, vì vậy, tôi khuyên bạn không nên sử dụng __SOMETHING trong các nhân viên bảo vệ của bạn. Ngoài ra, hãy cố gắng chọn tên mà làm cho các cuộc đụng độ khó xảy ra. Vì vậy, có vẻ như hướng dẫn của lớp học của bạn sai về ít nhất hai lần đếm. Xem ví dụ này humorous article.

0

Một đối số cho việc đưa các bộ bảo vệ vào tệp chứa tiêu đề, thay vì trong chính phần đầu, là nếu tệp đã được bao gồm trình biên dịch (cụ thể bộ tiền xử lý) không phải mở và đọc bao gồm lại tệp.

Đó là một đối số yếu. Trong thực tế, thời gian được lưu là tầm thường, và khả năng xảy ra lỗi lớn.

Trong ví dụ của bạn:

#ifndef HEADER_H 
#include "header.h" 
... 
#endif 

bạn không cho chúng ta thấy #define HEADER_H. Có ở đâu đó trong số header.h không?Nếu vậy, làm thế nào để bạn biết rằng tác giả của header.h chọn sử dụng HEADER_H làm tên của macro bảo vệ bao gồm? Điều gì sẽ xảy ra nếu nó thay đổi một cái gì đó khác sau này?

Nếu bạn quyết định đặt bao gồm bảo vệ trong đó có tập tin, bạn nên xác định vĩ mô đó là tốt:

#ifndef HEADER_H 
#include "header.h" 
#define HEADER_H 
#endif 

Nhưng, như câu trả lời khác đã nói, nó tốt hơn nhiều để đưa bảo vệ trong tiêu đề riêng của mình:

header.h:

#ifndef HEADER_H 
#define HEADER_H 
/* contents of header.h */ 
#endif 

và sau đó bao gồm chỉ đơn giản là có:

#include "header.h" 

và có ít thông tin hơn cần lo lắng.

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