dim*_*mba 2 c++ linux 64-bit null gcc
我正在使用gcc 4.1.2在RHEL 5.1 64位平台上运行.
我有一个实用功能:
void str_concat(char *buff, int buffSize, ...);
Run Code Online (Sandbox Code Playgroud)
concats 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
Run Code Online (Sandbox Code Playgroud)
第二个是/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
Run Code Online (Sandbox Code Playgroud)
当然我需要第二个,因为它将NULL定义为__null(8个字节),而第一个定义为整数0(4个字节).
如何防止/usr/include/linux/stddef.h被正确包含?
UPD:
编译行非常简单:
g ++ -Wall -fmessage-length = 0 -g -pthread
很多人建议传递(void*)0.这当然会起作用.功能在很多地方使用的问题,我的意思是很多地方.我想找到能给我C++标准所承诺的解决方案 - 8字节大小的NULL.
AnT*_*AnT 12
在这种情况下,没有"NULL定义问题".您NULL在代码中尝试使用的方式存在问题.
NULL无法在C/C++中可移植地传递给可变函数.你必须在传递之前显式地转换它,即在你的情况下你必须(const char*) NULL作为参数列表的终止符传递.
您的问题被标记为C++.在任何情况下,无论大小如何,在C++中NULL总是被定义为整数常量.在C++中定义NULL为指针是非法的.由于你的函数需要一个指针(const char *),NULL因此在C++代码中没有任何定义可用于它.
对于更干净的代码,您可以定义自己的常量,例如
const char* const STR_TERM = NULL;
Run Code Online (Sandbox Code Playgroud)
并在调用函数时使用它.但是你永远无法仅仅NULL为了那个目的而有意义地使用它.每当普通NULL作为可变参数传递时,它都是一个必须修复的明显的可移植性错误.
补充:您的更新声称"C++标准承诺NULL8字节大小"(在我认为的64位平台上).这没有任何意义.C++标准不承诺任何类似的东西NULL.
NULL旨在用作右值.它没有特定的大小,并且没有有效使用NULL它的实际大小甚至远程重要的地方.
引自ISO/IEC 14882:1998,第18.1节"类型",第4段:
宏NULL是本国际标准(4.10)中实现定义的C++空指针常量.180)
180)可能的定义包括0和0L,但不包括(void*)0.
一个解决方案 - 可能是最好的,但肯定非常可靠 - 是将一个显式的null char指针传递给你的函数调用:
str_concat(buffer, sizeof(buffer), "str1", "str2", ..., (char *)0);
Run Code Online (Sandbox Code Playgroud)
要么:
str_concat(buffer, sizeof(buffer), "str1", "str2", ..., (char *)NULL);
Run Code Online (Sandbox Code Playgroud)
例如,这是execl()POSIX系统中函数的标准推荐实践,并且出于完全相同的原因 - 可变长度参数列表的尾随参数受常规促销(char或short to int; float to double)的约束,但是否则不能是类型安全的.
这也是C++从业者通常避免使用可变长度参数列表的原因 ; 它们不是类型安全的.
| 归档时间: |
|
| 查看次数: |
5028 次 |
| 最近记录: |