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)

これは、s 値が 25 (sizeof = 5) のバイト単位でインクリメントされることを意味します。これは、出力した値に対応np1しますst_one。上記の代わりに、あなたが望んでいたと思います:pst1pst1np1 * sizeof (st_one)

 (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)すると、増分が 2 倍になります。

sizeof(char) は 1 であるため、char の計算は正常に機能します。

于 2011-07-27T16:07:45.080 に答える
2

C++ は、追加する整数にポインターが指す要素のサイズを自動的に乗算します。バイトではなく要素全体でポインターを進めることを前提としています。

于 2011-07-27T16:08:47.237 に答える
2

C および C++ でのポインター演算はsizeof、ポインターの指す型の倍数で行われます。つまり、結果int *abc = /* ... */; int *def = abc + 1はではなくよりも前になります。defintabcchar

へのポインターのキャストに関してはlong、それは実装定義の動作であるため、異なるマシンでそれを行うと奇妙な結果が生じる可能性があります。

(さらに言えば、ポインタ型間のキャストも同様です。C++ では、実装も定義されていると言われています)

于 2011-07-27T16:08:56.443 に答える
1

あなたはすべて間違っているようです。たとえば、pst1 から pst2 を取得するには、ポインタpst1の型がst_one *であるため、1 ずつインクリメントする必要があるため、次のように記述する必要があります。

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

..しかし、あなたは持っています:

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

... np1 はsizeofofであるため、構造体のバイト数と同じ数の構造体st_oneをスキップします...st_one

このようなポインター演算に関するドキュメントを読んでください。

于 2011-07-27T16:08:43.363 に答える