C++ pointer arithmetic weirdness

痴心易碎 提交于 2019-12-02 13:52:17

问题


I found my bug (after a few hours) and isolated it in the following program. The problem is with the way in which the pst2 variable's value is calculated when using pointers to a struct. When using pointers to char, all works fine. Why is this?
(Using gcc/g++ version: (Debian 4.4.5-8) 4.4.5)
(For those who are wondering: I'm accessing a file-buffer containing data-groupings at regular offsets.)

#include <iostream>
#include "testpa.h"

#pragma pack(push)
#pragma pack(1)
//---------------------------
struct st_one
{
    int i;
    char c;
};
//---------------------------
struct st_two
{
    long l;
    int i;
};
#pragma pack(pop)

//===========================
int main()
{
    int n=1024, np1=sizeof(st_one); //, np2=sizeof(st_two);
    st_one *pst1, *pst1a;
    st_two *pst2, *pst2a;
    char *pc1, *pc2, *pc1a, *pc2a, *pb;

    pb = new char[n];

    pst1 = (st_one*)(pb);
    pst2 = (st_two*)(pst1 + np1); //using pst1
    pc1 = (char*)(pb);
    pc2 = (char*)(pc1 + np1); //using pc1

    pst1a = (st_one*)(pb);
    pst2a = (st_two*)(pb + np1); //using pb
    pc1a = (char*)(pb);
    pc2a = (char*)(pb + np1); //using pb

    std::cout << "\npb = " << (long)pb;
    std::cout << "\n-----";
    std::cout << "\npst1 = " << (long)pst1 << "\tpst2 = " << (long)pst2;
    std::cout << "\npc1  = " << (long)pc1 << "\tpc2  = " << (long)pc2;
    std::cout << "\n-----";
    std::cout << "\npst1a = " << (long)pst1a << "\tpst2a = " << (long)pst2a;
    std::cout << "\npc1a  = " << (long)pc1a << "\tpc2a  = " << (long)pc2a;
    std::cout << "\n-----\n";

    return 0;
}

Output:

pb = 19546128

pst1 = 19546128         pst2 = 19546153  <--- WRONG!
pc1  = 19546128         pc2  = 19546133

pst1a = 19546128        pst2a = 19546133
pc1a  = 19546128        pc2a  = 19546133

回答1:


That looks fine to me. The line:

 (pst1 + np1)

adds np1 instances of st_one to what pst1 points at, which means that pst1s value is incremented by np1 * sizeof (st_one) bytes, which is 25 (sizeof = 5), which corresponds to the values you've outputted. Instead of the above, I think you wanted:

 (pst1 + 1)

The pc1 value works because that is a char pointer, so the line:

(pc1 + np1)

adds np1 * sizeof (char) bytes to pc1, which is 5 bytes.

Incrementing a pointer makes the pointer point to the next element in memory, not the next byte.




回答2:


You shouldn't add sizeof(x), because that is done automatically. When you increment a pointer, like ++p, the address is incremented by the size of the object, so that it points to the next one.

Adding 1 to a pointer is the same as ++p. Adding sizeof(x) scales the increment twice.

Your calculations work fine for char, because sizeof(char) is 1.




回答3:


C++ automatically multiplies the integer you're adding by the size of the element the pointer points to. It assumes you want to advance the pointer by whole elements, not bytes.




回答4:


Pointer arithmetic in C and C++ is done times the sizeof the pointed to type of the pointer. That is, int *abc = /* ... */; int *def = abc + 1 results in def having a result an int ahead of abc, not a char.

As for your casting of the pointers into longs, that's implementation defined behavior, so you might get strange results on different machines from doing that.

(For that matter, so is your casting between pointer types. C++ says that's implementation defined too)




回答5:


It looks like you got everything wrong. For example, for get pst2 from pst1, you have to increment it by one, as pointer pst1 is of type st_one *, so you have to write like this:

pst2 = (st_two*)(pst1 + 1);

.. but you have:

pst2 = (st_two*)(pst1 + np1);

... where np1 is a sizeof of st_one, so it will skip as many st_one structures as that structure has bytes...

Read some docs on pointer arithmetic, like this one.



来源:https://stackoverflow.com/questions/6847538/c-pointer-arithmetic-weirdness

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!