NULL究竟是个什么东东?

发表于:2007-05-25来源:作者:点击数: 标签:东东例如是个NULL究竟
例如 char*p="hello"; 这时候p的值是一个地址,指向hello 然后 令p=NULL; 意思是让指针失效,那么这时候p的值是多少?是不是一个非法的地址值就可。 也就是说,只要p指向的地址程序不可访问,p就是NULL。 所以NULL可以是很多不同的值。 flw 回复于:2004-09-

例如
char *p = "hello";
这时候p的值是一个地址,指向hello
然后
令p = NULL;
意思是让指针失效,那么这时候p的值是多少?是不是一个非法的地址值就可。
也就是说,只要p指向的地址程序不可访问,p就是NULL。
所以NULL可以是很多不同的值。

 flw 回复于:2004-09-10 16:45:16
在 VC 中,把鼠标挪到“NULL”这个字上面,它就原形毕露了。

 ljttlf 回复于:2004-09-10 16:47:54
c里面好象定义为(void *)0 ,但这个不是严谨的定义,在哪本书上看见的更复杂,记不太清楚了.

 shitalone 回复于:2004-09-10 16:50:50
呵呵,多谢。我看到了,原来是0
或者是(void *)0

 aero 回复于:2004-09-10 16:53:14
^_^,楼主的推论蛮有意思的,不过是错误的,让p = NULL只不过是一种习惯而已。你可以指向别的,但不能说NULL 可以是很多值哦。
下面是/usr/include/linux下的stddef.h文件中的NULL定义:
[code:1:7f6e418f04]
#undef NULL
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif
[/code:1:7f6e418f04]

 converse 回复于:2004-09-10 17:26:45
>>意思是让指针失效,那么这时候p的值是多少?
此时p的值是0,c语言规定,对0指针的访问无效

>>也就是说,只要p指向的地址程序不可访问,p就是NULL。 
>>所以NULL可以是很多不同的值。
p == NULL 那么p指向的地址程序不可访问,反之不然,因为不可访问的地址很多,NULL值就是零,没有别的值.

标准规定了NULL指针,它作为一个特殊的指针变量,表示不指向任何东西,要使一个指针变量为NULL,可以给它赋一个零值,为了测试一个指针变量是否为NULL,可以将它与零值比较.之所以选择零值是因为一个源代码约定,就机器内部而言,指针的实际值可能与此不同.在这种情况下,编译器负责零值和内部值之间的翻译转换.
                                               --上面这段话选自<<c和指针>>p96

 JohnBull 回复于:2004-09-11 11:53:06
NULL完全就是(void*)0,并不特殊.
C语言没有任何对于NULL的特殊语法和语义定义.
参见stddef.h:
[code:1:a18bc77e85]
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif
[/code:1:a18bc77e85]

 ljttlf 回复于:2004-09-11 12:12:43
>>NULL完全就是(void*)0,并不特殊.

有特殊,而且NULL ((void *)0)不是适合所有平台的写法,也就是说不是严谨的写法,几年以前我看了篇文章专门讨论NULL ((void *)0) 的问题,外国人写的,名字我忘了,当时 对c 的理解不到位没有看懂,只记得NULL ((void *)0)不严谨这句话。

我再翻翻书看是什么文章,找到的话我给大家贴出来。

 win_hate 回复于:2004-09-12 21:00:02
in c:

1、The NULL is nothing but (void *)0  because the standard say that is.

2、In different implementation, if p = (void *)0, p may be not all bits zero. It seem to be 

odd,  but look at this, if double x = 0, x may be not all bits zero.

 ljttlf 回复于:2004-09-12 21:52:10
