sizeof(char) C不是C++的子集:以一个简单的程序,来显示C和C++标准中的差异
想象一下,我们想要创建一个程序,在编译时,它会告诉我们如何使用 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 位芯片的 int 大小与 char 不同,在这种情况下我们不希望这样。
所以我们的第一个函数是:
int is_C(void){
整数a=0; char b='\0';
((a)!=(b));
(('\0') == (a));
下一个主要区别是 C99 之前的 C 和 C99 之后的 C。最大的变化是允许 C++ 风格的内联注释。因此,您可以使用“//any”而不是“/*any*/”。这导致我们:
int(无效){
1//**/2
因此,如果我们有 C++ 风格的内联注释,则将返回 1,因为该行的其余部分是注释。如果我们不这样做,那么我们将有一个“/”,后面跟着一个注释,然后是 2,所以在注释和空白删除之后,我们得到“1/2;”根据整数除法规则我们知道它是0。
下面是区分2011年之后的C和C++版本,以及之前需要使用C宏的版本。在 C11 和 C++11 修订版之后,语言发生了重大变化,向字符串文字添加了一些新的前缀,以允许它们在字符串中使用(有关各种前缀含义的更多信息,请参阅本页,一般来说是很好的参考)。 com 是有关 C 或 C++ 的良好信息来源)。这是我们的宏和函数:
# 测试(U)U“1”
int(无效){
((测试()[0]) >1);
这使用了 Don Yang 的技巧,因为在标准的早期版本中,预处理器将定义中的“U”视为提供给“test”函数类型宏的参数值。
如果你在学习C/C++的过程中遇到问题,可以加入小编的企鹅圈,向小编提问~小编很热心(●'◡'●)
在语句中,我们没有传入任何参数,因此 'U' 被替换为任何内容,我们只得到 '("1"[0])>
1',即'(char) > 1',始终为假。在该标准的后续版本中,“
U" 被解析为字符串文字的前缀,在本例中为 32 位宽字符串,因此字符串中“U”字符后面的每个元素必须至少为 32 位宽。
只要我们不在具有 >= 32 位字符的体系结构上,就会导致 (至少 32 位) > 1 ,在这种情况下这是正确的。
如果 C2x 标准的建议 N2231 获得通过,那么 C++20 和 C2x 都将具有以“u8”为前缀的字符串文字类型的数据类型,这将是我们可以做的另一个测试。
最终的程序在这里:
#
#
int(无效){
1//**/2
int is_C(void){
整数a=0; char b='\0';
((a)!=(b));
(('\0') == (a));
# 测试(U)U“1”
int(无效){
((测试()[0]) >1);
int main(int argc, char*argv[])
int C = is_C();
整数 = ();
整数 = ();
如果(C && && ){
("这是 C11 或更高版本!\n");
如果(C && &&!){
(“这是C99!\n”);
如果(C &&!&&!){
(“这是 C89 或 C90\n”);
如果(!C && ){
(“这是 C++11 或更高版本\n”);
如果(!C && !){
(“这是 C++98 或 C++03\n”);
;
可以使用以下命令进行编译:
gcc-std=c89 main.c
任何一个
g++ -std=c++98 main.c
然后可以这样运行:
/a.out