C语言宏和Rust宏的区别?用AND替换&&?新类型?_GNU_SOURCE?如何知道g++编译默认会定义_GNU_SOURCE?ifdef和#if defined的区别是什么?

目录

C语言宏和Rust宏的区别

宏展开

用AND替换&&

新类型

_GNU_SOURCE

如何知道g++编译默认会定义_GNU_SOURCE?

ifdef和#if defined的区别是什么?


C语言宏和Rust宏的区别

C语言诞生早于Unix系统,宏的设计没有类型、安全,简单直接的文本替换规则,同时也不可避免可能产生一些问题。Rust语言基于很多优秀编程语言基础之上,设计考虑了类型安全和代码的可维护性,编译器可以介入宏处理,可以减少程序员犯错。

宏展开

C/C++/ObjC/Rust都支持宏(Macro), 同时也提供宏展开参数便于程序员分析宏替换是否符合预期。

  • GCC/Clang提供-E参数输出预处理后的讯息,MSVC则提供/E参数。
  • Rust提供-Z unstable-options --pretty=expanded参数组合得到宏扩展。
    rustc -Z unstable-options --pretty=expanded demo.rs

用AND替换&&

#define可以将一个标识符替换成另外一段文本(可以是任何文本)。#define AND &&可以在代码用AND指代&&. 这种设计能让程序员更自由扩展个性化语言,对于任何运算符,都可以用相应的"英文"代替,还可以有OR, EQUALS, NEQ, GTR, LESS等等。

让int变成short

新类型

编程语言默认提供的类型显然不能满足人类的需要,定义新类型是高级编程语言必须解决的事情。大部分编程语言提供形如结构体或者类,枚举也是一种简单的新类型。

  • C/ObjC/C++提供宏定义的方式可以用文本替换的方式引入"新类型",同时也提供typedef定义新类型。
  • C#也可以用宏#define, 但不能做文本替换,不是为了定义类型,为了定义功能,比如DEBUG.
  • Java没有宏定义。
  • Python提供了import ... as ...的方式,可以算新类型,在C#中用using ... = ... 实现。
  • Go提供type newType oldType定义新类型。
  • Rust和Go类似,语法为type newType = oldType.
  • Kotlin 用 typealias 定义别名。

_GNU_SOURCE

g++编译比gcc编译,默认会开启_GNU_SOURCE宏,会产生features的差异,这是为什么有时用gcc无法编译过,g++却可以编译过的原因。

/usr/include/features.h当_GNU_SOURCE定义后,打开很多GNU features.

/* If _GNU_SOURCE was defined by the user, turn on all the other features. */
#ifdef _GNU_SOURCE
#undef _ISOC95_SOURCE
#define _ISOC95_SOURCE 1
#undef _ISOC99_SOURCE
#define _ISOC99_SOURCE 1
#undef _ISOC11_SOURCE
#define _ISOC11_SOURCE 1
#undef _ISOC2X_SOURCE
#define _ISOC2X_SOURCE 1
#undef _POSIX_SOURCE
#define _POSIX_SOURCE 1
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#undef _XOPEN_SOURCE
#define _XOPEN_SOURCE 700
#undef _XOPEN_SOURCE_EXTENDED
#define _XOPEN_SOURCE_EXTENDED 1
#undef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE 1
#undef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE 1
#undef _ATFILE_SOURCE
#define _ATFILE_SOURCE 1
#undef _DYNAMIC_STACK_SIZE_SOURCE
#define _DYNAMIC_STACK_SIZE_SOURCE 1
#endif

一种解法是在.c文件开头#define _GNU_SOURCE强制开启GNU features,或者放在编译选项中。

如何知道g++编译默认会定义_GNU_SOURCE?

可以通过g++ --verbose选项查看g++定义了哪些宏。

gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)
COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'a-'
/usr/lib/gcc/x86_64-linux-gnu/11/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE 1.c -quiet -dumpdir a- -dumpbase 1.c -dumpbase-ext .c -mtune=generic -march=x86-64 -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccVq1vV1.s

ifdef和#if defined的区别是什么?

#if defined它提供了更大的灵活性,可以在括号内使用更复杂的宏表达式,如 defined(MACRO1) && defined(MACRO2)。而#ifdef后面只可以跟一个macro.


若文章对您有帮助,欢迎关注 程序员小迷 。助您在编程路上越走越好!

微风不燥,阳光正好,你就像风一样经过这里,愿你停留的片刻温暖舒心。

我是 程序员小迷 (致力于C、C++、C#、Android、iOS、Java、Kotlin、Objective-C、Swift、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享),若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢,您的支持是我们为您提供帮助的最大动力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值