这个很少被人意识到,2个分别对应到c头文件定义和c++头文件定义,日常使用没有影响是因为先包含的会使后续包含定义触发条件编译,而且经常using namespace std;使不区分std:size_t。做为一个优秀的代码输出者,要严谨的弄清楚,有针对性的处理,提高代码质量,降低代码开发周期。
结论:c和C++混编,尤其是跨平台时,一定要注意头文件包含顺序,如果是c++,最早的包含c++的头文件,如果是c,则晚一些包含c++头文件,这是有差异的,不保证完全等价。
第一部分,影响:
对于业务逻辑,包括typeid等,都没有影响,因为条件编译是预处理阶段完成,编译阶段面对的已经是基础类型定义。
但是,毕竟两个文件是独立的,在跨平台编译等情况下,类型定义仅为了保证长度相等,两个文件可能会产生定义差异,导致类型不匹配,比如
#include <iostream> #include <typeinfo> using namespace std; typedef long long type1; typedef int64_t type2; int main() { type1 s1 = 0; type2 s2 = 0; cout << sizeof(type1) << " " << sizeof(type2) << endl; cout << (typeid(s1) == typeid(s2) ? "eq" : "nq") << endl; cout << typeid(s1).name() << endl; cout << typeid(s2).name() << endl; return 0; } 输出 8 8 nq x l
这与逻辑是对不上的,位长一样,符号一样,却是不同的类型。
第二部分,验证一下区别,通过将size_t重定义产生冲突报错来查看定义源
#include <stdio.h> typedef bool size_t; int main() { return 0; }
编译报错:
main.cpp:3:14: error: conflicting declaration ‘typedef bool size_t’typedef bool size_t;
^
In file included from /usr/include/stdio.h:34:0,
from main.cpp:1:
/opt/rh/devtoolset-2/root/usr/lib/gcc/x86_64-redhat-linux/4.8.2/include/stddef.h:212:23: error: ‘size_t’ has a previous declaration as ‘typedef long unsigned int size_ ’
typedef __SIZE_TYPE__ size_t;
^
make: *** [main] Error 1
继续追踪:
/opt/rh/devtoolset-2/root/usr/lib/gcc/x86_64-redhat-linux/4.8.2/include/stddef.h:209:#define __SIZE_TYPE__ long unsigned int
所以C头文件定义是:long unsigned int
再来看一下c++定义
#include <iostream> using namespace std; namespace std { typedef bool size_t; } int main() { return 0; }编译报错
main.cpp:7:15: error: conflicting declaration ‘typedef bool std::size_t’
typedef bool size_t;
^
In file included from /opt/rh/devtoolset-2/root/usr/include/c++/4.8.2/iostream:38:0,
from main.cpp:2:
/opt/rh/devtoolset-2/root/usr/include/c++/4.8.2/x86_64-redhat-linux/bits/c++config.h:1857:26: error: ‘std::size_t’ has a previous declaration as ‘typedef long unsigned int std::size_t’
typedef __SIZE_TYPE__ size_t;
^
make: *** [main] Error 1
进一步追踪:
bits/c++config.h:1764 if __cplusplus
...
bits/c++config.h:1855 namespace std
{
typedef __SIZE_TYPE__ size_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
#if __cplusplus >= 201103L
typedef decltype(nullptr) nullptr_t;
#endif
}
这个做法非常聪明,直接使用了系统的__SIZE_TYPE__,所以必然和C一致