网站首页 > 教程分享 正文
想象一下我们想创建一个程序,该程序在编译时将告诉我们如何使用C或C ++的标准进行编译。 显然,我们不能使用C和C
++都不具有的任何功能,因此不能使用模板魔术,因此我们将无法区分C ++ 98和C ++ 03或C ++ 11,C ++ 14 ,C ++
17或C ++ 20。 显然,我们也不会试图说明C89和C90之间的区别。
而且,我们将仅考虑C89之后的C,因为它不一定总是在之前一致地实现,并且K&R函数签名很难看。
我们将尽量不使用C预处理程序,但是为了告诉C11之前的版本,我们需要引入一些宏。
C和C ++之间的第一个也是最简单的区别之一。 在C语言中,像'a'这样的字符文字与int大小相同。 在C
++中,它的大小与char相同。
现在,如果您在一个int和char大小相同的平台上,那么您将需要进行不同的测试(在2020年秋季这个时代,即使大多数嵌入式芯片也正在转向32位ARM
/ RISC-V /其他任何版本(我相信大多数常用的16位芯片都有一个与char大小不同的int,在这种情况下,我们不希望出现这种情况。
因此,我们的第一个功能是:
static int is_C(void){
int a=0; char b='\0';
assert(sizeof(a)!=sizeof(b));
return(sizeof('\0') == sizeof(a));
}
下一个主要区别是C99之前的C和C99之后的C。 最大的变化是允许使用C ++样式的内联注释。 因此,您可以使用'// any'来代替'/ * any * /'。 这导致我们:
static int is_post_ANSI_C(void){
return 1//**/2
;
}
因此,如果我们具有C ++样式的内联注释,则由于该行的其余部分为注释,因此将返回1。 如果不这样做,那么我们将有一个“ /”,后跟一个注释,后跟2,因此在注释和空格删除之后,我们得到“ return 1/2;”。 根据整数除法规则我们知道它是0。
接下来是为了区分2011年之后的C和C ++版本,以及在我们需要使用C Preprocessor宏之前的版本。
在C11和C ++ 11修订版之后,通过为字符串文字添加一些新前缀以允许在字符串中使用Unicode,该语言发生了显着变化(请参阅本页 ,以获取有关各种前缀的含义的良好参考,一般为cppreference)。 com是有关C或C ++的良好信息来源)。 这是我们的宏和功能:
#define test(U) U"1"
static int is_post_11(void){
return(sizeof(test()[0]) >1);
}
这使用了Don Yang的技巧,因为在标准的先前版本中,预处理器会将定义中的“ U”视为提供给“ test”函数类型宏的自变量值。
在return语句中,我们不传入任何参数,因此'U'被替换为空,而我们只得到'sizeof(“ 1” [0])>
1',这只是'sizeof(char)> 1',始终假。 在标准的更高版本中,“
U”被解析为字符串文字的前缀,在这种情况下为32位宽的unicode字符串,因此字符串中跟随“ U”字符的每个元素必须至少为32位宽。
只要我们不再具有> = 32位字符的体系结构上,这将导致'sizeof(至少32位)> 1',在这种情况下将是正确的。
如果针对C2x标准的建议N2231通过,那么C ++ 20和C2x都将具有char8_t数据类型,该数据类型将是'u8'前缀字符串文字的类型,这将是我们可以做的另一项测试。
最终程序在这里:
#include <stdio.h>
#include <assert.h>
static int is_post_ANSI_C(void){
return 1//**/2
;
}
static int is_C(void){
int a=0; char b='\0';
assert(sizeof(a)!=sizeof(b));
return(sizeof('\0') == sizeof(a));
}
#define test(U) U"1"
static int is_post_11(void){
return(sizeof(test()[0]) >1);
}
int main(int argc, char*argv[])
{
int C = is_C();
int post_11 = is_post_11();
int post_ANSI_C = is_post_ANSI_C();
if(C && post_ANSI_C && post_11){
printf("This is C11 or later!\n");
}
if(C && post_ANSI_C && !post_11){
printf("This is C99!\n");
}
if(C && !post_ANSI_C && !post_11){
printf("This is C89 or C90\n");
}
if(!C && post_11){
printf("This is C++11 or later\n");
}
if(!C && !post_11){
printf("This is C++98 or C++03\n");
}
return0;
}
可以使用以下命令进行编译:
gcc-std=c89 main.c
要么
g++ -std=c++98 main.c
然后可以运行为:
/a.out
猜你喜欢
- 2024-10-18 信号 - Linux Signal - 网络编程的相关信号
- 2024-10-18 干货 | 一文搞定 pytest 自动化测试框架(一)
- 2024-10-18 linux网络编程—tcp和udp基本函数调用过程及如何选择
- 2024-10-18 C语言之结构体基础(c语言结构体经典例题)
- 2024-10-18 linux定时器编程详解(包含代码)(linux定时器执行脚本)
- 2024-10-18 C语言学习第16篇---三目运算符和逗号表达式
- 2024-10-18 Linux网络编程相关高级I/O函数 - 用于创建文件描述符的函数
- 2024-10-18 干货 | 一文搞定 pytest 自动化测试框架(二)
- 2024-10-18 现代c++之移动构造,移动赋值,拷贝构造,拷贝赋值
- 2024-10-18 探索C语言断言:保证程序的健壮性和可靠性
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- css导航条 (66)
- sqlinsert (63)
- js提交表单 (60)
- param (62)
- parentelement (65)
- jquery分享 (62)
- check约束 (64)
- curl_init (68)
- sql if语句 (69)
- import (66)
- chmod文件夹 (71)
- clearinterval (71)
- pythonrange (62)
- 数组长度 (61)
- javafx (59)
- 全局消息钩子 (64)
- sort排序 (62)
- jdbc (69)
- php网页源码 (59)
- assert h (69)
- httpclientjar (60)
- postgresql conf (59)
- winform开发 (59)
- mysql数字类型 (71)
- drawimage (61)
本文暂时没有评论,来添加一个吧(●'◡'●)