コンテンツ
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つの他のメンバーが必要です。それ以外の場合、構造体のサイズは0です。
- sizeofによって返されるこの構造体のサイズには、柔軟な配列のメモリは含まれていません。
- 柔軟な配列メンバーを含む構造体は、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を複数回使用することで開かれるスペースは必ずしも連続的ではないため、中央にいくつかのギャップがあり、これらのギャップをメモリの断片化と呼びます。
ブロガーの能力には限界があります。誤解があれば、鉄汁を批判してください。
今日はこれでおしまい、ご覧いただきありがとうございます