30/09/2018, 16:01

Hỏi về #pragma trong khai báo thư viện c++

Em đang muốn biết thêm về #pragma once, anh chị nào có thể giúp em được không ạ? Càng nhiều thông tin dễ hiểu càng tốt :))

Nguyễn Minh Dũng viết 18:06 ngày 30/09/2018

Anh nhớ anh giải thích cái này ở đâu đó rồi, chắc trên Facebook.

#pragma là gì?

#pragma nói chung cũng là một tiền xử lý, nó sẽ được thực thi trước khi việc compile xảy ra. Em xem lại phần C của anh có nói về tiền xử lý.

Đăng ký khóa học C++ cơ bản 2016 ( NEW ) tại đây : Thông tin về khóa học xem tại đây : -Sự khác biệt giữa 2 khóa học cũ và mới : +Khóa học C++ cơ bản 2016 là khóa học mới, được đầu tư nhiều hơn từ nội dung, phương pháp học, cách học hiệu quả. +Trong khóa học còn có nhiều kiến thức mới như thực hành trên HackerRank, thực hành trên Codefights và Đạt nghĩ mọi người nên học khóa học mới, bởi vì đây là kiến thức mới, phù hợp với hiện tại..... Mặt khác âm thanh cũng tốt hơn nhiều so với khóa học …

#pragma once là gì?

Có nhiều loại lệnh bắt đầu bằng #pragma mà trong đó #pragma once được sử dụng nhiều nhất, được nhiều compiler hỗ trợ. Tuy nhiên #pragma once không phải là chuẩn.

Bài này a có nói về chuẩn và không chuẩn

Đăng ký khóa học C++ cơ bản 2016 ( NEW ) tại đây : Thông tin về khóa học xem tại đây : -Sự khác biệt giữa 2 khóa học cũ và mới : +Khóa học C++ cơ bản 2016 là khóa học mới, được đầu tư nhiều hơn từ nội dung, phương pháp học, cách học hiệu quả. +Trong khóa học còn có nhiều kiến thức mới như thực hành trên HackerRank, thực hành trên Codefights và Đạt nghĩ mọi người nên học khóa học mới, bởi vì đây là kiến thức mới, phù hợp với hiện tại..... Mặt khác âm thanh cũng tốt hơn nhiều so với khóa học …

Công dụng của #pragma once là để tránh việc include trùng lặp. Trong tiếng Anh, once có nghĩa là một lần. #pragma once đảm bảo cho việc include một file, một lần duy nhất. Ví dụ như sau lấy từ Wikipedia

Wikiwand

pragma once | Wikiwand

In the C and C++ programming languages, #pragma once is a non-standard but widely supported preprocessor directive designed to cause the current source file to be included only once in a single compilation. Thus, #pragma once serves the same purpose...

File “grandparent.h”

#pragma once
 
struct foo 
{
    int member;
};

File “parent.h”

#include "grandparent.h"

File “child.c”

#include "grandparent.h"
#include "parent.h"

File child.c vừa include parent.h vừa include grandparent.h. Chú ý một điều là parent.h đã include grandparent.h. Điều này dẫn đến child.c sẽ include grandparent.h hai lần. Như vậy sẽ dẫn đến lỗi nếu có khai báo biến ở file grandparent.h. Lỗi đó gọi là lỗi khai báo nhiều lần redefinition.

Để tránh lỗi xảy ra do include nhiều hơn một lần. Ta thêm #pragma once ở file grandparent.h. Trước khi compiler thực hiện compile, thì tiền xử lý sẽ đảm bảo child.c chỉ include grandparent.h một lần.

Cách khác để tránh include nhiều lần

Vậy nếu nói #pragma once không phải là chuẩn. Vậy chuẩn thì dùng cái nào? Ta dùng như sau

File "grandparent.h"
#ifndef _GRANDPARENT_H // Nếu chưa định nghĩa _GRANDPARENT_H 
#define _GRANDPARENT_H // thì định nghĩa _GRANDPARENT_H 
... nội dung của grandparent.h
#endif /* !_GRANDPARENT_H */ // chấm dứt

Ở đoạn code trên, người ta dùng một cái mẹo có sẵn trong C. Đó là người ta dùng tiền xử lý #ifndef, có nghĩa là if not define == nếu chưa định nghĩa. Thì mới định nghĩa cái đoạn bên trong của file đó, tức là phần nội dung của grandparent.h.

Giải thích khi ta include 1 file nhiều lần, như ví dụ trên

  • File child.c include grandparent.h lần đầu thì nội dung của grandparent.h sẽ được include
  • Khi File child.c include grandparent.h lần tiếp theo thì nội dung của grandparent.h sẽ không được include nữa, vì bây giờ _GRANDPARENT_H đã được định nghĩa.

