動的メモリ管理(続き)+柔軟なアレイ

コンテンツ

1.いくつかの筆記試験の質問

1.1トピック1:

 1.2トピック2

1.3トピック3

1.4質問4

2.動的メモリ管理のレビュー

 3.柔軟なアレイ

 3.1フレキシブルアレイの機能

 3.2柔軟な配列の使用

3.3柔軟なアレイの利点 


1.いくつかの筆記試験の質問

1.1トピック1:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
void GetMemory(char* p) 
{
	p = (char*)malloc(100);
}
void Test(void) 
{
	char* str = NULL;
	GetMemory(str);
	strcpy(str, "hello world");
	printf(str);
}
int main()
{
    Test();
    return 0;
}

運転結果

pは仮パラメータであるため、スペースが開かれるとGetMemory関数が破棄されます。このとき、ポインタが開いたスペースのアドレスを見つけることができず、メモリリークの問題が発生します。したがって、strはまだNULLであり、strcpyが必要です。 strcpyを実装するときに参照解除されます(NULLを参照解除)と、問題(メモリへの不正アクセス)が発生し、プログラムがクラッシュします。

strcpyの実装は、C言語の文字列+メモリ関数を参照できます-プログラマーが求めています 

:ここにprintf(str)を書き込んでも問題ありませんが、上記の理由により印刷できません。

次に例を示します。printf( "abc")は、実際には最初の要素aのアドレスをprintf関数char * str = "abc"に渡します。strは、配列に相当する"abc"の最初の要素のアドレスを格納します。名前なので、printf(str)が妥当です。

修正1

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void GetMemory(char** p)
{
	*p = (char*)malloc(100);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(&str);
	strcpy(str, "hello world");
	printf(str);
	free(str);
	str = NULL;
}
int main()
{
	Test();
	return 0;
}

スクリーンショットを実行する

修正2

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* GetMemory(char* p)
{
	*p = (char*)malloc(100);
    return p;
}
void Test(void)
{
	char* str = NULL;
	GetMemory(str);
	strcpy(str, "hello world");
	printf(str);
	free(str);
	str = NULL;
}
int main()
{
	Test();
	return 0;
}

 1.2トピック2

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* GetMemory(void) 
{
	char p[] = "hello world";//这块空间是在栈区开辟的,出函数后空间自动销毁
	return p;
}
void Test(void) 
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}
int main()
{
	Test();
	return 0;
}

GetMemory関数の実行後、「helloworld」スペースが解放され、pはそれを使用する権限がありません。これはワイルドポインタです。このスペースに再度アクセスすると、このスペースが上書きされた可能性があります(不正なアクセススペース)。

例:たとえば、Li Huaは仕事に疲れていて、家に帰って休むことを望んでいません。彼は外にホテルを見つけ、部屋は509です。彼は疲れすぎているため、しばらく眠ります。 Huaの外国人の友人Johnが明日その場所を訪問します。住む場所を見つけたい場合は、LiHuaに電話してください。LiHua:わかりました。明日来て滞在できます。私は509にいます。翌日、Li Huaが部屋を出ます。ジョンは、Li Huaが昨日言うのを聞きました。私は509にとどまることができるので、荷物をホテルにドラッグして、「509にとどまりたいのですが、部屋はすでに占有されています... ..。。

 変更:静的変更

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* GetMemory(void) 
{
	static char p[] = "hello world";//静态区
	return p;
}
void Test(void) 
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}
int main()
{
	Test();
	return 0;
}

1.3トピック3

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void GetMemory(char** p, int num)
{
	*p = (char*)malloc(num);
}
void Test(void) 
{
	char* str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");
	printf(str);
}
int main()
{
	Test();
	return 0;
}

動的に開かれたスペースが使い果たされたら、freeを使用してスペースを解放し、ポインターを空にします

法律を変える

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void GetMemory(char** p, int num)
{
    
	*p = (char*)malloc(num);
}
void Test(void) 
{
	char* str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");
	printf(str);
    free(str);
    str=NULL;
}
int main()
{
	Test();
	return 0;
}

1.4質問4

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void Test(void)
{
	char* str = (char*)malloc(100);
	strcpy(str, "hello");
	free(str);//hello所在的空间已经还给操作系统,此时str为野指针
    //free之后,一定要将指针置空
	if (str != NULL)
	{
		strcpy(str, "world");//world会把hello覆盖,(非法访问)
		printf(str);
	}
}
int main()
{
	Test();
	return 0;
}

