NULL是个指针,还是个整数?0?或(void*)0?答案是和g++版本有关。g++ 4.6支持C++11,引入了nullptr,也许会发生变化。

可以写段简单代码求证一下:

#include <stdio.h>

#include <typeinfo>

int main()

{

printf("NULL: %d\n", NULL);

printf("sizeof(NULL): %d\n", sizeof(NULL));

printf("typeid(__null).name(): %s\n", typeid(__null).name());

printf("typeid(0).name(): %s\n", typeid(0).name());

return 0;

}

使用g++ 4.1.2(SuSE 10.1)编译,输出结果如下:

NULL: 0

sizeof(NULL):

typeid(__null).name(): l

typeid(0).name(): i

从输出结果,可以看到NULL是long类型的整数,定义应当是0L或0LL。

下面再借助gdb,来看一看它的真面目(博文:《GDB高级技巧》有介绍gdb的高级使用)。假设源文件名为x.cpp,使用如下方法编译:

g++ -g3 -gdwarf-2 -o x x.cpp

注意这里使用了参数“-g3 -gdwarf-2”。其中“-g3”不能是“-g”。

编译成功后,在gdb中跟踪运行程序,在main函数处打断点即可:

adoop@VM-39-166-sles10-64:~/current> gdb ./x

GNU gdb 6.6

Copyright (C) 2006 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB.  Type "show warranty" for details.

This GDB was configured as "x86_64-suse-linux"...

Using host libthread_db library "/lib64/libthread_db.so.1".

(gdb) b main

Breakpoint 1 at 0x4005dc: file x.cpp, line 6.

(gdb) r

Starting program: /data/hadoop/hadoop-2.4.0/x

Breakpoint 1, main () at x.cpp:6

6               printf("NULL: %d\n", NULL);

(gdb) macro expand NULL

expands to: __null

(gdb) p NULL

No symbol "__null" in current context.

(gdb) ptype NULL

No symbol "__null" in current context.

(gdb) p __null

No symbol "__null" in current context.

(gdb) ptype __null

No symbol "__null" in current context.

(gdb)

从gdb的跟踪结果,不难看到NULL的真身是__null,但__null又是什么了?试图从/usr/include中找到答案:

hadoop@VM-39-166-sles10-64:~/current> grep __null /usr/include/*

/usr/include/libio.h:#  define NULL (__null)

hadoop@VM-39-166-sles10-64:~/current> grep __null /usr/include/*/*

/usr/include/asm-i386/vm86.h:   long __null_ds;

/usr/include/asm-i386/vm86.h:   long __null_es;

/usr/include/asm-i386/vm86.h:   long __null_fs;

/usr/include/asm-i386/vm86.h:   long __null_gs;

/usr/include/asm-i386/vm86.h:   long __null_ds;

/usr/include/asm-i386/vm86.h:   long __null_es;

未能找到满意的答案,那么__null只能是g++内置定义的,所以未出现在任何头文件中,事实证明也如此,在代码中可以直接使用__null(尽管如此,但这个不是个好主意):

#include <stdio.h>

#include <typeinfo>

int main()

{

printf("NULL: %d\n", NULL);

printf("NULL: %d\n", __null);

printf("sizeof(NULL): %d\n", sizeof(NULL));

printf("typeid(__null).name(): %s\n", typeid(__null).name());

printf("typeid(0).name(): %s\n", typeid(0).name());

return 0;

}

执行man g++,然后搜索“__null”,找到一个有关的条目:

-Wstrict-null-sentinel (C++ only)

Warn also about the use of an uncasted "NULL" as sentinel.  When compiling only with GCC this is a valid sentinel, as "NULL" is defined to "__null".  Although it is a null pointer constant not a null pointer, it is guaranteed to of the same size as a pointer(保证和指针相同的大小).  But this use is not portable across different compilers.

搜索gcc 4.8.2源码中的FSFChangeLog.11文件:

Wed Aug  7 14:10:07 1996  Jason Merrill  <jason@yorick.cygnus.com>

* ginclude/stddef.h (NULL): Use __null for G++.

继续搜索gcc源代码,可以得到更多信息:

VM-39-166-sles10-64:/data/gcc-4.8.2/gcc # grep __null */*

c-family/c-common.c:  { "__null",               RID_NULL,       0 },

c-family/c-common.c:  /* Create the built-in __null node.  It is important that this is

c-family/c-common.c:      /* Although __null (in C++) is only an integer we allow it

c-family/c-common.h:/* The node for C++ `__null'.  */

cp/call.c:            /* If __null has been converted to an integer type, we do not

cp/NEWS:  <stddef.h> is now defined as __null, a magic constant of type (void *)

cp/parser.c:     __null

cp/parser.c:      /* The `__null' literal.  */

进一步查看c-family/c-common.c文件:

const struct c_common_resword c_common_reswords[] =