Many programs and utilities were written using UNIX on VAX computers. On this
computer, the first byte of any program is 0. Many programs written on this
computer contain a bug—they use the null pointer as a string.
For example:
#ifndef NULL
#define NULL ((char *)0)
#endif NULL
char *string;
string = NULL;
printf("String is '%s'\n", string);
This code is actually an illegal use of string. Null pointers should never be
dereferenced. On the VAX, this error causes no problems. Because byte of the
program is 0, string points to a null string. This result is due to luck, not design.
On a VAX, the following result is produced:
String is ''
On a Celerity computer, the first byte of the program is a 'Q'. When this program is
run on a C1200, it produces:
String is 'Q'
On other computers, this type of code can generate unexpected results. Many of the
utilities ported from a VAX to a Celerity exhibited the 'Q' bug.
Many of the newer compilers will now check for NULL and print:
String is (null)
This message does not mean that printing NULL is not an error. It means that the
error is so common that the compiler makers decided to give the programmer a
safety .net. The idea is that when the error oclearcase/" target="_blank" >ccurs, the program prints something
reasonable instead of crashing.

 ljttlf 回复于:2004-09-12 21:53:25
移植性问题。我看得文章就是基于这个问题讨论的,但是我现在找不到原文了。
这个议题保留,我再看看找的到不。

 JohnBull 回复于:2004-09-13 14:28:31
1. It says that define NULL as (void*)0 is not a good idea on UNIX.
But the bad idea is the TRUTH.

2. I said "C语言没有任何对于NULL的特殊语法和语义定义" which means that NULL is not a keyword of C. Most C implementations define it as a macro not anything INSIDE C.

 win_hate 回复于:2004-09-13 16:36:19
[quote:1c8c9debf3="ISO/IEC 9899:1999(E)"]

7 library
7.17 Commnd definitions <stddef.h>

3 The macros are                                                          (pg 253)
NULL
which expands to an implementation-defined null pointer constant


6. Language
6.3.2.3 Pointers                                                             (pg 47)

3 An interger constant expression with the value 0, or such an expression cast to type void * is called a null pointer constant. If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guarranteed to compare unequal to a pointer to any object or function.
[/quote:1c8c9debf3]

 win_hate 回复于:2004-09-13 16:46:02
[quote:55b1deaa2b="ljttlf"]移植性问题。我看得文章就是基于这个问题讨论的,但是我现在找不到原文了。
这个议题保留,我再看看找的到不。[/quote:55b1deaa2b]

from Your post  :
[quote:55b1deaa2b]
Many programs written on this
computer contain a bug—they use the null pointer as a string.
.........
This code is actually an illegal use of string. Null pointers should never be dereferenced. 
[/quote:55b1deaa2b]

It says [color=red:55b1deaa2b]use the null pointer as a string[/color:55b1deaa2b] is a bug, but It dose not say NULL = (void *)0  is a bug. right? 

waitting for you post,  :D 
ps> the null pointer constant is  (void *)0 now, not (char *)0.

 思一克 回复于:2004-09-13 16:54:08
这本来不是什么问题值得讨论的。
如果要说,JohnBull 和 win_hate 都是对的。NULL其实不是C语言本身的内容,仅仅是人们编程是的习惯定义。在*.h文件中的#define出来的常量都不是语言本身的内容。

ljttlf  你这句话是什么意思?
On this computer, the first byte of any program is 0.

 ming_study 回复于:2004-09-13 17:23:43
在AIX Version 5中的定义是这样的

#ifndef NULL
#define NULL 0
#endif

 ming_study 回复于:2004-09-13 17:35:23
The symbolic constant NULL is often used in place of zero. as a mnemonic to indecate more clearly that this is a special value for a pointer.

 Blacklac 回复于:2004-09-13 18:07:53
is 0

 ljttlf 回复于:2004-09-13 20:57:51
>>but It dose not say NULL = (void *)0 is a bug. right

是的, 我只是说了 NULL = (void *)0 是个不严谨的定义,没有说是个BUG :) 

>>It says that define NULL as (void*)0 is not a good idea on UNIX.But the bad idea is the TRUTH.

