恨铁不成钢什么意思| hp代表什么意思| 股票roe是什么意思| 孕早期适合吃什么食物| 10月7号是什么星座| 口腔医学技术可以考什么证| 怀二胎初期有什么症状| 一什么月光| 投递是什么意思| 乳酸杆菌是什么| 挫伤用什么药| 小孩长得慢是什么原因| 什么是无期徒刑| 巴子是什么意思| joseph是什么意思| 胰腺在人体什么位置| 寒天是什么| 1221是什么星座| 乌鸡蛋什么颜色| 脾胃挂什么科| 女生适合养什么狗| 产褥热是什么病| 孕妇胆固醇高对胎儿有什么影响| 子宫内膜增厚吃什么药| 左眼屈光不正是什么意思| dunk是什么意思| 喵星人是什么意思| 光动能手表是什么意思| 番石榴什么时候成熟| 巴西龟吃什么食物| 低血压吃什么药效果好| 老打喷嚏是什么原因| 边界清是什么意思| 刚愎自用是什么意思| 支气管炎吃什么消炎药| 拿什么证明分居两年| 拿的起放的下是什么意思| 道德什么意思| 高潮是什么| 韧带拉伤吃什么药| 什么人不适合吃榴莲| 什么是变异性哮喘| 繁花似锦是什么意思| 口淡无味是什么原因| phicomm是什么牌子| 摩羯座什么性格| 什么态度| 什么无云| 常喝蜂蜜水有什么好处和坏处| 母亲节送给妈妈什么礼物| 颈椎头晕吃点什么药| autumn什么意思| 鱼泡是鱼的什么器官| 手串断了寓意什么| 冠状沟有白色分泌物是什么原因| 气管炎吃什么好| 减肥晚上适合吃什么水果| 庆大霉素治疗鱼什么病| 手指头麻是什么原因引起的| 抗核抗体阴性说明什么| 磁共振检查什么| 心脏缺血吃什么补得快| 心率过缓有什么危害| 血压为什么高| 凤是什么意思| homie什么意思| 执勤是什么意思| 牙齿突然酸痛什么原因| 吃什么hcg翻倍快| 卫衣是什么| 9.27日是什么星座| 例假推迟是什么原因| 妊娠阴性是什么意思| 思觉失调是什么意思| 孤帆远影碧空尽的尽是什么意思| 尘肺病吃什么能排出尘| 什么食物蛋白质含量最高| 风尘是什么意思| 吃什么长卵泡| 安全期是指什么时间| 蕴字五行属什么| 舌苔厚是什么原因引起的| hp是什么牌子的电脑| 左眼跳代表什么| 支原体弱阳性是什么意思| 下午2点半是什么时辰| 什么动物是爸爸生的| 阴囊湿疹长什么样图片| 白羊女和什么星座最配| ct和b超有什么区别| 阴囊潮湿瘙痒用什么药| 轻轻地什么| af是什么| 抗链球菌溶血素o偏高是什么原因| 重磅是什么意思| 口干舌燥吃什么中成药| 眉梢有痣代表什么| 云南的特产是什么| 仔仔是什么意思| hg是什么元素| 经常晕倒是什么原因引起的| 输卵管堵塞有什么症状| 梦见挖坟墓预示什么| 什么是电信诈骗| 卫生湿巾是干什么用的| 芝麻分是什么意思| 酸化是什么意思| ahc是韩国什么档次| 感知力是什么意思| 金牛座和什么星座最不配| 玄关挂什么装饰画好| pumpkin是什么意思| 抽搐吃什么药| 霸天虎和威震天是什么关系| 三星是什么军衔| 叶酸不能和什么一起吃| 绿豆和什么相克中毒| 血肿是什么意思| 梦见自己把蛇打死了是什么意思| 自相矛盾的道理是什么| 有什么书| 心脏缺血吃什么药最好| 早上四点是什么时辰| 女人梦见桃子预示什么| 脚浮肿吃什么药| 什么是真心| 颈椎病吃什么药最好效果| pppd是什么意思| txt什么意思| 舌苔厚腻吃什么药| 什么万| 什么是tct检查| 成都人民公园有什么好玩的| 嘴唇颜色深是什么原因| yaoi是什么| 五海瘿瘤丸主要治什么病| 脑出血有什么后遗症| 癫是什么意思| 什么都值得买| 车加失读什么| 女人梦到被蛇咬是什么意思| 三焦指的是什么器官| 土黄色裤子配什么颜色上衣| 鼻塞黄鼻涕吃什么药| 血症是什么病| 年轻人白头发是什么原因引起的| 拔罐拔出水泡是什么原因| 女人性冷淡用什么药| 犹太人为什么那么聪明| 姓许的女孩取什么名字好听| 柠檬酸钠是什么| 横空出世什么意思| 夏天能种什么菜| 于谦为什么加入国民党| 尿蛋白高是什么意思| 外强中干什么意思| 什么是哺乳动物| 尿ph值高是什么意思| 手指长痣代表什么| 甜虾是什么虾| 肾炎可以吃什么水果| 糖尿病有什么症状| her2是什么意思| 容颜是什么意思| 乐趣是什么意思| 153是什么意思| 情节是什么| 金丝玉是什么玉| 老板娘是什么意思| 乾卦代表什么| 灼热感是什么样的感觉| 嘴下面起痘是什么原因| 李开复是什么人| 6s管理内容是什么| 不为良相便为良医是什么意思| 喝温开水有什么好处| 思源名字的寓意是什么| 小便发黄是什么原因| 肝内钙化灶什么意思| 阴唇痒是什么原因| 梦见大鲤鱼是什么征兆| 蝉什么时候叫| 家里养什么花最好| 1919年发生了什么| 什么样的小河| 田螺不能和什么一起吃| 身上起火疖子什么原因| 碳十四检测是查什么的| 白色五行属什么| 米粉是用什么做出来的| 高烧用什么方法降温最快| 怀孕第一个月吃什么对胎儿好| 九宫八卦是什么意思| 2016年属什么生肖| 吃什么水果对皮肤好又美白| 犯困是什么原因| 二月一号是什么星座| 得了艾滋病会有什么症状| 100年前是什么朝代| 烧心吃什么药| 纯洁是什么意思| 标题是什么意思| 姨妈的老公叫什么| 塑料属于什么垃圾| 总流口水是什么原因| 四次元是什么意思| 反犬旁和什么有关| 送男性朋友什么礼物合适| 绿豆汤什么颜色| hpv16阳性有什么症状| 党内警告处分有什么影响| 鸭子吃什么食物| 嘴唇发紫发黑是什么原因| 喉咙痛喝什么饮料| 人参是什么参| 白芍有什么功效和作用| 难能可贵是什么意思| 咳嗽有血是什么原因| 殉葬是什么意思| 肺上有结节是什么病| 吃什么对脑血管好| honor是什么牌子| 眼睛有眼屎是什么原因引起的| 什么原因得湿疹| 尿素低是什么原因| 肚子上面是什么部位| 女人肝火旺吃什么好| 胎记看什么科| 金黄色葡萄球菌是什么菌| 狗女配什么属相最好| 依赖一个人是什么意思| 炮烙之刑是什么意思| 长寿花用什么肥料最好| 2022什么年| 性生活过多有什么危害| 陌上人如玉是什么意思| 皮重是什么意思| 十三香是什么| 鼻子两侧毛孔粗大是什么原因造成的| 角质层是什么| 检出限是什么意思| 上焦不通吃什么中成药| 猫咪有泪痕是什么原因| 经常头痛是什么原因| 紫外线过敏是什么症状| 割包皮去医院挂什么科| tea是什么意思| 回门是什么意思| 怀孕什么时候吃鹅蛋最好| 什么时候浇花最好| 在什么情况下需要做肠镜| 公鸡为什么打鸣| 季夏是什么意思| 阳虚有什么症状和表现| 反文旁和什么有关| 生活因什么而精彩| 普工是什么| 刮宫是什么| 四大美女指什么生肖| 出现血精吃什么药| 溃烂用什么药治愈最快| Cr是什么意思医学| 什么菜好消化| 蓝色配什么颜色最好看| 百度Jump to content

