【理论实践】size_t和std:size_t可能是不同的类型定义,只是定义为相同的类型
2017-06-28 10:39
302 查看
这个很少被人意识到,2个分别对应到c头文件定义和c++头文件定义,日常使用没有影响是因为先包含的会使后续包含定义触发条件编译,而且经常using namespace std;使不区分std:size_t。做为一个优秀的代码输出者,要严谨的弄清楚,有针对性的处理,提高代码质量,降低代码开发周期。
结论:c和C++混编,尤其是跨平台时,一定要注意头文件包含顺序,如果是c++,最早的包含c++的头文件,如果是c,则晚一些包含c++头文件,这是有差异的,不保证完全等价。
第一部分,影响:
对于业务逻辑,包括typeid等,都没有影响,因为条件编译是预处理阶段完成,编译阶段面对的已经是基础类型定义。
但是,毕竟两个文件是独立的,在跨平台编译等情况下,类型定义仅为了保证长度相等,两个文件可能会产生定义差异,导致类型不匹配,比如
这与逻辑是对不上的,位长一样,符号一样,却是不同的类型。
第二部分,验证一下区别,通过将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++定义
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一致
结论: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一致
相关文章推荐
- 数据类型和抽象数据类型是如何定义的。二者有何相同和不同之处,抽象数据类型的主要特点是什么?使用抽象数据类型的主要好处是什么?
- 比较高效地实现从两个不同数组中提取相同部分组成新的数组(暂时只支持Int类型)
- Java 理论与实践--有效和正确定义hashCode()和equals()
- DLL函数定义和函数实现写函数类型的不同, 引起不能使用Dll中的函数
- 在C#中的一个类型定义,可能包含的所有成员
- 5.5.1 定义闭包和不同类型
- 数据类型的不同实现相同功能:代码的区别
- 定义相同FullName的类型
- flex 3 list控件添加Item的方法【1061: 调用可能未定义的方法 addItem (通过 static 类型 spark.components:List 引用)】
- 父类和子类的同名成员函数参数格式相同,返回值类型不同
- 学习effective java-19类和接口之接口只是用来定义类型
- 符合类型(引用,指针)的两种不同形式的定义
- [我们在不同的城市有着相同的故事 虽然不写实但怀抱同样的理想]这只是生辰图
- 合并不同WebService之间的相同对象类型
- 黄聪:DEDECMS联动调用时提示“你设定了字段为联动类型,但系统中没找到与你定义的字段名相同的联动组名!”
- ClassLoader:由不同的类加载器实例加载,那么它们的类型是不相同的
- STL程序设计实践六:自定义类型尽量定义恒等和小于操作符
- [转]比较高效地实现从两个不同数组中提取相同部分组成新的数组(只支持Int类型) [C#]
- 已定义了一个具有相同参数类型的成员
- C#方法参数个数和类型相同,名称不同,可以实现重载吗