GCC中常用的宏

2022年 5月 20日 106点热度 0人点赞

file

含义
__BASE_FILE__ 表示主输入文件的名字
__CHAR_UNSIGNED__ 用于指定该机器上 char 是无符号类型
__COUNTER__ 自身计数器, 用于记录以前编译过程中出现的 __COUNTER__ 的次数, 从 0 开始计数. 常用于构造一系列的变量名称, 函数名称等
__cplusplus 使用 C++ 编译器编译
__DATE__ 最后一次编译的日期 (字符串形式)
__FILE__ 编译文件名
__func__ __FUNCTION__
__FUNCTION__ 函数名
__GNUC__ GCC 的主版本号
__GNUC_MINOR__ GCC 的次版本号
__GNUC_PATCHLEVEL__ GCC 的修订号
__GNUG__ 由 C++ 编译程序定义
__INCLUDE_LEVEL__ #include 的层次. 用于表示文件被包含的计数, 从 0 开始递增, 常作为递归包含的限制条件.
__LINE__ 本行位于该文件的第几行
__NASE_FILE__ 源文件的完整路径名, 和 FILE 不同, 被引用的文件仍然是原来文件名
__NO_INLINE__ 不允许 inline
__OPTIMIZE__ 打开了优化选项
__OPTIMIZE_SIZE__ 打开了对编译出文件尺寸的优化
__PRETTY_FUNCTION__ c 语言中和同上, C++中稍有区别
__STDC__ 表示该程序符合 ansi C 标准
__STDC_HOSTED__ 表示宿主具有标准 C 的环境
__STDC_VERSION__ 标准 C 制定时间
__TIME__ 最后一次编译的时间 (字符串形式)
__TIMESTAMP__ __TIME__ 的格式相同. 同于得到本文件最后一次被修改的时间.
__VA_ARGS__ 格式化输出
__VERSION__ 用于得到编译器的版本.
_WIN32
WIN32
_WIN64
_DEBUG 当我们的工程设置为 debug 版编译时, 编译器会定义该宏; 该宏与 #ifdef 等预编译语句一起进行条件编译, 以区分 debug 和 release 版本功能.
ASSERT 断言, 当该宏后面的语句值为 0 时引起程序中断, 只在 debug 版中有效.
VERIFY ASSERT 功能类似, 在 debug 和 release 版本中均有效.
ASSERT_VALID 检查后面参数指针是否为空, 只在 debug 版中有效.
TRACE 格式化输出字符串信息.
_ATL_VER 指明 ATL 的版本.
_CLR_VER 指明公共运行时 (commonlanguage runtime) 的版本.
_COUNTER_ 一个从 0 开始的全局的计数器, 每次用于源文件或在源文件中被引用头文件时, 自动加 1.
_DLL 当工程类型为动态链接库时, 该值为 1.
WINVER 指示 Windows 版本.
_MFC_VER 指示 MFC 版本.
_MSC_VER 指示编译器版本.
_WIN32 为 Win32 和 Win64 程序定义.

__VA_ARGS__ 的使用例子

#define ct_verbose(level, chfr, ...)  ct_log("", 0, "", level , NULL, chfr, __VA_ARGS__)

其他的更简单, 就不写了.

在标准 C 以及各中编译器中定义了一些对象宏, 这些宏的名称以 __ 开头和结尾, 并且都是大写字符. 这些预定义宏可以被 #undef, 也可以被重定义.

在 ANSI C 标准中定义了 __FILE__, __LINE__, __DATA__, __TIME__, __STDC__ 等标准的预定义宏. GCC 对其进行扩展, 也定义了多个预定义宏.

下面是 glib 把调试信息定义成宏:

#if defined(__GNUC__) && (__GNUC__ < 3) && ! defined(__cplusplus)
#  define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__) ":" __PRETTY_FUNCTION__ "()"
#else
#  define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__)
#endif

查看 gcc 所定义的宏的命令:cpp -dM /dev/null

命令一: cpp -dM /dev/null
命令二: gcc -dM -E - < /dev/null
1:OS MACRO:
  WINDOWS: _WIN32, WIN32,_WIN64;
  UNIX: unix, __unix,__unix__;   LINUX : linux, __linux,__linux__,__gnu_linux__;
  SunOS/SOLARIS: __SVR4, __svr4__,sun,__sun,__sun__,sparc,__sparc,__sparc__;
  HPUX: __hppa, __hppa__,__hpux,__hpux__,_HPUX_SOURCE;
  AIX: _AIX, _AIX32,_AIX41,_AIX43,_AIX51,_AIX52;
  CPU: __x86_64, __x86_64__(Intel); __amd64, __amd64__(AMD); sparc, __sparc,__sparc__(Sun-SPARC);
2:Compiler MACRO:
  __STDC__: ANSI C 标志, 值为 1, 说明兼容 ANSI C 标准;
  __GNUC__: 它是 gcc 编译器编译代码时预定义的一个宏; 需要针对 gcc 编写代码时, 可以使用这个宏进行条件编译;__GNUC__ 的值表示 gcc 的版本号, 需要针对特定版本的 gcc 编写代码时, 也可以使用这个宏进行条件编译;__GNUC__ 的类型是 int;
  __GNUC_MINOR__: gcc 的次版本号;
  __GNUC_PATCHLEVEL__: gcc 的修订号; 比如:gcc3.4.6 版本, 则 __GNUC__=3;__GNUC_MINOR__=4;__GNUC_PATCHLEVEL__=6;
  __GLIBC__: glib 的主版本号;
  __GLIBC_MINOR__: glib 的次版本号;