スクリーンショットを実行する

 法律を変える

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void Test(void)
{
	char* str = (char*)malloc(100);
	strcpy(str, "hello");
	free(str);
    str=NULL;
    if (str != NULL)
	{
		strcpy(str, "world");
		printf(str);
	}
}
int main()
{
	Test();
	return 0;
}

2.動的メモリ管理のレビュー

c言語の動的メモリ管理-ZhenBailinziのブログ-CSDNブログ

 3.柔軟なアレイ

構造体の最後の要素は、柔軟な配列メンバーと呼ばれる、サイズが不明な配列にすることができます。

例えば: 

struct s1
{
	int age;
	char name[20];
	int arr[];//柔性数组成员
};

 一部のコンパイラはエラーを報告します。次の記述方法を試すことができます。

struct s2
{
	int age;
	char name[20];
	int arr[0];//柔性数组成员,这里的0代表未知大小
};

 3.1フレキシブルアレイの機能

  1. 構造内の柔軟な配列メンバーの前には、少なくとも1つの他のメンバーが必要です。それ以外の場合、構造体のサイズは0です。
  2. sizeofによって返されるこの構造体のサイズには、柔軟な配列のメモリは含まれていません。
  3. 柔軟な配列メンバーを含む構造体は、malloc()関数を使用して動的にメモリを割り当てます。割り当てられたメモリは、柔軟な配列の予想サイズに対応するために、構造体のサイズよりも大きくする必要があります。

 例えば:

#include<stdio.h>
struct s2
{
	int age;//4
	char name[20];//20
	int arr[0];//0
};
int main()
{
	printf("%d\n", sizeof(struct s2));
	return 0;
}

 3.2柔軟な配列の使用

#include<stdio.h>
#include<stdlib.h>
struct s3//4
{
	int num;
	int arr[];
};
int main()
{
	struct s3* ps = (struct s3*)malloc(sizeof(struct s3) + 40);//假设我们希望数组中有10个元素
	ps->num = 100;
	int i = 0;
	//使用
	for (i = 0; i < 10; i++)
	{
		ps->arr[i] = i;
	}
	//增容
	struct s3* ptr = realloc(ps, sizeof(struct s3) + 80);
	if (ptr != NULL)
	{
		ps = ptr;
	}
	for (i = 10; i < 20; i++)
	{
		ps->arr[i] = i;
	}
	for (i = 0; i < 20; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	//释放
	free(ps);
	ps = NULL;//置空
	return 0;
}

柔軟な配列に似た別の書き方 

struct s3//sizeof计算为8
{
	int num;
	int *arr;
};
int main()
{
	struct s3* ps = (struct s3*)malloc(sizeof(struct s3));
	ps->arr = (int*)malloc(sizeof(int) * 5);
	int i = 0;
	//使用
	for (i = 0; i < 5; i++)
	{
		ps->arr[i] = i;
	}
	//增容
	int * ptr = realloc(ps->arr, 10*sizeof(int));
	if (ptr != NULL)
	{
		ps->arr = ptr;
	}
	for (i = 5; i < 10; i++)
	{
		ps->arr[i] = i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	//释放
	free(ps->arr);
	free(ps);
	ps = NULL;//置空
	return 0;

 2つの違いは

1.フレキシブルアレイが配置されている構造のサイズは4で、次の構造のサイズは8です。

2.柔軟な配列は構造体にのみ存在し、次の方法が一般的です(動的にメモリスペースを開きます)

3.3柔軟なアレイの利点 

1.便利なメモリリリース
コードが他のユーザーによって使用される関数内にある場合は、そのコードで2次メモリの割り当てを行い、構造全体をユーザーに返します。ユーザーはfreeを呼び出すことで構造体を解放できますが、構造体のメンバーも解放する必要があることをユーザーは知らないため、ユーザーが見つけることを期待することはできません。したがって、構造体のメモリとそのメンバーが必要とするメモリを一度に割り当て、構造体ポインタをユーザーに返すと、ユーザーは一度解放することですべてのメモリを解放できます。
2.アクセス速度を助長します
連続メモリは、アクセス速度を向上させ、メモリの断片化を減らすのに役立ちます

mallocを複数回使用することで開かれるスペースは必ずしも連続的ではないため、中央にいくつかのギャップがあり、これらのギャップをメモリの断片化と呼びます。

ブロガーの能力には限界があります。誤解があれば、鉄汁を批判してください。

今日はこれでおしまい、ご覧いただきありがとうございます

おすすめ

転載: blog.csdn.net/weixin_63451038/article/details/123997636