4

CまたはC++でパックされていないパッドなしの構造体を作成するための最良の方法は何ですか?目標は次のとおりです。

typedef struct {
    char first[3]; //padded to 8 because next type has size 8
    double second;
    char third;
} SomeStruct;

but do something to make sizeof(SomeStruct) be equal 17;

構造は外部ライブラリ仕様によって定義されます。私には2つの決定があります:

1)

#pragma pack (push, 1)

typedef struct {
    char first[3];
        char unused[5]; // Manual padding of second field.
    double second;
    char third;
} SomeStruct;

#pragma pack (pop)

2)宣言の最初のバリアントを使用しますが、データをシリアル化するときは(int)(&((SomeStruct*)0)->third) + sizeof(((SomeStruct*)0)->third)代わりに書き込みsizeof(SomeStruct)ます。そのような構造体の配列をシリアル化する必要はないので、そうすることができます。

しかし、どちらも汚いハックです。Cの構造体パディングを削除する標準的なアプローチはありますか?

4

3 に答える 3

2

C11には_Alignas、より狭い範囲の配置を提案できるキーワードが含まれるようになりました。double

typedef struct {
    char first[3]; //padded to 8 because next type has size 8
    _Alignas(uint16_t) double second;
    char third;
} SomeStruct;

これにより、可能な場合はいつでも、つまりdouble、プラットフォーム上の標準のオペレーターがそのような調整に対処できる場合は、より狭い調整が行われます。(そうでなければ、とにかくねじ込まれます。)

Clangはすでにその機能を実装しており、gccなどの他のコンパイラーにはすでにそれに近い拡張機能があるため、この構文を使用して「将来にわたって利用できる」ラッパーを簡単に作成できます。

編集:私はあなたの質問がC++についてでもあることを投稿した後にのみ見ました。C++1にはと同じ機能があると思いますalignas。(C11にはalignas -> _Alignas、標準のヘッダーファイルからのマクロがあります。)

于 2012-08-30T08:40:14.553 に答える
0

正しい順序で配置してみてください

#include <stdio.h>

struct s
{
    char first[3];
    char second;
    double third;
};

int main()
{
    printf("%u\n", sizeof(struct s));
    return 0;
}
于 2012-08-30T06:54:53.267 に答える
0

外部ライブラリの仕様で17バイトのサイズが課されている場合、SomeStructの0番目の宣言は不正確です。James McNellisがコメントで指摘したように、あなたのバージョンのサイズは24です。しかし、私たちはあなたが何を意味していたかを理解することができます。

SomeStructの最初の宣言は、どこにもパディングがないため、必要なことを実行します。外部ライブラリの仕様に一致させるために、未使用の5バイトを入力します。構造体は17バイトです。だからこれはあなたの答えのように見えます。

SomeStructの2番目の宣言が何であるかを言わないため、2番目の提案は不明確です。

SomeStructの配列を使用するかどうかは関係ありません。James McNellisのコメントが指摘しているように、標準では、配列を使用するかどうかに関係なく、コンパイラが配列の可能性を許可することを要求しています。

(もちろん、これはdoubleが8バイトであり、プラグマが希望どおりに機能することを前提としています。)

于 2012-08-30T07:00:34.157 に答える