課堂筆記4

428号宇宙伞兵發表於2024-03-22

判斷計算機是大端還是小段儲存

include <stdio.h>

int CheckSys()
{
int a = 1;
if((char)&a == 1)//對存在記憶體的資料進行訪問就得取出該資料得地址這樣才能在記憶體中找到該資料,強轉為char*型別是因為要取出第一個位元組的內容
{
return 1;
}
else
{
return 0;
}

}

int main()
{
int ret = CheckSys();
if(ret == 1)
{
printf("小段\n");
}
else
{
printf("大端\n");
}
return 0;
}

常見的動態記憶體錯誤
1.對NULL指標進行解引用操作
void test()
{
int *p = (int *)malloc(INT_MAX/4);
*p = 20;//如果p的值是NULL,就會有問題,要先判斷p是否為空才能解引用
free(p);
}

2.對動態開闢的空間越界訪問
void test()
{
int i = 0;
int *p = (int )malloc(10sizeof(int));
if(NULL == p)
{
exit(EXIT_FAILURE);
}
for(i=0; i<=10; i++)
{
*(p+i) = i;//申請的動態記憶體只有10個整形空間的大小,當i是10的時候越界訪問
}
free(p);
}

3.對非動態開闢的記憶體使用free釋放
void test()
{
int a = 10;//a為臨時變數存在於棧區而動態記憶體申請的空間實在堆區不能使用free釋放
int *p = &a;
free(p);
}

4.使用free釋放一部分動態記憶體空間
//int main()
//{
// //intp = (int)malloc(40);
// int* p = calloc(10, sizeof(int));
//
// if (p == NULL)
// return 1;
//
// int i = 0;
// for (i = 0; i < 5; i++)
// {
// printf("%d\n", *(p + i));
// }
//
// free(p);
// p = NULL;
//
// return 0;
//}

經典筆試題:
//str傳給GetMemory函式的時候是值傳遞,所以GetMemory函式的形參p是str的一份臨時複製。
//在GetMemory函式內部動態申請空間的地址,存放在p中,不會影響外邊str,所以當GetMemory函式返回之後,str依然是NULL。所以strcpy會失敗。
//
//當GetMemory函式返回之後,形參p銷燬,使得動態開闢的100個位元組存在記憶體洩漏。無法釋放。
//void GetMemory(char* p)
//{
// p = (char)malloc(100);//p是一個臨時變數在函式內部使用完以後就會被釋放
//}
//void Test(void)
//{
// char
str = NULL;
// GetMemory(str);
// strcpy(str, "hello world");
// printf(str);
//}
//
//int main()
//{
// Test();
// return 0;
//}

//改:1
//char* GetMemory(char* p)
//{
// p = (char)malloc(100);
// return p;//這裡返回的是申請的動態記憶體的地址,在 GetMemory 函式內部,雖然分配了動態記憶體並將其地址賦給了 p,
//但是這個地址並沒有傳遞迴 Test 函式中的 str,因為 p 是按值傳遞的。
//}
//void Test(void)
//{
// char
str = NULL;
// str = GetMemory(str);
// strcpy(str, "hello world");
// printf(str);//strcpy 函式試圖將字串 "hello world" 複製到 str 指向的記憶體位置,但是 str 仍然是 NULL,沒有指向有效的記憶體區域,因此這裡會產生未定義的行為。
// //printf("hello world");//char *p = "hello world";
// free(str);
// str = NULL;
//}
//int main()
//{
// Test();
// return 0;
//}

//改2
//void GetMemory(char** p)//str本身就是char型別所以在設計形參時要用二級指標接受
//{
// p = (char)malloc(100);
//}
//void Test(void)
//{
// char
str = NULL;
// GetMemory(&str);把str的地址傳進去
//
// strcpy(str, "hello world");
// printf(str);
// free(str);
// str = NULL;
//}
//
//int main()
//{
// Test();
// return 0;
//}這樣就能正確列印出hello world了

//GetMemory 函式內部建立的陣列是在棧區上建立的
//出了函式,p陣列的空間就還給了作業系統
//返回的地址是沒有實際的意義,如果透過返回的地址,去訪問記憶體就是非法訪問記憶體的
//
//char* GetMemory(void)
//{
// char p[] = "hello world";
// return p;
//}
//void Test(void)
//{
// char* str = NULL;
// str = GetMemory();
// printf(str);
//}
//
//int main()
//{
// Test();
// return 0;
//}

//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;
//}在函式 GetMemory 中,它接受一個指向指標的指標 p 和一個整數 num,它透過呼叫 malloc 分配了 num 位元組大小的動態記憶體,並將其地址賦給 *p。這裡使用了間接賦值,將動態記憶體的地址傳遞迴了 Test 函式中的 str。

在函式 Test 中,首先將 str 初始化為 NULL。然後呼叫 GetMemory 函式,將 &str(str 的地址)作為引數傳遞給 GetMemory。在 GetMemory 函式內部,透過 *p 將動態記憶體的地址賦給了 str。

接下來,使用 strcpy 函式將字串 "hello" 複製到 str 指向的記憶體位置。然而,在呼叫 printf 函式時,使用了 str 作為引數,這是不正確的。printf 函式需要一個格式化字串作為第一個引數,而 str 只是一個指向字元的指標,不能直接傳遞給 printf。

相關文章