Vậy _GRANDPARENT_H là gì? Thực ra đây là một cái mẹo thôi, tên file gốc là grandparent.h thì ta thêm một _ ở trước và thay dấu . bằng _. Tất cả các chữ cái viết hoa lên hết là được _GRANDPARENT_H.

Tò_mò_IT viết 18:01 ngày 30/09/2018

Dạ, em cảm ơn…còn nhiều thắc mắt nữa mong sẽ đc anh giải đáp lần sau . cái này hơi dài, e đọc chỉ hiểu dc sơ sơ, anh nói chi tiết, liên quan đến nhiều thứ quá làm e hơi rối.
#pragma once chỉ dùng để tránh include “thư viện.h”(theo em hiểu đây là thư viện tự tạo) nhiều lần, hay là tất cả các thư viện chuẩn của c++ ạ ?

Nguyễn Minh Dũng viết 18:16 ngày 30/09/2018

theo em hiểu đây là thư viện tự tạo

Thư viện hệ thống họ có làm sẵn cái cách khác để tránh include nhiều lần rồi.

Sáng Béo viết 18:02 ngày 30/09/2018

Vậy _GRANDPARENT_H là gì? Thực ra đây là một cái mẹo thôi, tên file gốc là grandparent.h thì ta thêm một _ ở trước và thay dấu . bằng _. Tất cả các chữ cái viết hoa lên hết là được _GRANDPARENT_H.

thế rốt cuộc cái này là gì hả a?

Nguyễn Minh Dũng viết 18:10 ngày 30/09/2018

Cái này là một #define thôi, không có ý nghĩa gì cả. Nhưng nó sẽ giúp cho mình đảm bảo file grandparent.h không bị include hai lần.

Sáng Béo viết 18:01 ngày 30/09/2018

Cái này là một #define thôi, không có ý nghĩa gì cả. Nhưng nó sẽ giúp cho mình đảm bảo file grandparent.h không bị include hai lần.

không, ý e là cái e trích thôi a ạ. a đặt câu hỏi đó, mà câu trả lời ko rõ, chưa nói đc nó là gì, chức năng của nó ạ

Nguyễn Minh Dũng viết 18:02 ngày 30/09/2018

Em đọc lại từ đoạn “Cách khác để tránh include nhiều lần”, anh giải thích chức năng của nó từ đoạn đấy.

Sáng Béo viết 18:05 ngày 30/09/2018

Em đọc lại từ đoạn “Cách khác để tránh include nhiều lần”, anh giải thích chức năng của nó từ đoạn đấy.

thế cái GRANDPARENT kia thay bằng tên gì cũng đc ạ?

Nguyễn Minh Dũng viết 18:05 ngày 30/09/2018

Thay bằng gì cũng chạy được. Em thử đi. Nhưng cách tốt nhất vẫn là theo chuẩn trên, tránh nhầm lẫn.

Sáng Béo viết 18:03 ngày 30/09/2018

Thay bằng gì cũng chạy được. Em thử đi. Nhưng cách tốt nhất vẫn là theo chuẩn trên, tránh nhầm lẫn.

e nghĩ thế này đúng ko a:
Nó định nghĩa thêm một cái gì đó (có phải là hằng???) để qua file khác nếu include rồi tức là phía trên đã định nghĩa cái gì đó rồi (hằng???) nên nó sẽ ko định nghĩa lại, cũng như bỏ qua mấy cái trong #ifndef ... #endif luôn.

Nguyễn Minh Dũng viết 18:16 ngày 30/09/2018

Chính xác rồi đấy, nhưng sao lại nhắc tới hằng? Mình chỉ cần hiểu rằng cái này đã định nghĩa, thế nên bỏ qua.

Đừng thêm chữ hằng vào gây sai vấn đề đi.

Sáng Béo viết 18:18 ngày 30/09/2018

vì e thấy chả có gì cả, mỗi cái tên. chắc là nó chỉ định nghĩa cái tên đó thôi a nhỉ.

Nguyễn Minh Dũng viết 18:08 ngày 30/09/2018

Em đã chú ý được tới điểm này là rất tốt. Em nhớ lại định nghĩa của macro. Khi mình define tức là mình thay thế vế trái bằng vế phải trong lệnh define

#define vetrai vephai

Trong trường hợp này vế phải rỗng, vì ta không quan tâm nó là gì cả. Mình chỉ quan tâm là nó đã được define.

Sáng Béo viết 18:04 ngày 30/09/2018

Khi mình define tức là mình thay thế vế trái bằng vế phải trong lệnh define

vâng, cái này đấy ạ.

Trong trường hợp này vế phải rỗng, vì ta không quan tâm nó là gì cả. Mình chỉ quan tâm là nó đã được define.

à, ok ok, e hiểu rồi, thế cái mình define trong này là Mr.Nothing.

Bài liên quan
0