C和C++有许多不同之处,并非所有有效的C代码都是有效的C++代码.
("有效"是指具有已定义行为的标准代码,即不是特定于实现/未定义/等.)
在使用每种语言的标准编译器编译时,是否有任何一种在C和C++中都有效的代码会产生不同的行为?
为了使它成为一个合理/有用的比较(我试图学习一些实用的东西,而不是试图在问题中找到明显的漏洞),让我们假设:
#ifdef __cplusplus,pragma等) Set*_*gie 459
下面是一个利用C和C++中函数调用和对象声明之间差异的示例,以及C90允许调用未声明函数的事实:
#include <stdio.h>
struct f { int x; };
int main() {
f();
}
int f() {
return printf("hello");
}
Run Code Online (Sandbox Code Playgroud)
在C++中,这将不会打印任何内容,因为临时f创建和销毁,但在C90中它将打印,hello因为可以在未声明的情况下调用函数.
如果您想知道f两次使用的名称,C和C++标准明确允许这样做,并制作一个对象,您必须说明struct f是否需要结构消除歧义,或者struct如果您想要该功能则不要使用.
Jer*_*fin 420
对于C++与C90,至少有一种方法可以获得不是实现定义的不同行为.C90没有单行注释.稍加注意,我们可以使用它来创建一个在C90和C++中具有完全不同结果的表达式.
int a = 10 //* comment */ 2
+ 3;
Run Code Online (Sandbox Code Playgroud)
在C++中,从行//到结尾的所有内容都是注释,因此这可以解释为:
int a = 10 + 3;
Run Code Online (Sandbox Code Playgroud)
由于C90没有单行注释,因此只有/* comment */注释.第一个/和第二个2都是初始化的部分,所以它出现在:
int a = 10 / 2 + 3;
Run Code Online (Sandbox Code Playgroud)
所以,一个正确的C++编译器会给出13,但是一个严格正确的C90编译器8.当然,我只是在这里选择了任意数字 - 你可以根据需要使用其他数字.
Ale*_*nze 385
以下内容在C和C++中有效(最有可能)导致iC和C++中的值不同:
int i = sizeof('a');
Run Code Online (Sandbox Code Playgroud)
有关差异的解释,请参阅C/C++中的字符大小('a').
#include <stdio.h>
int sz = 80;
int main(void)
{
struct sz { char c; };
int val = sizeof(sz); // sizeof(int) in C,
// sizeof(struct sz) in C++
printf("%d\n", val);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
det*_*zed 172
C90 vs. C++ 11(intvs. double):
#include <stdio.h>
int main()
{
auto j = 1.5;
printf("%d", (int)sizeof(j));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在C中auto表示局部变量.在C90中,可以省略变量或函数类型.它默认为int.在C++ 11中auto意味着完全不同的东西,它告诉编译器从用于初始化它的值推断变量的类型.
god*_*eek 115
另一个我还没有提到过的例子,这个例子突出了预处理器的区别:
#include <stdio.h>
int main()
{
#if true
printf("true!\n");
#else
printf("false!\n");
#endif
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这在C中打印"false",在C++中打印"true" - 在C中,任何未定义的宏的计算结果为0.在C++中,有1个例外:"true"计算结果为1.
Kir*_*lev 105
每个C++ 11标准:
一个.逗号运算符在C中执行左值到右值的转换但不是C++:
char arr[100];
int s = sizeof(0, arr); // The comma operator is used.
Run Code Online (Sandbox Code Playgroud)
在C++中,此表达式的值将为100,而在C中,这将是sizeof(char*).
湾 在C++中,枚举器的类型是它的枚举.在C中,枚举器的类型是int.
enum E { a, b, c };
sizeof(a) == sizeof(int); // In C
sizeof(a) == sizeof(E); // In C++
Run Code Online (Sandbox Code Playgroud)
这意味着sizeof(int)可能不等于sizeof(E).
C.在C++中,使用空参数列表声明的函数不带参数.在C空参数列表中,表示函数参数的数量和类型是未知的.
int f(); // int f(void) in C++
// int f(*unknown*) in C
Run Code Online (Sandbox Code Playgroud)
Pav*_*aev 51
该程序1以C++和0C 格式打印:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int d = (int)(abs(0.6) + 0.5);
printf("%d", d);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
发生这种情况是因为double abs(double)C++中存在重载,因此在C中abs(0.6)返回0.6时返回,0因为在调用之前隐式的double-int转换int abs(int).在C中,您必须使用fabs它double.
Ale*_*x B 37
另一个sizeof陷阱:布尔表达式.
#include <stdio.h>
int main() {
printf("%d\n", (int)sizeof !0);
}
Run Code Online (Sandbox Code Playgroud)
它等于sizeof(int)C,因为表达式是类型的int,但在C++中通常是1(尽管不是必须的).在实践中,它们几乎总是不同的.
Ada*_*eld 36
#include <stdio.h>
int main(void)
{
printf("%d\n", (int)sizeof('a'));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在C中,这将打印sizeof(int)当前系统上的任何值,这通常4在当今通常使用的大多数系统中.
在C++中,必须打印1.
der*_*ert 25
C++编程语言(第3版)给出了三个例子:
sizeof('a'),正如@Adam Rosenfield所说;
// 用于创建隐藏代码的注释:
int f(int a, int b)
{
return a //* blah */ b
;
}
Run Code Online (Sandbox Code Playgroud)结构等将东西隐藏在范围内,如您的示例所示.
dmc*_*kee 24
一个依赖于C编译器的旧栗子,没有识别C++行尾注释......
...
int a = 4 //* */ 2
+2;
printf("%i\n",a);
...
Run Code Online (Sandbox Code Playgroud)
Joh*_*itb 20
C++标准列出的另一个:
#include <stdio.h>
int x[1];
int main(void) {
struct x { int a[2]; };
/* size of the array in C */
/* size of the struct in C++ */
printf("%d\n", (int)sizeof(x));
}
Run Code Online (Sandbox Code Playgroud)
fkl*_*fkl 20
C中的内联函数默认为外部作用域,而C++中的内联函数则不行.
将以下两个文件一起编译将在GNU C的情况下打印"我是内联"但对C++没有任何内容.
档案1
#include <stdio.h>
struct fun{};
int main()
{
fun(); // In C, this calls the inline function from file 2 where as in C++
// this would create a variable of struct fun
return 0;
}
Run Code Online (Sandbox Code Playgroud)
档案2
#include <stdio.h>
inline void fun(void)
{
printf("I am inline\n");
}
Run Code Online (Sandbox Code Playgroud)
此外,C++隐式地将任何const全局视为static除非显式声明extern,不像C extern是默认值.
小智 16
struct abort
{
int x;
};
int main()
{
abort();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
返回C++中的退出代码为0或C中的3.
这个技巧可能会用来做一些更有趣的事情,但是我想不出一个创建一个适合C的构造函数的好方法.我尝试用复制构造函数创建一个类似无聊的例子,这会让一个参数通过,虽然是一种相当不便携的方式:
struct exit
{
int x;
};
int main()
{
struct exit code;
code.x=1;
exit(code);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然而,VC++ 2005拒绝在C++模式下编译它,抱怨重新定义了"退出代码".(我认为这是一个编译器错误,除非我突然忘记了如何编程.)当编译为C时,退出时进程退出代码为1.
wef*_*fa3 15
#include <stdio.h>
struct A {
double a[32];
};
int main() {
struct B {
struct A {
short a, b;
} a;
};
printf("%d\n", sizeof(struct A));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当使用C++编译器编译时以及使用C编译器编译时,此程序打印128(32 * sizeof(double))4.
这是因为C没有范围解析的概念.在C结构中包含的其他结构被置于外部结构的范围内.
小智 7
不要忘记C和C++全局命名空间之间的区别.假设你有一个foo.cpp
#include <cstdio>
void foo(int r)
{
printf("I am C++\n");
}
Run Code Online (Sandbox Code Playgroud)
和一个foo2.c
#include <stdio.h>
void foo(int r)
{
printf("I am C\n");
}
Run Code Online (Sandbox Code Playgroud)
现在假设你有一个main.c和main.cpp,它们看起来像这样:
extern void foo(int);
int main(void)
{
foo(1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当编译为C++时,它将使用C++全局命名空间中的符号; 在C中它将使用C一:
$ diff main.cpp main.c
$ gcc -o test main.cpp foo.cpp foo2.c
$ ./test
I am C++
$ gcc -o test main.c foo.cpp foo2.c
$ ./test
I am C
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
42791 次 |
| 最近记录: |