开发者

Explicit Address Manipulation in C++

Please check out the following func and its output

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

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

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

The class Distance gets its values thru setFeet and setInch开发者_如何学运维es, passing int and float arguments respectively. It displays the values through through the getFeet and getInches methods.

However, the output of this function is 257 2.2. Why am I getting these values?


This is a really bad idea:

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

Your code should never make assumptions about the internal structure of the class. If your class had any virtual functions, for example, that code would cause a crash when you called them.

I can only conclude that your Distance class looks like this:

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

When you setFeet(256), it sets the high byte (MSB) to 1 (256 = 1 * 2^8) and the low byte (LSB) to 0. When you assign the value 1 to the char at the address of the Distance object, you're forcing the first byte of the short representing feet to 1. On a little-endian machine, the low byte is at the lower address, so you end up with a short with both bytes set to 1, which is 1 * 2^8 + 1 = 257.

On a big-endian machine, you would still have the value 256, but it would be purely coincidental because you happen to be forcing a value of 1 on a byte that would already be 1.

However, because you're using undefined behavior, depending on the compiler and the compile options, you might end up with literally anything. A famous expression from comp.lang.c is that such undefined behavior could "cause demons to fly out of your nose".


You are illegally munging memory via the 'p' pointer.

The output of the program is undefined; as you are directly manipulating memory that is owned by an object through a pointer of another type without regard to the underlying types.

Your code is somewhat like this:

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.
}


The behaviour based on the code given is going to be very unpredictable. Setting the first byte of d1's data could potentially clobber a vptr, compiler-specific memory, the sign/exponent of a floating point value, or LSB or MSB of an integer, all depending on the definition of Distance.


I assume you think doing *p = 1 will set one of the internal data members (presumably 'feet') in the Distance object. It may work, but (afaik) you've got no guarantees that the feet member is at the first address of the object, is of the correct size (unless its type is also char) or that it's aligned correctly.

If you want to do that why not make the 'feet' member public and do:

d1.feet = 1;


Another thing, to comment on the program: don't use void main(). It isn't standard, and it offers you no benefits. It will make people not take you as seriously when asking C or C++ questions, and could cause programs to not compile, or not work properly.

The C++ Standard, in 3.6.1 paragraph 2, says that main() always returns int, although the implementation may offer variations with different arguments.

This would be a good time to break the habit. If you're learning from a book that uses void main(), the book is unreliable. See about getting another book, if only for reference.


It looks like you are new to programming and could use some help with basic concepts.

It's good that you are looking for that, but SO may not be the right place to get it.

Good luck.


The Definition of class is

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

now the int feet would be 00000001 00000000 (2 bytes) where the zeros would occupy lower address in Little Endian so the char *p will be 00000000.. when u make *p=1, the lower byte becomes 00000001 so the int variable now is 00000001 00000001 which is exactly 257!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