我想知道如何在C中定义一个对象,其引用将为null?
// definition of foo
...
void * bar = &foo; // bar must be null
我有一些方法可以做到这一点,但没有一种方法符合我的需要。
__attribute__((weak)) extern int foo; //not working with cygwin/gcc 3.4
__attribute__((at(0))) int foo; //only with rvds
#define foo (*(int*) 0) //cannot be embedded in a macro
实际上,我更喜欢符合标准的解决方案(c99),但任何有效的方法 没关系。
编辑:执行此操作的原因是bar不会始终为null。这是一个更相关的例子:
// macro that will define foo to a real object or to *null
DECL(foo);
int * bar = &foo;
if(bar) {
// we can call func
func(bar);
} else {
// bar undefined
exit(-1);
}
当然这仍然不是很相关,因为我可以在我的条件下使用#if。该项目实际上涉及大型结构,大量文件,一些编译器,一些cpu目标,以及许多程序员,他们生成的错误概率指数与他们使用的语法的复杂性呈指数关系。这就是为什么我想要一个简单的宏来声明我的foo对象。
答案 0 :(得分:16)
我必须遗漏一些东西,但是对于void * bar = NULL
什么不起作用?
答案 1 :(得分:2)
在您的课程中,您可以覆盖&
运算符:
class MyClass
{
public:
MyClass() :
m_isNull(true)
{
}
MyClass(int value) :
m_isNull(),
m_value(value)
{
}
int value() const
{
/* If null, throw exception, maybe? */
return m_value;
}
bool isNull() const
{
return m_isNull;
}
/////////////////////////
// Here's the "magic". //
/////////////////////////
MyClass *operator&()
{
if(m_isNull)
return 0;
return this;
}
private:
bool m_isNull;
int m_value;
};
这会产生MyClass
的用户可能不会期望的行为。我不确定这个“功能”在哪里需要甚至想要。
如果您想获取MyClass
个实例的真实地址,可以使用boost
(根据此答案的评论中的建议):
MyClass foo;
MyClass *fooptr = &foo; // fooptr == NULL
fooptr = boost::addressof(foo); // fooptr = &foo (the real address)
或者您可以使用强制转换,因此不会调用MyClass::operator&()
:
struct DummyStruct {};
MyClass foo;
MyClass *fooptr = &foo; // fooptr == NULL
fooptr = &reinterpret_cast<DummyStruct>(foo); // fooptr = &foo (the real address)
答案 2 :(得分:2)
您想要的是一个包含空地址的引用。这是非常糟糕的做法,但这里有:
#ifdef NON_NULL
Foo realFoo;
Foo &foo = realFoo;
#else
Foo &foo = *(Foo*)NULL;
#endif
请不要这样做。 auto_ptr可能是更好的选择。
答案 3 :(得分:1)
您正在尝试创建地址为零的符号。您的最后一个示例可能是在C编译器/语言中执行此操作的唯一方法。
最有可能解决问题的方法是查看链接器程序的输入文件。大多数链接器允许您将标签foo定义为零。
在unix ld脚本中,这只是: foo = 0;
答案 4 :(得分:0)
我认为没有一种标准的方法可以定义地址为0的东西。或者更确切地说,它是未定义的,因为它可以在标准中取消引用0,这是未定义的(或者它是特定于平台的?)
你想做什么?
答案 5 :(得分:0)
好的,这是问题,但你想要一个值为0的指针?
怎么样
void * bar = (void*) 0;
你不必做所有那些搞乱:指针只是编译器与一个类型相关联的数字;如果您希望数字为0,请指定0。
哦,回答另一个问题,并不是语言与它有任何关系,只是你不一定知道位置0的内容。我们在当天遇到了很多BSD代码的麻烦,因为在早期的BSD unices中,* 0 == 0是可靠的。所以人们会写像
这样的东西while(*c) doSomething();
因为当他们在字符串末尾取消引用0x00时,它会查看LOCATION 0,其值为0.不幸的是,在其他平台上并不一定如此。
答案 6 :(得分:0)
我真的怀疑在标准C99中有办法做到这一点。在标准C ++中,如果你可以创建它,你将很难引用该对象,因为取消引用空指针常量是未定义的,并且指针常量中的常量整数0是空指针常量。 (是的,您可以尝试int i; i = 0; foo * p = reinterpret_cast<foo *>i; p->doSomething();
,但标准没有指定reinterpret_cast&lt;&gt;做什么,除了模糊和依赖于实现的方式。)
所以,我的下一个问题是你在这里想要完成的事情。如果你试图以奇怪而有趣的方式扭曲语言,那么根据标准,它不会扭曲。如果你有合法的用途,它会是什么?
答案 7 :(得分:0)
我认为你很接近,只是指针间接的一步。
根据您的代码示例判断,无需使用foo
的地址。
您可以通过创建分配和实例化bar
的函数来完成您想要的任务。
所以而不是:
DECL(foo);
int * bar = &foo;
你可以:
#define FOO_IS_NULL 0
int * getFoo()
{
if( FOO_IS_NULL )
{
return 0;
}
int *tmp = malloc(sizeof(int));
*tmp = 1234;
return tmp;
}
int * bar = getFoo();
请注意,这完全消除了变量foo
。
唯一需要注意的是,您现在需要free(bar)
。
答案 8 :(得分:0)
嗯,这就是我们所拥有的:
operator&
并具有模板来为您完成工作,但不允许解除引用空指针。 void*
分配给任何指向对象的指针。 嗯,那是理想的。首先,C部分,这很容易。我不明白你的观点,你不能把它嵌入到宏中。它对我来说很好。
#define foo_ (*(void*) 0)
现在,C ++部分。把东西放在nullp.hpp:
struct nullp {
struct proxy {
template<typename T> operator T*() {
return 0;
}
};
proxy operator&() {
return omg();
}
} foo;
现在,我们需要做的就是把事情粘在一起:
#ifdef __cplusplus
#include "nullp.hpp"
#else
#define foo (*(void*) 0)
#endif
现在,您可以使用&foo
并将其指定给指向某个对象类型的指针。
答案 9 :(得分:0)
看,我很抱歉,但你这太难了太复杂了。
如果你想在C中调用这个东西,你需要一个指向函数的指针。所以,例如,你有
/* ptr to 0-ary function returning int */
int (*func)() = NULL ; /* That's all you need. */
// elsewhere ....
int myfunc() { /* do a good thing */ }
func = myfunc ; /* function name *is* its address */
现在,在以后的代码中你可以做
if(!func)
(*func)();
else
/* function not defined */
你不需要搞乱加载器,你不需要---也不应该使用---任何zippy宏,除非你真的 真的有充分的理由这样做。这都是标准C。
答案 10 :(得分:-1)
如果您使用的是C ++,则可以使用引用:
int *foo = 0;
int &bar = *foo;
int *foo_addr = &bar; // gives NULL