詳細なカスタムタイプ構造
(構造体は値のコレクションであり、これらの値はメンバー変数と呼ばれます。構造体の各メンバーは、さまざまなタイプの変数にすることができます。)
構造型宣言
たとえば、学生について説明します。
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
};//分号不能丢
特別な宣言:構造を宣言するとき、完全に宣言することはできません(構造タグを省略してください)
//匿名结构体类型
struct
{
int a;
char b;
float c; }x;
struct
{
int a;
char b;
float c; }a[20], *p;
構造の自己参照(正しい自己参照はポインターを追加するのに最適です)
struct Node
{
int data;
struct Node* next;
};
構造変数の定義と初期化
struct Point
{
int x;
int y; }p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//初始化:定义变量的同时赋初值。
struct Point p3 = {
x, y};
struct Stu //类型声明
{
char name[15];//名字
int age; //年龄
};
struct Stu s = {
"zhangsan", 20};//初始化
struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = {
10, {
4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {
20, {
5, 6}, NULL};//结构体嵌套初始化
構造体のメモリアライメント
主に構造のサイズを計算します(人気のあるテストサイト):
最初に、構造の配置ルールを習得する必要があります:
- 最初のメンバーは、構造変数からのオフセットが0のアドレスにあります。
- 他のメンバー変数は、特定の数(位置合わせ番号)の整数倍であるアドレスに位置合わせする必要があります。
アラインメント番号=コンパイラのデフォルトのアラインメント番号とメンバーサイズの小さい方の値。
VSのデフォルト値は8です - 構造体の合計サイズは、最大配置の整数倍です(各メンバー変数には配置があります)。
- 構造体がネストされている場合、ネストされた構造体は最大配置の整数倍に配置され、構造体の全体的なサイズはすべての最大配置の整数倍になります(ネストされた構造体の配置を含む)。
//练习1
struct S1
{
字节 默认值 较小值
char c1; 1 8 1
int i; 4 8 4
char c2; 1 8 1
};
int main()
{
printf("%d\n", sizeof(struct S1));
}
実行結果
注:
メモリアライメントがあるのはなぜですか?
ほとんどの参考資料には次のように書かれています。
- プラットフォームの理由(移植の理由):すべてのハードウェアプラットフォームが任意のアドレスのデータにアクセスできるわけではありません。一部のハードウェアプラットフォームは
、特定のアドレスの特定のタイプのデータしかフェッチできません。そうしないと、ハードウェア例外がスローされます。 - パフォーマンス上の理由:データ構造(特にスタック)は、可能な限り自然な境界に揃える必要があります。その理由は、アラインされていない
メモリにアクセスするには、プロセッサが2回のメモリアクセスを行う必要があるのに対し、アラインされたメモリアクセスには1回のアクセスしか必要ないためです。
一般
に、構造のメモリアライメントは、時間と空間のトレードオフの慣行です。ビットテクノロジー
。構造を設計するときは、配置を満たすだけでなく、スペースを節約する必要があります。方法:
小さなスペースを占めるメンバーをできるだけ集めます。
タイプS1とS2のメンバーはまったく同じですが、S1とS2が占めるスペースのサイズは多少異なります。
構造パラメータの転送
例えば:
struct S
{
int data[1000];
int num;
};
struct S s = {
{
1,2,3,4}, 1000};
//结构体传参
void print1(struct S s)
{
printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps)
{
printf("%d\n", ps->num);
}
int main()
{
print1(s); //传结构体
print2(&s); //传地址
return 0;
}
print1関数とprint2関数のprint2関数は優れてい
ます。関数がパラメーターを渡すとき、パラメーターをスタックにプッシュする必要があります。これにより、時間とスペースのシステムオーバーヘッドが発生します。
構造体オブジェクトを渡すときに構造体が大きすぎると、パラメータスタッキングのシステムオーバーヘッドが比較的大きくなるため、パフォーマンスが低下します。
結論:構造パラメータを渡すときは、構造のアドレスを渡す必要があります。
ビットセグメントを実現するための構造(ビットセグメントの充填と移植性)
ビットセグメントとはビットセグメントの宣言と構造は似ていますが、2つの違いがあります
。1。ビットセグメントのメンバーは、int、unsigned int、またはsignedintである必要があります。
2.ビットセグメントのメンバー名の後にコロンと数字があります。
ビットセグメントを実装する構造の機能は次のとおりです。
例:
#include<stdio.h>
#include<string.h>
struct A
{
int _a : 2;
int _b : 5;
int _c : 10;
int _d : 30;
};
int main()
{
printf("%d\n", sizeof(struct A));
}
Aはビットセグメントタイプです。(1バイト= 8ビット)
そのセグメントAのサイズはどれくらいですか?8
実行結果
ビットセグメントのメモリ割り当て
- ビットセグメントのメンバーは、int unsigned int signed intまたはchar(整数ファミリに属する)タイプにすることができます。
- ビットセグメントのスペースは、必要に応じて4バイト(int)または1バイト(char)で開かれます。
- ビットセグメントには多くの不確実な要素が含まれます。ビットセグメントはクロスプラットフォームではありません。移植性に重点を置いたプログラムでは、ビットセグメントの使用を避ける必要があります。
クロスプラットフォームの問題 - intビットフィールドが符号付き数値として扱われるのか、符号なし数値として扱われるのかは不明です。
- ビットセグメントの最大ビット数を特定できません。(16ビットマシンの最大数は16、32ビットマシンの最大数は32です。27と記述してください。16ビットマシンで
問題が発生する可能性があります。 - ビットセグメントのメンバーがメモリ内で左から右に割り当てられているか、右から左への割り当て基準が定義されていません。
- 構造体に2つのビットセグメントが含まれていて、2番目のビットセグメントのメンバーが比較的大きく、最初のビットセグメントの残りのビットに収まらない場合、残りのビット
を破棄するか使用するかは不明です。
構造と比較すると、ビットセグメントは同じ効果を達成できますが、スペースを非常に節約できますが、クロスプラットフォームの問題があります。