C /C++标准库 - (stddef.h)

1. 概述

stddef.h定义了一些标准宏以及类型,是C语言标准所必须的一部分。

2. 定义

2.1 Types

序号 标记 原型 说明
1 ptrdiff_t 两个指针相减的结果的有符号整数类型
2 size_t 无符号整数类型,对数组下标或地址算数操作时使用
3 wchar_t c++已作为基本类型,不再任何头文件定义 宽字节字符类型,是一个整数,可以表示实现支持的所有款字节字符编码的所有编码值
4 max_align_t c++11 Type with widest scalar alignment
5 nullptr_t typedef decltype(nullptr) nullptr_t; 空指针类型,即nullptr是std::nullptr_t类型的(constexpr)变量。std::nullptr_t可以显式或隐式地转换为任何指针(包括类的成员函数指针),但不能显式或隐式地转换为任何其他类型

2.2 Macro functions

标记 原型 说明
offsetof offsetof (type,member) 返回size_t类型的常量表达式,其值为结构其实位置到结构成员的偏移量,以字节为单位

2.3 Macro constants

说明
NULL 通用空指针,可以作为不指向任何数据对象指针值直接使用,该宏可以定义为0/0L或(void*)0中的任何一个

3. NULL和nullptr的区别

1. 引入nullptr的原因

引入nullptr的原因,这个要从NULL说起。对于C和C++程序员来说,一定不会对NULL感到陌生。但是C和C++中的NULL却不等价。NULL表示指针不指向任何对象,但是问题在于,NULL不是关键字,而只是一个宏定义(macro)。

1.1 NULL在C中的定义

在C中,习惯将NULL定义为void*指针值0:

  #define NULL (void*)0  

但同时,也允许将NULL定义为整常数0

1.2 NULL在C++中的定义

在C++中,NULL却被明确定义为整常数0:

    // lmcons.h中定义NULL的源码 
    #ifndef NULL 
    #ifdef __cplusplus 
    #define NULL 0 
    #else 
    #define NULL ((void *)0) 
    #endif 
    #endif 

1.3为什么C++在NULL上选择不完全兼容C?

根本原因和C++的重载函数有关。C++通过搜索匹配参数的机制,试图找到最佳匹配(best-match)的函数,而如果继续支持void*的隐式类型转换,则会带来语义二义性(syntax ambiguous)的问题。

    // 考虑下面两个重载函数 
    void foo(int i);  
    void foo(char* p)  

    foo(NULL); // which is called? 

2. nullptr的应用场景

2.1 编译器

如果我们的编译器是支持nullptr的话,那么我们应该直接使用nullptr来替代NULL的宏定义。正常使用过程中他们是完全等价的。
对于编译器,Visual Studio 2010已经开始支持C++0x中的大部分特性,自然包括nullptr。而VS2010之前的版本,都不支持此关键字。
Codeblocks10.5附带的G++ 4.4.1不支持nullptr,升级为4.6.1后可支持nullptr(需开启-std=c++0x编译选项)
2.2 使用方法
0(NULL)和nullptr可以交换使用,如下示例:

  int* p1 = 0;  
    int* p2 = nullptr;  

    if(p1 == 0) {}  
    if(p2 == 0) {}  
    if(p1 == nullptr) {}  
    if(p2 == nullptr) {}  
    if(p1 == p2) {}  
    if(p2) {}  

不能将nullptr赋值给整形,如下示例:

    int n1 = 0;             // ok 
    int n2 = nullptr;       // error 

    if(n1 == nullptr) {}    // error 
    if(n2 == nullptr) {}    // error 
    if(nullprt) {}          // error 
    nullptr = 0             // error 

上面提到的重载问题,使用nullptr时,将调用char*。

  void foo(int)   {cout << "int" << endl;}  
    void foo(char*) {cout << "pointer" << endl;}  

    foo(0);       // calls foo(int) 
    foo(nullptr); // calls foo(char*) 

3. 模拟nullptr的实现

某些编译器不支持c++11的新关键字nullptr,我们也可以模拟实现一个nullptr。

  const  
    class nullptr_t_t  
    {  
    public:  
        template<class T>           operator T*() const {return 0;}  
        template<class C, class T>  operator T C::*() const { return 0; }  
    private:  
        void operator& () const;  
    } nullptr_t = {};  
    #undef NULL 
    #define NULL nullptr_t 

4. nullptr 和 nullptr_t解析

nullptr习惯被称作指针空值

nullptr_t习惯被称作指针空值类型

即表示指针空值类型并非仅有nullptr一个实例

可以通过nullptr_t来声明一个指针空值类型的变量

除去nullptr以及nullptr_t以外,C++中还存在各种内置类型。

C++11标准严格规定了数据间的关系。常见规则简单如下:

  1. 所有定义为nullprt_t类型的数据都是等价的,行为也完全一致

  2. nullprt_t类型数据可以隐式转换成任意一个指针类型

  3. nullptr_t类型数据不能转换为非指针类型,

即使使用reinterpret_cast也是不可以的

  1. nullptr_t类型数据不适用算术运算表达式

  2. nullptr_t类型数据可以用于关系运算表达式,

5. 关于nullptr和void*的称法

  • nullptr习惯被称作指针空值
  • void*习惯被称作无类型指针

6. 参考文献

  1. http://my.oschina.net/jthmath/blog/539845
  2. http://www.cplusplus.com/reference/cstddef/
  3. 《C标准库》,P.J. Plauger 著
  4. 《C语言参考手册》,Samuel P. Harbison III 等著
  5. nullptr详解:http://blog.csdn.net/huang_xw/article/details/8764346
  6. nullptr:http://www.cnblogs.com/Braveliu/p/4263355.html

你可能感兴趣的:(null,C语言,nullptr,stddef)