64位系统上的NULL定义问题
我使用gcc 4.1.2在RHEL 5.1 64位平台上运行。
我有一个实用功能:
void str_concat(char *buff, int buffSize, ...);
其中concat char *在可变参数列表(...)中传递,而最后一个参数应该为NULL,以指定参数的结尾。 在64位系统上,NULL是8个字节。
现在解决问题。 我的应用程序包括直接/间接2 stddef.h文件。
第一个是/usr/include/linux/stddef.h ,它定义了NULL,如下所示:
#undef NULL
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif
第二个是/usr/lib/gcc/x86_64-redhat-linux/4.1.2/include/stddef.h
#if defined (_STDDEF_H) || defined (__need_NULL)
#undef NULL /* in case <stdio.h> has defined it. */
#ifdef __GNUG__
#define NULL __null
#else /* G++ */
#ifndef __cplusplus
#define NULL ((void *)0)
#else /* C++ */
#define NULL 0
#endif /* C++ */
#endif /* G++ */
#endif /* NULL not defined and <stddef.h> or need NULL. */
#undef __need_NULL
当然,我需要第二个,因为它将NULL定义为__null(8字节),而第一个定义为整数0(4字节)。
我如何防止/usr/include/linux/stddef.h被不正确地包含在内?
UPD:
编译线非常简单:
g ++ -Wall -fmessage-length = 0 -g -pthread
你们许多人建议通过(void *)0。 这当然会起作用。 这个函数在很多地方使用的问题,我的意思是很多地方。 我想找到解决方案,将给我什么C ++标准承诺 - 8字节大小的NULL。
在这种情况下没有“NULL定义问题”。 在您的代码中如何尝试使用NULL
存在问题。
NULL
不能自己传递给C / C ++中的可变参数函数。 你必须在传递之前明确地转换它,也就是说,你必须传递(const char*) NULL
作为参数列表的终止符。
你的问题被标记为C ++。 在任何情况下,无论大小如何,在C ++中, NULL
总是被定义为一个整数常量。 在C ++中将NULL
定义为指针是非法的。 由于你的函数需要一个指针( const char *
),因此在C ++代码中不会有NULL
定义。
为了更清晰的代码,你可以定义你自己的常量,比如
const char* const STR_TERM = NULL;
并用它来调用你的函数。 但是你永远不能仅仅为了这个目的而使用NULL
。 每当一个普通的NULL
被作为可变参数传递时,它就是一个公然的可移植性bug,必须修复。
补充说:你的更新声明“C ++标准承诺8字节大小的NULL
”(在我假设的64位平台上)。 这只是没有任何意义。 C ++标准不承诺任何类似NULL
东西。
NULL
旨在用作右值。 它没有特定的大小,并且在实际大小甚至可能很重要的情况下,没有NULL
的有效使用。
引用ISO / IEC 14882:1998第18.1节“类型”第4段:
宏NULL是本国际标准(4.10).180中定义的一个实现定义的C ++空指针常量)
180)可能的定义包括0和0L,但不包括(void *)0。
一种解决方案 - 可能甚至是最好的,但肯定非常可靠 - 是将明确的空字符指针传递给你的函数调用:
str_concat(buffer, sizeof(buffer), "str1", "str2", ..., (char *)0);
要么:
str_concat(buffer, sizeof(buffer), "str1", "str2", ..., (char *)NULL);
这是标准的推荐实践execl()
在POSIX系统的功能,例如,和用于精确地相同的原因-一个可变长度的参数列表的尾部参数是受到通常的优惠(char或短为int;浮动加倍),但不能以其他方式安全。
这也是C ++从业者通常避免可变长度参数列表的原因; 他们不安全。
删除__GNUG__
大小写,并反转第二个文件中的ifdef / endif,BOTH文件可以:
#undef NULL
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif
也就是说,它们将NULL定义为((void *)0)用于C编译,0定义为C ++。
所以简单的答案是“不要编译为C ++”。
你真正的问题是你希望在你的可变参数列表中使用NULL,并结合你的编译器的不可预知的参数大小。 你可能会尝试写“(void *)0”而不是NULL来终止你的列表,并强制编译器传递一个8字节的指针而不是4字节的int。
链接地址: http://www.djcxy.com/p/49179.html上一篇: NULL definition problem on 64 bit system
下一篇: How to send Keyboard events (e.g. Backspace, Delete) in Safari from javascript