3: 常量宏:
  __PRETTY_FUNCTION__: 记录当前函数的函数头信息;
  __FUNCTION__: 仅记录当前函数名;
  __VA_ARGS__: 保存了可变参数列表"...";
4.C/C++原文件扩展名:
  .C: 用 C 语言编写的源代码文件;
  .CPP/.CXX: 用 C++语言编写的源代码文件;
  .H/.HPP/.HXX: 用 C/C++语言编写的头文件;

If

The #if directive allows you to test the value of an arithmetic expression, rather than the mere existence of one macro. Its syntax is

#if expression

controlled text

#endif /* expression */

expression is a C expression of integer type, subject to stringent restrictions. It may contain

  • Integer constants.
  • Character constants, which are interpreted as they would be in normal code.
  • Arithmetic operators for addition, subtraction, multiplication, division, bitwise operations, shifts, comparisons, and logical operations (&& and ||). The latter two obey the usual short-circuiting rules of standard C.
  • Macros. All macros in the expression are expanded before actual computation of the expression's value begins.
  • Uses of the defined operator, which lets you check whether macros are defined in the middle of an '#if'.
  • Identifiers that are not macros, which are all considered to be the number zero. This allows you to write #if MACRO instead of #ifdef MACRO, if you know that MACRO, when defined, will always have a nonzero value. Function-like macros used without their function call parentheses are also treated as zero.

In some contexts this shortcut is undesirable. The -Wundef option causes GCC to warn whenever it encounters an identifier which is not a macro in an '#if'.

The preprocessor does not know anything about types in the language. Therefore, sizeof operators are not recognized in '#if', and neither are enum constants. They will be taken as identifiers which are not macros, and replaced by zero. In the case of sizeof, this is likely to cause the expression to be invalid.

The preprocessor calculates the value of expression. It carries out all calculations in the widest integer type known to the compiler; on most machines supported by GCC this is 64 bits. This is not the same rule as the compiler uses to calculate the value of a constant expression, and may give different results in some cases. If the value comes out to be nonzero, the '#if' succeeds and the controlled text is included; otherwise it is skipped.

Ifdef

The simplest sort of conditional is

#ifdef MACRO

controlled text

#endif /* MACRO */

This block is called a conditional group. controlled text will be included in the output of the preprocessor if and only if MACRO is defined. We say that the conditional succeeds if MACRO is defined, fails if it is not.

The controlled text inside of a conditional can include preprocessing directives. They are executed only if the conditional succeeds. You can nest conditional groups inside other conditional groups, but they must be completely nested. In other words, '#endif' always matches the nearest '#ifdef' (or '#ifndef', or '#if'). Also, you cannot start a conditional group in one file and end it in another.

Even if a conditional fails, the controlled text inside it is still run through initial transformations and tokenization. Therefore, it must all be lexically valid C. Normally the only way this matters is that all comments and string literals inside a failing conditional group must still be properly ended.

The comment following the '#endif' is not required, but it is a good practice if there is a lot of controlled text, because it helps people match the '#endif' to the corresponding '#ifdef'. Older programs sometimes put MACRO directly after the '#endif' without enclosing it in a comment. This is invalid code according to the C standard. CPP accepts it with a warning. It never affects which '#ifndef' the '#endif' matches.

Sometimes you wish to use some code if a macro is not defined. You can do this by writing '#ifndef' instead of '#ifdef'. One common use of '#ifndef' is to include code only the first time a header file is included. See Once-Only Headers.

Macro definitions can vary between compilations for several reasons. Here are some samples.

  • Some macros are predefined on each kind of machine (see System-specific Predefined Macros). This allows you to provide code specially tuned for a particular machine.
  • System header files define more macros, associated with the features they implement. You can test these macros with conditionals to avoid using a system feature on a machine where it is not implemented.
  • Macros can be defined or undefined with the -D and -U command-line options when you compile the program. You can arrange to compile the same source file into two different programs by choosing a macro name to specify which program you want, writing conditionals to test whether or how this macro is defined, and then controlling the state of the macro with command-line options, perhaps set in the Makefile. See Invocation.
  • Your program might have a special header file (often called config.h) that is adjusted when the program is compiled. It can define or not define macros depending on the features of the system and the desired capabilities of the program. The adjustment can be automated by a tool such as autoconf, or done by hand.

main 函数的四种写法:

  int main(void)
  int main(int argc)
  int main(int argc, char** argv)
  int main(int argc, char** argv, char** env)

VC++的版本号宏:

Visual Studio 5.0  --> VC++5.0 _MSC_VER = 1100
Visual Studio 6.0  --> VC++6.0 _MSC_VER = 1200
Visual Studio 2002 --> VC++7.0 _MSC_VER = 1300
Visual Studio 2003 --> VC++7.1 _MSC_VER = 1310
Visual Studio 2005 --> VC++8.0 _MSC_VER = 1400
Visual Studio 2008 --> VC++9.0 _MSC_VER = 1500

参考

rainbow

这个人很懒,什么都没留下

文章评论