{

{ "__is_union",       RID_IS_UNION,   D_CXXONLY },

{ "__label__",        RID_LABEL,      0 },

{ "__null",           RID_NULL,       0 },

{ "__real",           RID_REALPART,   0 },

{ "__real__",         RID_REALPART,   0 },

{ "__restrict",       RID_RESTRICT,   0 },

结构体c_common_resword的定义在c-family/c-common.h中:

/* The node for C++ `__null'.  */

#define null_node                       c_global_trees[CTI_NULL]

/* An entry in the reserved keyword table.  */

struct c_common_resword

{

const char *const word;

ENUM_BITFIELD(rid) const rid : 16;

const unsigned int disable   : 16;

};

enum c_tree_index

{

。。。。。。

CTI_VOID_ZERO,

CTI_NULL,

CTI_MAX

};

查看文件cp/parser.c,parser.c是C/C++语法解析器的实现文件:

static tree

cp_parser_primary_expression (cp_parser *parser,

bool address_p,

bool cast_p,

bool template_arg_p,

bool decltype_p,

cp_id_kind *idk)

{

。。。。。。

case CPP_KEYWORD:

switch (token->keyword)

{

/* These two are the boolean literals.  */

case RID_TRUE:

cp_lexer_consume_token (parser->lexer);

return boolean_true_node;

case RID_FALSE:

cp_lexer_consume_token (parser->lexer);

return boolean_false_node;

/* The `__null' literal.  */

case RID_NULL:

cp_lexer_consume_token (parser->lexer);

return null_node;

/* The `nullptr' literal.  */

case RID_NULLPTR:

cp_lexer_consume_token (parser->lexer);

return nullptr_node;

g++中宏NULL究竟是什么?的更多相关文章

  1. C++ 中宏的使用 --来自:http://blog.csdn.net/hgl868/article/details/7058906

    宏在代码中的使用实例: g_RunLog2("Middleware client for Linux, build:%s %s", __DATE__, __TIME__); 下面详 ...

  2. ATL中宏定义offsetofclass的分析

    近日学习ATL,通过对宏定义offsetofclass的解惑过程.顺便分析下虚函数表,以及通过虚函数表调用函数的问题. 1 解开ATL中宏定义offsetofclass的疑惑 #define _ATL ...

  3. Oracle中的null

    测试数据:公司部分员工基本信息

  4. 正则表达式(/[^0-9]/g,'')中的"/g"是什么意思 ?

    正则表达式(/[^0-9]/g,'')中的"/g"是什么意思 ?     表达式加上参数g之后,表明可以进行全局匹配,注意这里“可以”的含义.我们详细叙述: 1)对于表达式对象的e ...

  5. SQL中的Null深入研究分析

    SQL中的Null深入研究分析 虽然熟练掌握SQL的人对于Null不会有什么疑问,但总结得很全的文章还是很难找,看到一篇英文版的, 感觉还不错. Tony Hoare 在1965年发明了 null 引 ...

  6. 深入详解SQL中的Null

    深入详解SQL中的Null NULL 在计算机和编程世界中表示的是未知,不确定.虽然中文翻译为 “空”, 但此空(null)非彼空(empty). Null表示的是一种未知状态,未来状态,比如小明兜里 ...

  7. 给定一个字符串里面只有"R" "G" "B" 三个字符,请排序,最终结果的顺序是R在前 G中 B在后。 要求:空间复杂度是O(1),且只能遍历一次字符串。

    题目:给定一个字符串里面只有"R" "G" "B" 三个字符,请排序,最终结果的顺序是R在前 G中 B在后. 要求:空间复杂度是O(1),且 ...

  8. JAVA中String = null 与 String = "" 的区别

    JAVA中String = null 与 String = ""的区别 笔者今天在Debug的时候发现的NPE(NullPointerException),辛辛苦苦地调试了半天,终 ...

  9. _DataStructure_C_Impl:求图G中从顶点u到顶点v的一条简单路径

    #pragma once #include<stdio.h> #include<stdlib.h> #define StackSize 100 typedef int Data ...

随机推荐

  1. toString()和toLocaleString()的区别

    在数字转换成字符串的时候,并没有感觉这两个方法有什么区别,如下: 1 2 3 4 5 6 7 8 var e=123     e.toString() "123"   e.toLo ...

  2. python _/__/__**__区别

    "_"单下划线:"单下划线 " 开始的成员变量叫做保护变量,意思是只有类对象(即类实例)和子类对象自己能访问到这些变量,需通过类提供的接口进行访问:不能用'fr ...

  3. Python ord(char)

    Given a string of length one, return an integer representing the Unicode code point of the character ...

  4. JSR-303 结合spring 校验

    使用注解 一.准备校验时使用的JAR validation-api-1.0.0.GA.jar:JDK的接口: hibernate-validator-4.2.0.Final.jar是对上述接口的实现: ...

  5. 关于python中的多进程模块multiprocessing

    python中的multiprocessing是一个多进程管理包,主要作用也就是提供多进程,而不是多线程,在其中用的比较多估计也就是Process和Pipe两个类,如下代码所示: #!/usr/bin ...

  6. leetcode819

    public class Solution { public string MostCommonWord(string paragraph, string[] banned) { //"a, ...

  7. Win7 资源管理器右键固定的文件夹不见了

    把常用的文件夹固定到任务栏的资源管理器右键菜单中 某天突然就不见了! %APPDATA%\Microsoft\Windows\Recent\AutomaticDestinations “最近" ...

  8. JAVA压缩 解压缩zip 并解决linux下中文乱码

    1. [代码][Java]代码   1:再压缩前,要设置linux模式, 需要使用第三方ant-1.6.5.jar  如果是文件目录,则ZipEntry zipEntry=new ZipEntry(b ...

  9. spring cloud zuul 配置(Robbin 和 熔断)

    #启动负载均衡的重试机制,默认falsespring.cloud.loadbalancer.retry.enabled=true#Hystrix是否启用超时时间hystrix.command.defa ...

  10. linux磁 盘分区 挂载

    f命令查看磁盘的分区和已经使用量 利用du命令查询当前目录下的所有目录/文件所占的容量 dumpe2fs查看分区的具体使用情况 磁盘的分区–命令fdisk fdisk /dev/sda 进入这个设备m ...