فرآیند گردآوری – پیش پردازش – جامعه dev

روند تدوین شامل چهار مرحله کلیدی است ، همانطور که در تصویر زیر نشان داده شده است. در این سری از پست های وبلاگ ، ما هر یک از این مراحل را کشف خواهیم کرد ، مهمترین جنبه ها را برجسته می کنیم و بینش های جالب را در این راه به اشتراک می گذاریم. 😊
پیش پردازش (c/cpp -> .i)
مرحله اول پیش پردازش است. ورودی یک پرونده .c یا .cpp است و خروجی یک پرونده .i است. بیایید به آنچه در این مرحله اتفاق می افتد شیرجه بزنیم.
برای نشان دادن ، ما از مثال زیر استفاده خواهیم کرد:
مثال 1
foo.h
// This is a comment in header file
int foo(void);
دست
#include "foo.h"
// We have a macro
#define SQUARE(x) (x * x)
#define PI 3.14
/* Our main function
* with multi-line comment
*/
int main() {
int result = foo() + SQUARE(3);
float area = PI * 5 * 5;
return result + area;
}
یادداشت: فرآیند تدوین در هر مرحله می تواند متوقف شود. در این حالت ، ما می خواهیم آن را پس از پیش پردازش متوقف کنیم و این کار را انجام دهیم ، ما از آن استفاده می کنیم
-E
پرچم
gcc -E main.c -o main.i
نتیجه:
main.i
# 1 "main.c"
# 1 "" 1
# 1 "" 3
# 418 "" 3
# 1 "" 1
# 1 "" 2
# 1 "main.c" 2
# 1 "./foo.h" 1
int foo(void);
# 2 "main.c" 2
# 11 "main.c"
int main() {
int result = foo() + (3 * 3);
float area = 3.14 * 5 * 5;
return result + area;
}
بیایید نتیجه را رعایت کنیم:
- گنجاندن پرونده هدر – پیش پردازنده جایگزین می شود
#include
بخشنامه هایی با محتوای واقعی پرونده های هدر مشخص شده. - اظهارات کنترل خط (# دستورالعمل)
- نظرات حذف می شوند (تک و چند خط)
- گسترش کلان (#define) – پیش پردازنده ماکروها را با مقادیر تعریف شده خود جایگزین می کند.
-
int result = foo() + SQUARE(3);
->int result = foo() + (3 * 3);
-
float area = PI * 5 * 5;
->float area = 3.14 * 5 * 5;
-
مثال 2
#ifdef DEBUG
#include
#endif
int main() {
#ifdef DEBUG
printf("Debug mode is enabled.\n");
#endif
return 0;
}
- تدوین مشروط (
#ifdef
با#ifndef
با#endif
)
پس از DEBUG
تعریف نشده است ، خروجی پس از پیش پردازش به این شکل است:
...
int main() {
return 0;
}
یک کاربرد شناخته شده از تدوین مشروط است شامل نگهبانانبشر این مثال ساده را در نظر بگیرید:
#include "foo.h"
#include "foo.h"
#include "foo.h"
#include "foo.h"
int main() {
return 0;
}
بدون شامل نگهبانان ، خروجی پس از پیش پردازش ممکن است چیزی شبیه به این باشد:
...
int foo(void);
# 2 "main_multi.c" 2
# 1 "./foo.h" 1
int foo(void);
# 3 "main_multi.c" 2
# 1 "./foo.h" 1
int foo(void);
# 4 "main_multi.c" 2
# 1 "./foo.h" 1
int foo(void);
# 5 "main_multi.c" 2
int main() {
return 0;
}
البته این یک نمونه احمقانه است ، اما در پروژه های بزرگتر ، این مسئله می تواند ناخواسته اتفاق بیفتد. به عنوان مثال:
#include "foo.h"
#include "bar.h"
#include "tar.h"
اگر هر دو bar.h
وت tar.h
همچنین شامل foo.h
، فرآیند کامپایلر foo.h
چندین بار ، که می تواند منجر به خطاهای تعریف مجدد شود.
برای جلوگیری از چندین مورد ، ما استفاده می کنیم شامل نگهبانان مثل این:
#ifndef FOO_H
#define FOO_H
int foo(void);
#endif // FOO_H
مثال 3
#include
#define CONCAT(a, b) a##b
int main() {
int CONCAT(my, Var) = 10; // Expands to int myVar = 10;
printf("File: %s, Line: %d\n", __FILE__, __LINE__);
return 0;
}
نتیجه:
// Ignored the stdio.h
int main() {
int myVar = 10;
printf("File: %s, Line: %d\n", "main.c", 7);
return 0;
}
- چسباندن توکن (##) و stringizing (#)
- از جمله ماکروهای داخلی در مثال ما
__FILE__
وت__LINE__
مرحله بعدی در این روند است تالیفبشر برای پست بعدی با ما همراه باشید!