C++指针算术怪异
我发现了我的错误(几个小时后)并将其隔离在以下程序中。问题在于使用指向结构的指针时计算 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
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这对我来说看起来不错。该行:
将
st_one
的np1
实例添加到pst1
指向的位置,这意味着pst1
的值递增bynp1 * sizeof (st_one)
字节,即 25 (sizeof = 5),对应于您输出的值。我认为您想要的不是上面的内容,而是:pc1
值有效,因为它是一个char
指针,因此该行:添加
np1 * sizeof (char)< /code> 字节到
pc1
,即 5 个字节。增加指针会使指针指向内存中的下一个元素,而不是下一个字节。
That looks fine to me. The line:
adds
np1
instances ofst_one
to whatpst1
points at, which means thatpst1
s value is incremented bynp1 * 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:The
pc1
value works because that is achar
pointer, so the line:adds
np1 * sizeof (char)
bytes topc1
, which is 5 bytes.Incrementing a pointer makes the pointer point to the next element in memory, not the next byte.
您不应该添加
sizeof(x)
,因为这是自动完成的。当您递增指针(例如 ++p)时,地址会按对象的大小递增,以便它指向下一个。指针加 1 与 ++p 相同。添加
sizeof(x)
会将增量缩放两倍。您的计算对于 char 来说效果很好,因为 sizeof(char) 是 1。
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.
C++ 自动将要添加的整数乘以指针指向的元素的大小。它假设您想要将指针前进整个元素,而不是字节。
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.
C 和 C++ 中的指针算术是乘以指针所指向的类型的 sizeof 来完成的。即 int *abc = /* ... */; int *def = abc + 1 导致
def
的结果是abc
前面的int
,而不是char
。至于将指针转换为
long
,这是实现定义的行为,因此您可能会在不同的机器上得到奇怪的结果。(就此而言,指针类型之间的转换也是如此。C++ 说这也是实现定义的)
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 indef
having a result anint
ahead ofabc
, not achar
.As for your casting of the pointers into
long
s, 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)
看来你一切都错了。例如,要从 pst1 获取 pst2,您必须将其加一,因为指针 pst1 的类型为 st_one * ,因此您必须这样编写
: >pst2 = (st_two*)(pst1 + 1);
..但是你有:
pst2 = (st_two*)(pst1 + np1);
...其中 np1是
st_one
的sizeof
,因此它将跳过与该结构具有字节数一样多的st_one
结构...阅读一些有关指针算术的文档,就像这个。
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 typest_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
ofst_one
, so it will skip as manyst_one
structures as that structure has bytes...Read some docs on pointer arithmetic, like this one.