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