1

我发现了我的错误(几个小时后)并将其隔离在以下程序中。问题在于使用指向结构的指针时计算 pst2 变量值的方式。使用指向 char 的指针时,一切正常。为什么是这样?
(使用 gcc/g++ 版本:(Debian 4.4.5-8)4.4.5)
(对于那些想知道的人:我正在访问一个包含常规偏移量的数据分组的文件缓冲区。)

#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;
}

输出:

pb = 19546128

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

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

5 回答 5

8

这对我来说看起来不错。该行:

 (pst1 + np1)

np1实例添加st_one到什么pst1点,这意味着pst1s 值以np1 * sizeof (st_one)字节递增,即 25 (sizeof = 5),这对应于您输出的值。而不是上面的,我认为你想要:

 (pst1 + 1)

pc1值有效,因为那是一个char指针,所以该行:

(pc1 + np1)

np1 * sizeof (char)字节添加到pc1,即 5 个字节。

递增指针使指针指向内存中的下一个元素,而不是下一个字节。

于 2011-07-27T16:06:08.963 回答
3

您不应该添加sizeof(x),因为这是自动完成的。当你增加一个指针时,比如 ++p,地址会增加对象的大小,所以它指向下一个。

给指针加 1 与 ++p 相同。添加sizeof(x)缩放增量两次。

您的计算适用于 char,因为 sizeof(char) 为 1。

于 2011-07-27T16:07:45.080 回答
2

C++ 自动将您添加的整数乘以指针指向的元素的大小。它假设您想要将指针推进整个元素,而不是字节。

于 2011-07-27T16:08:47.237 回答
2

C 和 C++ 中的指针算术运算是sizeof指针所指向类型的倍数。也就是说,int *abc = /* ... */; int *def = abc + 1结果是defaint领先于abc,而不是 a char

至于您将指针转换为longs,这是实现定义的行为,因此您可能会在不同的机器上得到奇怪的结果。

(就此而言,指针类型之间的转换也是如此。C++ 说这也是定义的实现)

于 2011-07-27T16:08:56.443 回答
1

看起来你搞错了。例如,为了从 pst1 中获取 pst2,你必须将它加一,因为指针pst1的类型是st_one *,所以你必须这样写:

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

.. 但是你有:

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

...其中 np1 是sizeofof st_one,因此它将跳过st_one该结构具有字节数的结构...

阅读一些关于指针算法的文档,比如这个

于 2011-07-27T16:08:43.363 回答