c++指针运算的怪异

C++ pointer arithmetic weirdness

本文关键字:运算 指针 c++      更新时间:2023-10-16

我找到了我的bug(几个小时后),并在下面的程序中隔离了它。问题在于使用指向结构体的指针时计算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

我看还行。线:

 (pst1 + np1)

st_onenp1个实例加到pst1所指向的位置,这意味着pst1的值增加了np1 * sizeof (st_one)个字节,即25 (sizeof = 5),这与您输出的值相对应。我想你应该这样做:

 (pst1 + 1)

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

(pc1 + np1)

pc1的基础上增加np1 * sizeof (char)字节,即增加5字节。

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

您不应该添加sizeof(x),因为这是自动完成的。当对指针进行自增操作(如++p)时,地址会随着对象的大小递增,从而指向下一个对象。

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

你的计算对char很好,因为sizeof(char)是1。

c++会自动将要添加的整数乘以指针所指向的元素的大小。

C和c++中的指针运算是乘以指针的指向类型sizeof。也就是说,int *abc = /* ... */; int *def = abc + 1导致defabc之前有int的结果,而不是char

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

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

看来你把一切都搞错了。例如,要从pst1获取pst2,您必须将其增加1,因为指针pst1的类型是st_one *,因此您必须这样写:

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

. .但是你有:

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

…其中np1是st_onesizeof,所以它会跳过多少st_one结构,因为该结构有多少字节…

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