确实,计算机科学本身就是折中的结果,比如速度与价格,才会发展出几级缓寸的问题,如果是理想的话,内存直接用寄存器做就是了.

文章是说的C1200上(void *)0就会有问题了,而且只是移植上的问题,相信我们没有几个人用过这个玩意.

ps:这篇文章是<实用c语言编程里面的>

 win_hate 回复于:2004-09-13 21:16:24
[quote:bcac8a5669="ljttlf"]>>but It dose not say NULL = (void *)0 is a bug. right

是的, 我只是说了 NULL = (void *)0 是个不严谨的定义,没有说是个BUG icon_smile.gif [/quote:bcac8a5669]

I study your  post carefully. I think the main idea is "use the null pointer as a string" is illegal, nothing elae. It dose not say (voidr *0) is good or bad.

[quote:bcac8a5669]
移植性问题。我看得文章就是基于这个问题讨论的,但是我现在找不到原文了。
这个议题保留,我再看看找的到不。
[/quote:bcac8a5669]

still, I waitting for this.  :D

 win_hate 回复于:2004-09-13 21:23:05
[quote:9e74610376="ming_study"]在AIX Version 5中的定义是这样的

#ifndef NULL
#define NULL 0
#endif[/quote:9e74610376]

What you say is c++ or c?

In my opinion, the implemention should obey the standard. If that C compiler on AIX define NULL  as 0, it's not ANSI conformance。 

make NULL a 0, will arose some subtile bug in some platform.

 ljttlf 回复于:2004-09-13 21:34:06
>>make NULL a 0, will arose some subtitle bug in some platform

可是C++他爸爸建议大家 make NULL a 0 ?为什么呢?

>>Many programs written on this 
computer contain a bug—they use the null pointer as a string

换句话说,如果(void*)0严谨的话,就不会出现问题啊:)而不管将null做为什么,不是吗?

就象一个数学的定义,严谨的方式是需要论述所有方面的。正因为硬件的多样性,才不可能保证所有事情的严谨性,不是C++委员会也是不段修改所有抹零两可的地方吗:) 

 ljttlf 回复于:2004-09-13 21:36:21
从头到尾,我也没有说过(void*)0的写法是错误的,我只是说是个不严谨的定义,不是吗,如果严谨,可能不会有上面那段话,至于我看的文章, 我再尽力找找, 我现在在上学,只有等国庆回家看看以前的书。

 win_hate 回复于:2004-09-13 21:41:56
[quote:521d19fd35="ljttlf"]>>make NULL a 0, will arose some subtitle bug in some platform

可是C++他爸爸建议大家 make NULL a 0 ?为什么呢?
[/quote:521d19fd35]

c++ and c, are different. I just talk about c, not c++. 

[quote:521d19fd35]
换句话说,如果(void*)0严谨的话,就不会出现问题啊:)而不管将null做为什么,不是吗?
[/quote:521d19fd35]

no, no, no, in any situation, "Null pointers should never be
dereferenced"

 win_hate 回复于:2004-09-14 00:44:22
to ljttlf:

你说的问题我查到了:

[quote:59bd833121="《c陷阱与缺陷》"]
7. 可移植性缺陷
7.6 内存位置 0

    null 指针并不指向任何对象。因此,除非是用于赋值或比较运算,出于其他任何目的使用null指针都是非法的。例如,如果p  或q 是一个null,那么strcmp (p,q)的值就是未定义的。

    在这种情况下究竟会得到什么结果呢?不同的编译器有不同的结果。某些c语实现对内存位置0强加了硬件级的读保护,在其上工作的程序如果错误使用了一个null指针,将立即终止执行。其他一些c语言实现对内存位置0只允许读,不允写。在这种情况下,一个null指针似乎指向的是某个字符串,但其内容通常不过是一堆“垃圾信息”。还有一些c语言实现对内存0位置既允许读,又允许写。在这种实现上面工作的程序如果错误使用了一个null指针,则很可能覆盖了操作系统的部分内容,造成彻底的灾难。

    [color=red:59bd833121]严格来说,这并非一个可移植性问题:在所有的c程序中,误用null指针的结果都是未定义的。[/color:59bd833121]然而,这样的程序有可能在某个c语言实现上“似乎”能正常工作,只有当该程序转移到另一台机器上运行时才会暴露出问题来。

    要检查出这类问题的最简单办法就是,把程序移到不允许读取内存位置0的机器上运行。下面的程序将揭示出某个c语言实现是任何处理内存地址0的:
[code:1:59bd833121]
#include <stdio.h>

main()
{
    char *p;
    p =  NULL;
    printf ("Location 0 contains %d\n", *p);
}
[/code:1:59bd833121]

    在禁止读取内存地址0的机器上,这个程序会执行失败。在其他机器上,这个程序会以10进制的格式打印出内存位置0中存储的字符内容。
[/quote:59bd833121]

从上面的内容可以看出,如果说有谁不严谨了,那必定是读取内存位置0的程序员,而不是c。c 的设计哲学之一是:程序员知道自己在干什么-----没有安全带。

 FH 回复于:2004-09-14 09:25:32
[quote:3c891bc4e8="win_hate"]从上面的内容可以看出,如果说有谁不严谨了,那必定是读取内存位置0的程序员,而不是c。c 的设计哲学之一是:程序员知道自己在干什么-----没有安全带。[/quote:3c891bc4e8]
赞同!

 ljttlf 回复于:2004-09-14 10:28:12
呵呵, 等我找到文章再说了:)
这个问题当然仁者见仁了,
你看的是《c陷阱与缺陷》,我找的是《实用C语言编程》,
我也只是说“在移植问题上的不严谨”,而我读的文章只是讨论如何找到一个定义,适合所有的硬件使他在诸如c2100上没有所谓的“Q”BUG问题。

>>c 的设计哲学之一是:程序员知道自己在干什么-----没有安全带

正因为如此,才会有如此多的缓冲区益处问题,你说对吗?
而我们现在讨论NULL的问题,也只是想找到一个方法避免误用null带来的潜在的危险(我看的文章也是基于这个论点,才的出的论点是NULL定义不严谨)。

就象一个物理定义一样,我们可以定义“时间是永恒,不变的”,这是真理,但是我们还可以定义“时间是可辩的,当速度接近光速时”。那你可以说上面那个真理是严谨的吗?当然可以为他加上时间限制。那么我们至少可以这样认为“((void*)0)”不是适合所有平台的定义。

呵呵,小弟最近在学自然辨证法, 发表的观点有点饶口哈。

我想我们现在没有必要为这个讨论,当大家在现实中遇到问题的时候再讨论不是更有意义,毕竟实践是检验真理的唯一标准。

 win_hate 回复于:2004-09-14 10:56:40
NULL 的出现估计是有部分程序员敲 ((void *)0) 敲烦了, 用 NULL 来代替。

>> 那么我们至少可以这样认为“((void*)0)”不是适合所有平台的定义。
((void *)0) 不必是零,其物理表示由具体的平台,实现决定-----如果在哪个平台上出了问题,那多半是实现的问题。我强调一点:按标准, ((void *)0) 是个抽象的东西,区别于其他指针,确保与任何地址相比较而不等。

>>就象一个物理定义一样,我们可以定义
物理的定义受物理世界的约束,但计算机的很多东西是人为制定,没有什么理由的。

>>正因为如此,才会有如此多的缓冲区益处问题
c 特别容易出这个问题, 它当然不是完美的。不过,dereferenced 一个零指针可是一个低级错误哦。

>>我想我们现在没有必要为这个讨论,当大家在现实中遇到问题的时候再讨论不是更有意义,毕竟实践是检验真理的唯一标准。

ok.

 lixuzhang 回复于:2004-09-14 14:14:16
