Một số cách sử dụng #pragma
trong C, với các ví dụ?
Một số cách sử dụng #pragma
trong 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
hack
khi 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 #pragma
và 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 once
khô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à #pragma
mộ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_VECTOR
và 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 example
câ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
briefly
là 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-specific
hoặ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 applications
bạ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 exit
và #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 #pragma
kiể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, func1
chạy trước main
và func2
chạ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 func1
và func2
như thế này:
void __attribute__((constructor)) func1();
void __attribute__((destructor)) func2();
Tóm lại, hãy #pragma
yê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:
#pragma
có 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 libportable
thự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.
#pragma
chỉ thị tồn tại trong giai đoạn tiền xử lý. Không giống như#include
và#define
.