我发现了我的错误(几个小时后)并在以下程序中将其隔离。问题在于使用指向结构的指针时计算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
答案 0 :(得分:8)
这对我来说很好看。这一行:
(pst1 + np1)
将np1
st_one
个实例添加到pst1
所指的位置,这意味着pst1
的值增加np1 * sizeof (st_one)
个字节,即25( sizeof = 5),它对应于您输出的值。而不是上述,我想你想要:
(pst1 + 1)
pc1
值有效,因为它是char
指针,所以行:
(pc1 + np1)
将np1 * sizeof (char)
个字节添加到pc1
,这是5个字节。
递增指针使指针指向内存中的下一个元素,而不是下一个字节。
答案 1 :(得分:3)
您不应添加sizeof(x)
,因为这是自动完成的。当您递增指针(如++ p)时,地址会增加对象的大小,以便指向下一个。
向指针添加1与++ p相同。添加sizeof(x)
会对增量进行两次缩放。
您的计算适用于char,因为sizeof(char)为1。
答案 2 :(得分:2)
C ++会自动将您添加的整数乘以指针所指向的元素的大小。它假设您希望通过整个元素而不是字节来推进指针。
答案 3 :(得分:2)
C和C ++中的指针运算是指针指向类型sizeof
的完成时间。也就是说,int *abc = /* ... */; int *def = abc + 1
会导致def
在int
之前的结果为abc
,而不是char
。
至于你将指针转换成long
s,这是实现定义的行为,所以你可能会在不同的机器上得到奇怪的结果。
(就此而言,您在指针类型之间的转换也是如此.C ++也说明了实现的定义)
答案 4 :(得分:1)
看起来你的一切都错了。例如,对于从pst1获取pst2,您必须将其递增1,因为指针pst1
的类型为st_one *
,因此您必须这样写:
pst2 = (st_two*)(pst1 + 1);
..但你有:
pst2 = (st_two*)(pst1 + np1);
...其中np1是sizeof
的{{1}},因此它将跳过尽可能多的st_one
结构,因为该结构具有字节...
阅读有关指针算术的一些文档,例如this one。