我的理解:

出现NULL的原因或它的意义在于需要有一个表示指向并不存在的东西的指针。但这总得用某一个数来表示呀。所以具体实现就是选用零地址来代替的,因为不可能有变量或东西是放在零地址的。这相当于一个协定。如果我们当初协定(void*)1是代表并不存在的东西同样也可以呀。但只是用0来表示比用1表示更恰当而已。正如true和false是用1和0表示,还是用枚举来表示是一样的道理。关键在于,一旦确定,大家必须遵守相同的规则。

因为NULL代表是不存在的东西,所以求存放于NULL地址的数值也就没有意义了,具体到实现就是没有定义,没有人知道NULL地址会是什么东西。

我们用指针,当它不指向任何东西的时候,就得让它变成NULL。不然它就是一个“野”指针。我们使用指针时也同样得先判断它是不是NULL,必须不是NULL了才可以使用它,这个指针才有意义。

如果指针不应该指向任何东西,却没有设为NULL,也成为就是野指针时;调用者或使用者怎么知道你这个指针是不是有意义呢?所以使用者一旦对你这个“野”指针求值(*p)或赋值,就有可能出错——读错数据或写错地方。

 bitstream 回复于:2004-09-14 15:14:54
在C里面是 #define NULL 0
在C++里面是 #define NULL ((void *)0)

 ming_study 回复于:2004-09-14 20:26:01
我认为:
NULL是针对指针而言的,来表明这个指针不指向任何东西,
指针为空

 step_by_step 回复于:2004-09-22 15:08:12
这种问题有什么好吵的啊.

看标准就是了

 梦蓝 回复于:2004-09-22 17:59:11
p是一个指针,在系统中有4个字节(32位系统下)保存它的值,这个值是一个内存的地址,通过这个地址可以访问到目的数据。
当我们把它的值赋为NULL时,也就是它把指向一个不存在的内存地址,这样才能保证读取的不是脏数据。

 stkeke 回复于:2004-09-23 09:18:25
APUE Page 525
ANSI C并不保证整数0和浮点0相同,也不保证整数0与NULL指针相同。

 dingdangbear 回复于:2004-09-24 16:00:53
(void*) 0 是什么意思?
和0有什么区别?

 Joinhack 回复于:2004-09-24 19:07:05
NULL其实用字符来表示可以定义为'\0'

 独孤九筒 回复于:2004-10-03 00:08:54
是个宏

 xzh2002 回复于:2005-01-02 13:37:13
NULL就是0吧

 ificanfly 回复于:2005-01-02 15:42:32
不同的硬件NULL的值不一定一样啦。
CPU决定访问某个或者某段地址时发生中断或者以其他方式,通知OS。
若C标准化此值,那CPU设计者就得遵从。
你设计一个CPU不允许访问0x40000,否则发生异常,不行吗?没人阻拦你.

 twen345 回复于:2005-01-04 18:04:43
NULL是个好东东,你没有感觉到吗?

 eagerly1 回复于:2005-01-04 20:01:48
就将它理解为数学中的无穷大符号吧,仅仅表示一个方向。

 海狼unix 回复于:2005-04-10 12:12:30
[size=18:3157146dbd]我是C和C++的初学者,请教个师兄,

代码: 

#undef NULL 
#if defined(__cplusplus) 
#define NULL 0 
#else 
#define NULL ((void *)0) 
#endif  

的undef 是用来定义什么的,及 ifndef又是用来定义什么含义。[/size:3157146dbd]

 Alligator27 回复于:2005-04-10 22:44:29
[quote:da20bde0bc="dingdangbear"](void*) 0 是什么意思?
和0有什么区别?[/quote:da20bde0bc]

(void*) 是告诉compiler, 这里的0是指针, 而不是char, int, float等其它类型. 不同的类型会有不同的机器代表方式.

原文转自:http://www.ltesting.net

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)