C ++中的显式地址操作

时间:2009-11-05 16:50:23

标签: c++ pointers

请查看以下func及其输出

void main()
{
    Distance d1;
    d1.setFeet(256);
    d1.setInches(2.2);

    char *p=(char *)&d1;
    *p=1;

    cout<< d1.getFeet()<< " "<< d1.getInches()<< endl;
}

班级Distance通过setFeetsetInches获取其值,分别传递intfloat个参数。它会通过getFeetgetInches方法显示值。

但是,此函数的输出为257 2.2。为什么我会得到这些值?

7 个答案:

答案 0 :(得分:14)

这是一个非常糟糕的主意:

char *p=(char *)&d1;
*p=1;

您的代码永远不应该对类的内部结构做出假设。例如,如果您的类具有任何虚函数,那么当您调用它们时,该代码会导致崩溃。

我只能断定你的Distance课程如下:

class Distance {
    short feet;
    float inches;
public:
    void setFeet(...
};

当你setFeet(256)时,它将高字节(MSB)设置为1(256 = 1 * 2 ^ 8),将低字节(LSB)设置为0.当你赋值1时对于char对象地址的Distance,你强制代表英尺的short的第一个字节为1.在小端机器上,低字节位于较低的地址,因此最终得到short,两个字节都设置为1,即1 * 2^8 + 1 = 257

在big-endian机器上,你仍然会得到值256,但这纯属巧合,因为你恰好在已经为1的字节上强制值为1。

但是,因为您正在使用未定义的行为,取决于编译器和编译选项,您最终可能会得到任何结果。 comp.lang.c中一个着名的表达式是,这种未定义的行为可能“导致恶魔飞出你的鼻子”。

答案 1 :(得分:2)

你是通过'p'指针非法重放内存。

该程序的输出未定义;因为您通过另一种类型的指针直接操作对象拥有的内存,而不考虑底层类型。

您的代码有点像这样:

struct Dist
{
    int     x;
    float   y;
};

union Plop
{
    Dist    s;  // Your class
    char    p;  // The type you are pretending to use via 'p'
};

int main()
{
    Plop    p;

    p.s.x   = 5;    // Set up the Dist structure.
    p.s.y   = 2.3;

    p.p     = 1;    // The value of s is now undefined.
                    // As you have scribbled over the memory used by s.
}

答案 2 :(得分:1)

基于给定代码的行为将是非常不可预测的。设置d1数据的第一个字节可能会破坏vptr,编译器特定的内存,浮点值的符号/指数,或整数的LSB或MSB,这些都取决于Distance的定义。

答案 3 :(得分:0)

我假设你认为做* p = 1会在Distance对象中设置一个内部数据成员(可能是'feet')。它可能有用,但是(afaik)你不能保证脚部件位于对象的第一个地址,具有正确的大小(除非它的类型也是char)或它是否正确对齐。

如果你想这样做,为什么不将'脚'成员公开并做:

d1.feet = 1;

答案 4 :(得分:0)

另外,对程序发表评论:不要使用void main()。它不是标准的,它不会给您带来任何好处。在询问C或C ++问题时,它会让人们不再认真对待,并且可能导致程序无法编译或无法正常工作。

C ++标准在3.6.1第2段中说main()总是返回int,尽管实现可能会提供不同参数的变体。

这是打破习惯的好时机。如果你从使用void main()的书中学习,那么这本书是不可靠的。如果仅供参考,请参阅另一本书。

答案 5 :(得分:0)

看起来你是编程新手,可以使用一些基本概念的帮助。

你正在寻找它,这很好,但是可能不是正确的地方。

祝你好运。

答案 6 :(得分:0)

类的定义是

class Distance{
    int feet;
    float inches;
    public:
//...functions
};

现在int脚将是00000001 00000000(2字节),其中零将占用Little Endian中的较低地址,因此char * p将为00000000 ..当你使* p = 1时,低位字节变为00000001所以int变量现在是00000001 00000001,正好是257!