C++指针算术怪异

发布于 2024-11-26 12:46:35 字数 1734 浏览 3 评论 0原文

我发现了我的错误(几个小时后)并将其隔离在以下程序中。问题在于使用指向结构的指针时计算 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

老街孤人 2024-12-03 12:46:35

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

 (pst1 + np1)

st_onenp1 实例添加到 pst1 指向的位置,这意味着 pst1 的值递增by np1 * sizeof (st_one) 字节,即 25 (sizeof = 5),对应于您输出的值。我认为您想要的不是上面的内容,而是:

 (pst1 + 1)

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

(pc1 + np1)

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

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

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.

小嗲 2024-12-03 12:46:35

您不应该添加 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.

世界和平 2024-12-03 12:46:35

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.

栖迟 2024-12-03 12:46:35

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 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)

月下伊人醉 2024-12-03 12:46:35

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

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

..但是你有:

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

...其中 np1是 st_onesizeof,因此它将跳过与该结构具有字节数一样多的 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 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文