C++ 如何定义地址为空的对象?

C++ 如何定义地址为空的对象?,c++,c,linker,weak-references,C++,C,Linker,Weak References,我想知道如何在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

我想知道如何在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,但一切都可以 好的

编辑:这样做的原因是,条形图并不总是空的。以下是一个更相关的示例:

// 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对象。

我肯定遗漏了一些东西,但是void*bar=NULL有什么不起作用呢?

您正在尝试创建一个地址为零的符号。最后一个示例可能是在C编译器/语言中实现这一点的唯一方法

最有可能解决问题的方法是查看链接器程序的输入文件。大多数链接器允许您将标签foo定义为零

在unix ld脚本中,这只是:
foo=0

我认为没有标准的方法来定义地址为0的内容。或者更确切地说,它是未定义的,因为这样就可以取消对0的引用,0是未定义的还是特定于平台的?在标准中


你想做什么?

好的,这一定是个问题,但是你想要一个值为0的指针吗

怎么样

void * bar = (void*) 0;
你不必这么胡闹:指针只是一个数字,编译器将它与一个类型相关联;如果希望数字为0,请指定0

哦,回答另一个问题,这不是语言与它有任何关系,只是你不一定知道位置0中有什么。我们在使用BSD代码时遇到了很多麻烦,因为在早期的BSD Unice中,*0==0是可靠的。所以人们会写这样的东西

while(*c) doSomething();

因为当他们取消引用字符串末尾的0x00时,它会查看值为0的位置0。不幸的是,在其他平台上不一定如此。

在您的类中,您可以覆盖&operator:

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)

我真的怀疑在标准C99中是否有办法做到这一点。在标准C++中,如果创建对象,则很难引用它,因为定义空指针常量是不定义的,指针常数中的常数积分0是空指针常数。是的,你可以试试INTI;i=0;foo*p=重新解释卡斯蒂;p->doSomething;但该标准没有具体说明reinterpret_cast的作用,只是以一种模糊且依赖于实现的方式


所以,我的下一个问题是,你们在这里想要实现什么。如果你试图以奇怪而有趣的方式扭曲语言,那么根据标准,它不会以这种方式扭曲语言。如果你有合法的使用,它会是什么?

如果你使用C++,你可以使用引用:

int *foo = 0;
int &bar = *foo;
int *foo_addr = &bar; // gives NULL

您需要的是一个包含空地址的引用。这是一种非常糟糕的做法,但这里有:

#ifdef NON_NULL
Foo realFoo;
Foo &foo = realFoo;
#else
Foo &foo = *(Foo*)NULL;
#endif

请不要这样做。自动ptr可能是一个更好的选择。

我想你很接近了,只需一步指针间接指向

根据您的代码示例判断,不需要获取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


唯一需要注意的是,您现在需要使用freebar。

好吧,我们有:

C++允许重载运算符,并且有模板来为您工作,但不允许取消空指针。 C允许取消对空指针的引用,只要随后获取地址即可。它还允许将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; 

现在,您可以使用&foo并将其分配给指向某个对象类型的指针

听着,我很抱歉,但你把这件事弄得太难也太复杂了

如果你想用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 */
您不需要搞乱加载程序,也不需要也不应该使用任何快速宏,除非您确实有充分的理由这样做。Th
is是所有标准C.

struct oops{struct omg{template operator T*{return 0;}}};omg operator&{return omg;}}}woops;int*p=&woops;assertp==空污秽警告!!嘿,为什么上面的答案不是我会投票的。但不确定是哪个方向。我得问问。。。为什么你需要首先做这个?为什么不是原来的海报需要C99解决方案,不是C++解决方案。我没有C标准,但是在C++的引用中,空指针是不定义的,指针上下文中的常数0是空指针。这就是他要求的。@Thornley,问题是任何有效的东西都可以。同样,这个问题用C++来标注,如果他还想得到第二个,他可以使用TEXBoo:addressof@litb,我已经用它更新了我的答案,并且是一个非boost方法。谢谢。实际上,我们缺少的是OP真正想要完成的任务的线索。请注意,正式取消对空指针的引用是未定义的。不过,标准中对此存在一些不一致之处。上面写的是UB,但有一处写的不是这样:。可能没有编译器会在你的代码上崩溃。这是未定义的行为,根据C++标准。foo正在取消对空指针的引用。这可以做任何事情,包括在最坏的情况下才露面。呃,没关系。我误读了你的陈述。不过,我确实收到了GCC的警告:取消引用“void*”指针。不过,有了这种黑客行为,我确信它可以被安全地忽略,即使我自己也会寻找更好的解决方案。是的,整个东西都是黑客行为,但我相信完全是标准的。comeau似乎也支持这一观点。至少从它没有警告:在C,它是有效的去引用空隙* -在C++中它是无效的。
if(!func) 
    (*func)();
else
    /* function not defined */