琼岛本周前中期气温下降 将现短时强降水等天气

From Wikipedia, the free encyclopedia
(Redirected from Stringizing)
百度 ”3月5日,(内蒙古)自治区党委常委、(包头)市委书记张院忠在市委办公厅《关于2017年人民网网民留言办理工作情况的报告》上作出批示,对此项工作予以充分肯定。

The C preprocessor (CPP) is a text file processor that is used with C, C++ and other programming tools. The preprocessor provides for file inclusion (often header files), macro expansion, conditional compilation, and line control. Although named in association with C and used with C, the preprocessor capabilities are not inherently tied to the C language. It can and is used to process other kinds of files.[1]

C, C++, and Objective-C compilers provide a preprocessor capability, as it is required by the definition of each language. Some compilers provide extensions and deviations from the target language standard. Some provide options to control standards compliance. For instance, the GNU C preprocessor can be made more standards compliant by supplying certain command-line flags.[2]

The C# programming language also allows for directives, even though they cannot be used for creating macros, and is generally more intended for features such as conditional compilation.[3] C# seldom requires the use of the directives, for example code inclusion does not require a preprocessor at all (as C# relies on a package/namespace system like Java, no code needs to be "included").

The Haskell programming language also allows the usage of the C preprocessor, which is invoked by writing {-# LANGUAGE CPP #-} at the top of the file. The accepted preprocessor directives align with those in standard C/C++.

Features of the preprocessor are encoded in source code as directives that start with #.

Although C++ source files are often named with a .cpp extension, that is an abbreviation for "C plus plus"; not C preprocessor.

Preprocessor directives

[edit]

The following languages have the following accepted directives.

C/C++

[edit]

The following tokens are recognised by the preprocessor in the context of preprocessor directives.

  • #if
  • #elif
  • #else
  • #endif
  • #ifdef
  • #ifndef
  • #elifdef
  • #elifndef
  • #define
  • #undef
  • #include
  • #embed
  • #line
  • #error
  • #warning
  • #pragma
  • defined (follows a conditional directive; not actually a directive, but rather an operator)
  • __has_include (operator)
  • __has_cpp_attribute (operator, C++ only)
  • __has_c_attribute (operator, C only)
  • __has_embed (operator)

Until C++26, the C++ keywords import, export, and module were partially handled by the preprocessor as well.

Haskell also accepts C preprocessor directives.

C#

[edit]

Although C# does not have a separate preprocessor, these directives are processed as if there were one.

  • #nullable
  • #if
  • #elif
  • #else
  • #endif
  • #define
  • #undef
  • #region
  • #endregion
  • #error
  • #warning
  • #line
  • #pragma

C# does not use a preprocessor to handle these directives, and thus they are not handled or removed by a preprocessor, but rather directly read by the C# compiler as a feature of the language.

Objective-C

[edit]

The following tokens are recognised by the preprocessor in the context of preprocessor directives.

  • #if
  • #elif
  • #else
  • #endif
  • #ifdef
  • #ifndef
  • #define
  • #undef
  • #include
  • #import
  • #error
  • #pragma
  • defined

History

[edit]

The preprocessor was introduced to C around 1973 at the urging of Alan Snyder and also in recognition of the usefulness of the file inclusion mechanisms available in BCPL and PL/I. The first version offered file inclusion via #include and parameterless string replacement macros via #define. It was extended shortly after, firstly by Mike Lesk and then by John Reiser, to add arguments to macros and to support conditional compilation.[4]

The C preprocessor was part of a long macro-language tradition at Bell Labs, which was started by Douglas Eastwood and Douglas McIlroy in 1959.[5]

Phases

[edit]

Preprocessing is defined by the first four (of eight) phases of translation specified in the C Standard.

  1. Trigraph replacement: The preprocessor replaces trigraph sequences with the characters they represent. This phase was removed in C23 following the steps of C++17.
  2. Line splicing: Physical source lines that are continued with escaped newline sequences are spliced to form logical lines.
  3. Tokenization: The preprocessor breaks the result into preprocessing tokens and whitespace. It replaces comments with whitespace.
  4. Macro expansion and directive handling: Preprocessing directive lines, including file inclusion and conditional compilation, are executed. The preprocessor simultaneously expands macros and, since the 1999 version of the C standard, handles _Pragma operators.

Features

[edit]

File inclusion

[edit]

There are two directives in the C preprocessor for including contents of files:

  • #include, used for directly including the contents of a file in-place (typically containing code of some kind)
  • #embed, used for directly including or embedding the contents of a binary resource in-place

Code inclusion

[edit]

To include the content of one file into another, the preprocessor replaces a line that starts with #include with the content of the file specified after the directive. The inclusion may be logical in the sense that the resulting content may not be stored on disk and certainly is not overwritten to the source file. The file being included need not contain any sort of code, as this directive will copy the contents of whatever file is included in-place, but the most typical use of #include is to include a header file (or in some rarer cases, a source file).

In the following example code, the preprocessor replaces the line #include <stdio.h> with the content of the standard library header file named 'stdio.h' in which the function printf() and other symbols are declared.

#include <stdio.h>

int main(void) {
    printf("Hello, World!\n");
    return 0;
}

In this case, the file name is enclosed in angle brackets to denote that it is a system file. For a file in the codebase being built, double-quotes are used instead. The preprocessor may use a different search algorithm to find the file based on this distinction.

For C, a header file is usually named with a .h extension. In C++, the convention for file extension varies with common extensions .h and .hpp. But the preprocessor includes a file regardless of the extension. In fact, sometimes code includes .c or .cpp files.

To prevent including the same file multiple times which often leads to a compiler error, a header file typically contains an #include guard or if supported by the preprocessor #pragma once to prevent multiple inclusion.

Binary resource inclusion

[edit]

C23 and C++26 introduce the #embed directive for binary resource inclusion which allows including the content of a binary file into a source even though it's not valid C code.[6][7] This allows binary resources (like images) to be included into a program without requiring processing by external tools like xxd -i and without the use of string literals which have a length limit on MSVC. Similarly to xxd -i the directive is replaced by a comma separated list of integers corresponding to the data of the specified resource. More precisely, if an array of type unsigned char is initialized using an #embed directive, the result is the same as-if the resource was written to the array using fread (unless a parameter changes the embed element width to something other than CHAR_BIT). Apart from the convenience, #embed is also easier for compilers to handle, since they are allowed to skip expanding the directive to its full form due to the as-if rule.

The file to embed is specified the same as for #include – either with brackets or double quotes. The directive also allows certain parameters to be passed to it to customize its behavior. The C standard defines some parameters and implementations may define additional. The limit parameter is used to limit the width of the included data. It is mostly intended to be used with "infinite" files like urandom. The prefix and suffix parameters allow for specifying a prefix and suffix to the embedded data. Finally, the if_empty parameter replaces the entire directive if the resource is empty. All standard parameters can be surrounded by double underscores, just like standard attributes on C23, for example __prefix__ is interchangeable with prefix . Implementation-defined parameters use a form similar to attribute syntax (e.g., vendor::attr) but without the square brackets. While all standard parameters require an argument to be passed to them (e.g., limit requires a width), this is generally optional and even the set of parentheses can be omitted if an argument is not required, which might be the case for some implementation-defined parameters.

const unsigned char icon_display_data[] = {
    #embed "art.png"
};

/* specify any type which can be initialized form integer constant expressions will do */
const char reset_blob[] = {
    #embed "data.bin"
};

/* attributes work just as well */
const signed char aligned_data_str[] __attribute__ ((aligned (8))) = {
    #embed "attributes.xml"
};

int main() {
    return
#embed </dev/urandom> limit(1)
    ;
}

Conditional compilation

[edit]

Conditional compilation is supported via the if-else core directives #if, #else, #elif, and #endif and with contraction directives #ifdef and #ifndef which stand for #if defined(...) and #if !defined(...), respectively. In the following example code, the printf() call is only included for compilation if VERBOSE is defined.

#ifdef VERBOSE
  printf("trace message");
#endif

The following demonstrates more complex logic:

#if !(defined __LP64__ || defined __LLP64__) || defined _WIN32 && !defined _WIN64
	// code for a 32-bit system
#else
	// code for a 64-bit system
#endif

Macro string replacement

[edit]
Object-like

A macro specifies how to replace text in the source code with other text. An object-like macro defines a token that the preprocessor replaces with other text. It does not include parameter syntax and therefore cannot support parameterization. The following macro definition associates the text "1 / 12" with the token "VALUE":

#define VALUE 1 / 12
Function-like

A function-like macro supports parameters; although the parameter list can be empty. The following macro definition associates the expression "(A + B)" with the token "ADD" that has parameters "A" and "B".

#define ADD(A, B) (A + B)

A function-like macro declaration cannot have whitespace between the token and the first, opening parenthesis. If whitespace is present, the macro is interpreted as object-like with everything starting at the first parenthesis included in the replacement text.

Expansion

The preprocessor replaces each token of the code that matches a macro token with the associated replacement text in what is known as macro expansion. Note that text of string literals and comments is not parsed as tokens and is therefore ignored for macro expansion. For a function-like macro, the macro parameters are also replaced with the values specified in the macro reference. For example, ADD(VALUE, 2) expands to 1 / 12 + 2.

Variadic

A variadic macro (introduced with C99) accepts a varying number of arguments which is particularly useful when wrapping functions that accept a variable number of parameters, such as printf.

Order of expansion

Function-like macro expansion occurs in the following stages:

  1. Stringification operations are replaced with the textual representation of their argument's replacement list (without performing expansion).
  2. Parameters are replaced with their replacement list (without performing expansion).
  3. Concatenation operations are replaced with the concatenated result of the two operands (without expanding the resulting token).
  4. Tokens originating from parameters are expanded.
  5. The resulting tokens are expanded as normal.

This may produce surprising results:

#define HE HI
#define LLO _THERE
#define HELLO "HI THERE"
#define CAT(a,b) a##b
#define XCAT(a,b) CAT(a,b)
#define CALL(fn) fn(HE,LLO)
CAT(HE, LLO) // "HI THERE", because concatenation occurs before normal expansion
XCAT(HE, LLO) // HI_THERE, because the tokens originating from parameters ("HE" and "LLO") are expanded first
CALL(CAT) // "HI THERE", because this evaluates to CAT(a,b)

Undefine macro

[edit]

A macro definition can be removed from the preprocessor context via #undef such that subsequent reference to the macro token will not expand. For example:

#undef VALUE

Predefined macros

[edit]

The preprocessor provides some macro definitions automatically. The C standard specifies that __FILE__ expands to the name of the file being processed and __LINE__ expands to the number of the line that contains the directive. The following macro, DEBUGPRINT, formats and prints a message with the file name and line number.

#define DEBUGPRINT(_fmt, ...) printf("[%s:%d]: " _fmt, __FILE__, __LINE__, __VA_ARGS__)

For the example code below that is on line 30 of file util.c and for count 123, the output is: [util.c:30]: count=123.

DEBUGPRINT("count=%d\n", count);

The first C Standard specified that __STDC__ expand to "1" if the implementation conforms to the ISO standard and "0" otherwise and that __STDC_VERSION__ expand to a numeric literal specifying the version of the standard supported by the implementation. Standard C++ compilers support the __cplusplus macro. Compilers running in non-standard mode must not set these macros or must define others to signal the differences.

Other standard macros include __DATE__, the current date, and __TIME__, the current time.

The second edition of the C Standard, C99, added support for __func__, which contains the name of the function definition within which it is contained, but because the preprocessor is agnostic to the grammar of C, this must be done in the compiler itself using a variable local to the function.

One little-known usage pattern of the C preprocessor is known as X-Macros.[8][9][10] An X-Macro is a header file. Commonly, these use the extension .def instead of the traditional .h . This file contains a list of similar macro calls, which can be referred to as "component macros." The include file is then referenced repeatedly.

Many compilers define additional, non-standard macros. A common reference for these macros is the Pre-defined C/C++ Compiler Macros project, which lists "various pre-defined compiler macros that can be used to identify standards, compilers, operating systems, hardware architectures, and even basic run-time libraries at compile-time."

Most compilers targeting Microsoft Windows implicitly define _WIN32.[11] This allows code, including preprocessor commands, to compile only when targeting Windows systems. A few compilers define WIN32 instead. For such compilers that do not implicitly define the _WIN32 macro, it can be specified on the compiler's command line, using -D_WIN32.

#ifdef __unix__ /* __unix__ is usually defined by compilers targeting Unix systems */
# include <unistd.h>
#elif defined _WIN32 /* _WIN32 is usually defined by compilers targeting 32 or 64 bit Windows systems */
# include <windows.h>
#endif

The example code tests if a macro __unix__ is defined. If it is, the file <unistd.h> is then included. Otherwise, it tests if a macro _WIN32 is defined instead. If it is, the file <windows.h> is then included.

Line control

[edit]

The values of the predefined macros __FILE__ and __LINE__ can be set for a subsequent line via the #line directive. In the code below, __LINE__ expands to 314 and __FILE__ to "pi.c".

#line 314 "pi.c"
printf("line=%d file=%s\n", __LINE__, __FILE__);

Operators

[edit]

The preprocessor is capable of interpreting operators and evaluating very basic expressions, such as integer constants, arithmetic operators, comparison operators, logical operators, bitwise operations, the defined operator, and the # stringificafion operator. This allows the preprocessor to make evaluations such as:

#if X == 10 // if X equals 10, the preprocessor sees #if 10 == 10

Defined operator

[edit]

While the defined operator, denoted by defined is not a directive in its own right, if it is read within a directive, it is interpreted by the preprocessor and determines whether a macro has been defined.

The following are both accepted ways of invoking the defined operator.

#if defined(MY_MACRO)
#if defined MY_MACRO

Token stringification operator

[edit]

The stringification operator (a.k.a. stringizing operator), denoted by # converts a token into a string literal, escaping any quotes or backslashes as needed. For definition:

#define str(s) #s

str(\n) expands to "\n" and str(p = "foo\n";) expands to "p = \"foo\\n\";".

If stringification of the expansion of a macro argument is desired, two levels of macros must be used. For definition:

#define xstr(s) str(s)
#define str(s) #s
#define foo 4

str(foo) expands to "foo" and xstr(foo) expands to "4".

A macro argument cannot be combined with additional text and then stringified. However, a series of adjacent string literals and stringified arguments, also string literals, are concatenated by the C compiler.

Token concatenation

[edit]

The token pasting operator, denoted by ##, concatenates two tokens into one. For definition:

#define DECLARE_STRUCT_TYPE(name) typedef struct name##_s name##_t

DECLARE_STRUCT_TYPE(g_object) expands to typedef struct g_object_s g_object_t.

Abort

[edit]

Processing can be aborted via the #error directive. For example:

#if RUBY_VERSION == 190
#error Ruby version 1.9.0 is not supported
#endif

Warning

[edit]

As of C23[12] and C++23,[13] a warning directive, #warning, to print a message without aborting is provided. Some typical uses are to warn about the use of deprecated functionality. For example:

Prior to C23 and C++23, this directive existed in many compilers as a non-standard feature, such as the C compilers by GNU, Intel, Microsoft and IBM. Because it was non-standard, the warning macro had varying forms:

// GNU, Intel and IBM
#warning "Do not use ABC, which is deprecated. Use XYZ instead."

// Microsoft
#pragma message("Do not use ABC, which is deprecated. Use XYZ instead.")

Non-standard features

[edit]

Pragma

[edit]

The #pragma directive is defined by standard languages, but with little or no requirements for syntax after its name so that compilers are free to define subsequent syntax and associated behavior. For instance, a pragma is often used to allow suppression of error messages, manage heap and stack debugging and so on.

C99 introduced a few standard pragmas, taking the form #pragma STDC ..., which are used to control the floating-point implementation. The alternative, macro-like form _Pragma(...) was also added.

One of the most popular uses of the #pragma directive is #pragma once, which behaves the same way an #include guard would, condensed into a single directive placed at the top of the file. Despite being non-standard, it is supported by most compilers.

Trigraphs

[edit]

Many implementations do not support trigraphs or do not replace them by default.

Assertion

[edit]

Some Unix preprocessors provided an assertion feature – which has little similarity to standard library assertions.[14]

Include next

[edit]

GCC provides #include_next for chaining headers of the same name.[15]

Import

[edit]

Unlike C and C++, Objective-C includes an #import directive that is like #include but results in a file being included only once – eliminating the need for include guards and #pragma once.

#import <Foundation/Foundation.h>
#import "MyClass.h"

In Microsoft Visual C++ (MSVC), there also exists an #import preprocessor directive, used to import type libraries.[16] It is a nonstandard directive.

#import "C:\\Program Files\\Common Files\\System\\ado\\msado15.dll" no_namespace rename("EOF", "ADOEOF")

The Objective-C directive should not be confused with the C++ keyword import, which is used to import C++ modules (since C++20), and is not a preprocessor directive.

Nullable

[edit]

The #nullable directive in C# is used to enable and disable nullable reference types. To enable them, use #nullable enable, and #nullable disable to disable them.

#nullable enable

string? name = null; // OK
string fullName = null; // Warning: possible null assignment

#nullable disable

string test = null; // No warning

This directive does not exist in C/C++.

Region

[edit]

The #region and #endregion directives in C# are used to expand/collapse sections of code in IDEs, and has no effect on actual compilation of the program. It is primarily used for code organisation and readability.

#region Helper methods

void Log(string message)
{
    Console.WriteLine(message);
}

#endregion

While this directive does not exist in C/C++, MSVC and Visual Studio instead have #pragma region and #pragma endregion.[17] Thus the equivalent C++ code would be:

#pragma region Helper methods

void log(std::string_view message) {
    std::println(message);
}

#pragma endregion

Other uses

[edit]

Traditionally, the C preprocessor was a separate development tool from the compiler with which it is usually used. In that case, it can be used separately from the compiler. Notable examples include use with the (deprecated) imake system and for preprocessing Fortran. However, use as a general purpose preprocessor is limited since the source code language must be relatively C-like for the preprocessor to parse it.[2]

The GNU Fortran compiler runs "traditional mode" CPP before compiling Fortran code if certain file extensions are used.[18] Intel offers a Fortran preprocessor, fpp, for use with the ifort compiler, which has similar capabilities.[19]

CPP also works acceptably with most assembly languages and Algol-like languages. This requires that the language syntax not conflict with CPP syntax, which means no lines starting with # and that double quotes, which CPP interprets as string literals and thus ignores, don't have syntactical meaning other than that. The "traditional mode" (acting like a pre-ISO C preprocessor) is generally more permissive and better suited for such use.[20]

Some modern compilers such as the GNU C Compiler provide preprocessing as a feature of the compiler; not as a separate tool.

Limitations

[edit]

Text substitution limitations

[edit]

Text substitution has a relatively high risk of causing a software bug as compared to other programming constructs.[21][22]

Hidden multiple evaluation

Consider the common definition of a max macro:

#define max(a,b) (((a) > (b)) ? (a) : (b))

The expressions represented by a and b are both evaluated two times due to macro expansion, but this aspect is not obvious in the code where the macro is referenced. If the actual expressions have constant value, then multiple evaluation is not problematic from a logic standpoint even though it can affect runtime performance. But if an expression evaluates to a different value on subsequent evaluation, then the result may be unexpected. For example, given int i = 1; j = 2;, the result of max(i,j) is 2. If a and b were only evaluated once, the result of max(i++,j++) would be the same, but with double evaluation the result is 3.

Hidden order of operation

Failure to bracket arguments can lead to unexpected results. For example, a macro to double a value might be written as:

#define double(x) 2 * x

But double(1 + 2) expands to 2 * 1 + 2 which due to order of operations, evaluates to 4 when the expected is 6. To mitigate this problem, a macro should bracket all expressions and substitution variables:

#define double(x) (2 * (x))

Not general purpose

[edit]

The C preprocessor is not Turing-complete, but comes close. Recursive computations can be specified, but with a fixed upper bound on the amount of recursion performed.[23] However, the C preprocessor is not designed to be, nor does it perform well as, a general-purpose programming language. As the C preprocessor does not have features of some other preprocessors, such as recursive macros, selective expansion according to quoting, and string evaluation in conditionals, it is very limited in comparison to a more general macro processor such as m4.

Phase out

[edit]

Due to its limitations and lack of type safety (as the preprocessor is completely oblivious to C/C++ grammar, performing only text substitutions), C and C++ language features have been added over the years to minimize the value and need for the preprocessor.

Constant

For a long time, a preprocessor macro provided the preferred way to define a constant value. An alternative has always been to define a const variable, but that results in consuming runtime memory. A newer language construct (since C++11 and C23), constexpr allows for declaring a compile-time constant value that need not consume runtime memory.[24]

Inline function

For a long time, a function-like macro was the only way to define function-like behavior that did not incur runtime function call overhead. Via the inline keyword and optimizing compilers that inline automatically, some functions can be invoked without call overhead.

Import

The include directive limits code structure since it only allows including the content of one file into another. More modern languages support a module concept that has public symbols that other modules import – instead of including file content. Many contend that resulting code has reduced boilerplate and is easier to maintain since there is only one file for a module; not both a header and a body. C++20 adds modules, and an import statement that is not handled via preprocessing.[25][26] Modules in C++ compile faster and link faster than traditional headers,[27] and eliminate the necessity of #include guards or #pragma once. Until C++26, import, export, and module keywords were partially handled by the preprocessor.

For code bases that cannot migrate to modules immediately, C++ also offers "header units" as a feature, which allows header files to be imported in the same way a module would. Unlike modules, header units may emit macros, offering minimal breakage between migration. Header units are designed to be a transitional solution before totally migrating to modules.[28] For instance, one may write import <string>; instead of #include <string>, or import "MyHeader.hpp"; instead of #include "MyHeader.hpp". Paradoxically, most build systems, such as CMake, do not currently support this feature.

See also

[edit]

References

[edit]
  1. ^ General-purpose text preprocessing with the C preprocessor. Featuring JavaScript
  2. ^ a b "The C Preprocessor: Overview". Retrieved 17 July 2016.
  3. ^ "C# preprocessor directives". Microsoft. 14 January 2022.
  4. ^ Ritchie (1993)
  5. ^ "Bell SAP – SAP with conditional and recursive macros". HOPL: Online Historical Encyclopaedia of Programming Languages. Archived from the original on 14 October 2023. Retrieved 4 October 2020.
  6. ^ "WG14-N3017 : #embed – a scannable, tooling-friendly binary resource inclusion mechanism". open-std.org. 27 June 2022. Archived from the original on 24 December 2022.
  7. ^ "#embed - a scannable, tooling-friendly binary resource inclusion mechanism". open-std.org.
  8. ^ Wirzenius, Lars. C "Preprocessor Trick For Implementing Similar Data Types". Retrieved January 9, 2011
  9. ^ Meyers, Randy (May 2001). "The New C: X Macros". Dr. Dobb's Journal. Retrieved 1 May 2008.
  10. ^ Beal, Stephan (August 2004). "Supermacros". Retrieved 27 October 2008. {{cite journal}}: Cite journal requires |journal= (help)
  11. ^ List of predefined ANSI C and Microsoft C++ implementation macros.
  12. ^ "WG14-N3096 : Draft for ISO/IEC 9899:2023" (PDF). open-std.org. 1 April 2023. Archived (PDF) from the original on 2 April 2023.
  13. ^ "Working Draft, Standard for Programming Language C++" (PDF). 22 March 2023.
  14. ^ GCC Obsolete features
  15. ^ "Wrapper Headers (The C Preprocessor)".
  16. ^ "#import directive (C++)".
  17. ^ "region and endregion pragma".
  18. ^ "1.3 Preprocessing and conditional compilation". GNU Project.
  19. ^ "Using the fpp Preprocessor". Intel. Retrieved 14 October 2015.
  20. ^ "Overview (The C Preprocessor)". gcc.gnu.org. Having said that, you can often get away with using cpp on things which are not C. Other Algol-ish programming languages are often safe (Ada, etc.) So is assembly, with caution. -traditional-cpp mode preserves more white space, and is otherwise more permissive. Many of the problems can be avoided by writing C or C++ style comments instead of native language comments, and keeping macros simple.
  21. ^ Gerard J. Holzmann. "The power of ten - Rules for developing safety critical code" (PDF). safety of macros. p. 4.
  22. ^ Michael D. Ernst; Greg J. Badros; David Notkin (December 2002). "An empirical analysis of c preprocessor use". IEEE Transactions on Software Engineering. 28 (12): 1146–1170. doi:10.1109/TSE.2002.1158288.
  23. ^ "Is the C99 preprocessor Turing complete?". Archived from the original on 24 April 2016.
  24. ^ Gabriel Dos Reis; Bjarne Stroustrup (22 March 2010). "General Constant Expressions for System Programming Languages, Proceedings SAC '10" (PDF). Archived (PDF) from the original on 13 June 2018. Retrieved 8 July 2024.
  25. ^ "N4720: Working Draft, Extensions to C++ for Modules" (PDF). Archived (PDF) from the original on 30 April 2019.
  26. ^ "P1857R1 – Modules Dependency Discovery".
  27. ^ "Overview of modules in C++". Microsoft. 12 February 2022.
  28. ^ "Walkthrough: Build and import header units in Microsoft Visual C++". Microsoft. 12 April 2022.

Sources

[edit]
[edit]
梅菜在北方叫什么菜 ysl是什么牌子 肠易激综合征是什么原因造成的 什么牌子的蜂胶最好 西瓜和什么食物相克
兰花的花语是什么 咳白痰吃什么药效果好 依云矿泉水为什么贵 宝宝低烧吃什么药 比特币是什么意思
富士山什么时候喷发 太阳又什么又什么 相声海清是什么意思 老公工作劳累炖什么汤 气短是什么原因引起的
吃牛肉不能吃什么 咳嗽咳白痰是什么症状 身上肉疼是什么原因 益母草什么时候喝最好 什么球不能踢脑筋急转弯
流清水鼻涕是什么感冒hcv9jop1ns4r.cn 1967属什么生肖wmyky.com 脚筋膜炎什么办法恢复的最快hcv8jop6ns1r.cn 脑膜炎是什么原因引起的hcv8jop7ns9r.cn 出虚恭是什么意思hcv7jop6ns1r.cn
bpd是胎儿的什么意思hcv8jop5ns9r.cn 乙丑是什么生肖zhongyiyatai.com ecom什么意思hcv7jop4ns8r.cn 为什么手比脸白那么多xscnpatent.com 吃什么升血小板最快最好hcv8jop7ns3r.cn
吃什么食物能降低胆固醇hcv9jop4ns5r.cn 天然气是什么气体hcv9jop3ns1r.cn 日本人为什么长寿hcv9jop3ns1r.cn 胎停有什么症状hcv9jop5ns0r.cn 儿童弱视是什么原因引起的hcv8jop0ns7r.cn
鸡飞狗跳是什么意思hcv9jop6ns0r.cn 副省长是什么级别hcv8jop7ns4r.cn 尿肌酐低是什么原因hcv8jop0ns8r.cn 微波炉可以做什么美食bjhyzcsm.com 维c之王是什么水果xinjiangjialails.com
百度