Một số cách sử dụng #pragmatrong C, với các ví dụ?
Một số cách sử dụng #pragmatrong C, với các ví dụ?
Câu trả lời:
#pragma là dành cho các chỉ thị của trình biên dịch dành riêng cho máy hoặc dành riêng cho hệ điều hành, tức là nó yêu cầu trình biên dịch làm điều gì đó, đặt một số tùy chọn, thực hiện một số hành động, ghi đè một số mặc định, v.v. có thể áp dụng hoặc không áp dụng cho tất cả các máy và hoạt động các hệ thống.
Xem msdn để biết thêm thông tin.
#pragma được sử dụng để làm điều gì đó cụ thể về triển khai trong C, tức là thực dụng cho bối cảnh hiện tại hơn là giáo điều về mặt ý thức hệ.
Cái mà tôi thường xuyên sử dụng là #pragma pack(1) nơi tôi đang cố gắng khai thác thêm không gian bộ nhớ của mình trên các giải pháp nhúng, với các mảng cấu trúc mà nếu không sẽ kết thúc với căn chỉnh 8 byte.
Thật đáng tiếc, chúng tôi chưa có #dogma. Điều đó sẽ rất vui;)
pragma(1)cải thiện tốc độ? Xem stackoverflow.com/questions/3318410/…
Nói chung, tôi sẽ cố gắng tránh sử dụng #pragmas nếu có thể, vì chúng cực kỳ phụ thuộc vào trình biên dịch và không di động. Nếu bạn muốn sử dụng chúng theo kiểu di động, bạn sẽ phải bao quanh mọi pragma bằng một #if/#endif cặp . GCC không khuyến khích việc sử dụng pragmas và thực sự chỉ hỗ trợ một số trong số chúng để tương thích với các trình biên dịch khác; GCC có những cách khác để thực hiện những điều tương tự mà các trình biên dịch khác sử dụng pragmas.
Ví dụ: đây là cách bạn đảm bảo rằng một cấu trúc được đóng gói chặt chẽ (tức là không có phần đệm giữa các thành viên) trong MSVC:
#pragma pack(push, 1)
struct PackedStructure
{
char a;
int b;
short c;
};
#pragma pack(pop)
// sizeof(PackedStructure) == 7
Đây là cách bạn làm điều tương tự trong GCC:
struct PackedStructure __attribute__((__packed__))
{
char a;
int b;
short c;
};
// sizeof(PackedStructure == 7)
Mã GCC dễ di động hơn, vì nếu bạn muốn biên dịch mã đó bằng trình biên dịch không phải GCC, tất cả những gì bạn phải làm là
#define __attribute__(x)
Trong khi nếu bạn muốn chuyển mã MSVC, bạn phải bao quanh mỗi pragma bằng một cặp #if/ #endif. Không đẹp.
struct __attribute__((__packed__)) PackedStructure
hackkhi nó gặp một pragma nó không nhận ra, vì nó sử dụng để làm một lần khi một thời gian rất, rất lâu rồi - xem #pragmavà GCC , vv)
Đặt #pragma onceở đầu tệp tiêu đề của bạn sẽ đảm bảo rằng nó chỉ được đưa vào một lần. Lưu ý rằng đó #pragma oncekhông phải là tiêu chuẩn C99, nhưng được hỗ trợ bởi hầu hết các trình biên dịch hiện đại.
Một thay thế là sử dụng bao gồm bảo vệ (ví dụ #ifndef MY_FILE #define MY_FILE ... #endif /* MY_FILE */)
những gì tôi cảm thấy là #pragmamột chỉ thị trong đó nếu bạn muốn mã ở vị trí cụ thể. hãy nói tình huống mà bạn muốn bộ đếm chương trình đọc từ địa chỉ cụ thể nơi ISR được ghi thì bạn có thể chỉ định ISR tại vị trí đó bằng cách sử dụng #pragma vector=ADC12_VECTORvà làm theo tên rotines ngắt và mô tả của nó
Lời khuyên tốt nhất của tôi là hãy xem tài liệu của trình biên dịch của bạn, vì pragmas theo định nghĩa dành riêng cho việc triển khai. Ví dụ, trong các dự án nhúng, tôi đã sử dụng chúng để định vị mã và dữ liệu trong các phần khác nhau hoặc khai báo trình xử lý ngắt. I E:
#pragma code BANK1
#pragma data BANK2
#pragma INT3 TimerHandler
Tất cả các câu trả lời ở trên giải thích tốt cho #pragma nhưng tôi muốn thêm một ví dụ nhỏ
Tôi chỉ muốn giải thích một simple OpenMP examplecâu chứng minh một số cách sử dụng #pragmađể thực hiện công việc của nó
OpenMp
brieflylà một triển khai cho lập trình song song bộ nhớ chia sẻ đa nền tảng (sau đó chúng ta có thể nói làmachine-specifichoặcoperating-system-specific)
hãy đi đến ví dụ
#include <stdio.h>
#include <omp.h>// compile with: /openmp
int main() {
#pragma omp parallel num_threads(4)
{
int i = omp_get_thread_num();
printf_s("Hello from thread %d\n", i);
}
}
đầu ra là
Hello from thread 0
Hello from thread 1
Hello from thread 2
Hello from thread 3
Note that the order of output can vary on different machines.
bây giờ hãy để tôi nói cho bạn biết những gì #pragmađã làm ...
nó yêu cầu hệ điều hành chạy một số khối mã trên 4 luồng
đây chỉ là một trong số many many applicationsbạn có thể làm với một chút#pragma
xin lỗi vì mẫu bên ngoài OpenMP
Đây là chỉ thị tiền xử lý có thể được sử dụng để bật hoặc tắt một số tính năng nhất định.
Nó có hai loại #pragma startup, #pragma exitvà #pragma warn.
#pragma startup cho phép chúng tôi chỉ định các chức năng được gọi khi khởi động chương trình.
#pragma exit cho phép chúng tôi chỉ định các hàm được gọi khi thoát chương trình.
#pragma warn cho máy tính biết để ngăn chặn bất kỳ cảnh báo nào hay không.
Nhiều #pragmakiểu khác có thể được sử dụng để điều khiển trình biên dịch.
#pragma startup là một chỉ thị được sử dụng để gọi một hàm trước hàm chính và để gọi một hàm khác sau hàm chính, ví dụ:
#pragma startup func1
#pragma exit func2
Ở đây, func1chạy trước mainvà func2chạy sau.
LƯU Ý: Mã này chỉ hoạt động trong trình biên dịch Turbo-C. Để đạt được chức năng này trong GCC, bạn có thể khai báo func1và func2như thế này:
void __attribute__((constructor)) func1();
void __attribute__((destructor)) func2();
Tóm lại, hãy #pragmayêu cầu trình biên dịch thực hiện các công việc. Dưới đây là một số cách tôi sử dụng:
#pragmacó thể được sử dụng để bỏ qua các cảnh báo của trình biên dịch. Ví dụ: để khiến GCC im lặng về các khai báo hàm ngầm, bạn có thể viết:
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
Một phiên bản cũ của libportablethực hiện điều này portably .
#pragma once, khi được viết ở đầu tệp tiêu đề, sẽ khiến tệp tiêu đề đó được đưa vào một lần. libportable kiểm tra hỗ trợ pragma một lần.
#pragmachỉ thị tồn tại trong giai đoạn tiền xử lý. Không giống như#includevà#define.