基礎知識-指針

1、指針的基本概念

1.1 什么是指針

1.1.1 指針的定義

????????指針是一種特殊的變量,與普通變量存儲具體數據不同,它存儲的是內存地址。在計算機程序運行時,數據都被存放在內存中,而指針就像是指向這些數據存放位置的 “路標”。通過指針,程序可以間接訪問和操作對應內存地址的數據。

1.1.2 指針與普通變量的區別

????????普通變量直接存儲數據值,比如 int num = 10; ,變量 num 中直接存放的是數值 10 。而指針變量存儲的是內存地址,例如 int num = 10; int *ptr = # ,指針 ptr 存儲的是變量 num 在內存中的地址,要獲取 num 的值,需要通過解引用操作 *ptr 。

????????此外,普通變量的運算基于其存儲的數據類型,如 int 型變量可進行加減乘除;指針變量的運算則圍繞內存地址偏移,比如 ptr++ 會根據 int 類型數據在內存中占用的字節數(通常 4 字節),將指針指向下一個 int 數據的地址。

1.2 內存與地址的關系

????????內存是計算機用于臨時存儲數據和程序的硬件設備,就像一個龐大的倉庫,被劃分成一個個連續的小格子,每個小格子都有唯一的編號,CPU 通過這些編號,找到相應的內存空間,這個編號就是內存地址。數據在存儲時,會被分配到特定的內存地址空間中。地址就如同倉庫格子的編號,程序通過地址來準確找到數據在內存中的存放位置,從而實現對數據的讀寫操作 。當定義一個變量時,系統會在內存中為其分配一定的空間,并賦予對應的內存地址,而指針變量存儲的就是這些地址,以此建立起對數據的間接訪問通道。

????????形象地來說,內存是一棟樓,一個內存單元是一戶人家,指針是門牌號,CPU是我們,我們通過門牌號可以找到那戶人家住的地方。

1.2.1 計算機內存結構簡介

????????計算機內存通常采用線性編址結構,從低地址到高地址連續排列。在邏輯上,內存可分為多個區域,如棧區、堆區、全局數據區、代碼區等。

  • 棧區:主要用于存儲函數調用時的局部變量、函數參數等,遵循后進先出原則
  • 堆區:用于動態內存分配,可通過 malloc (C 語言)或 new (C++ 語言)等函數在堆上申請內存
  • 全局數據區:存放全局變量和靜態變量
  • 代碼區:存儲程序的可執行代碼

????????指針在不同內存區域的數據操作中都發揮著關鍵作用,比如在堆區通過指針管理動態分配的內存,在棧區利用指針傳遞函數參數等。

1.2.2 地址的作用與表示

????????地址的核心作用是標識內存中數據的存儲位置,它使得程序能夠準確找到并操作數據。

????????在計算機中,地址通常以二進制形式存儲和處理,但在編程中,常以十六進制數表示,便于閱讀和理解。在 C 語言的調試過程中,打印指針變量的值,顯示的就是十六進制的內存地址。

2、指針的基本語法

2.1 指針的聲明與初始化

2.1.1 指針的聲明

????????語法格式:數據類型 *指針名;

注:“數據類型” 表明該指針所指向變量的類型,“指針變量名” 則是用戶為指針取的名字

int *ptr;  //聲明一個指向int類型數據的指針ptr
float *fptr;  //聲明一個指向float類型數據的指針fptr

2.1.2 指針的初始化

????????指針初始化就是在聲明指針的同時為其賦予一個合法的內存地址。

常見的初始化方式有:

  • 初始化為 NULL
  • 初始化為變量的地址
  • 初始化為動態分配的內存地址
//初始化為 NULL
int *ptr = NULL;//初始化為變量的地址
int num = 10;
int *ptr = #//初始化為動態分配的內存地址
int *ptr = (int *)malloc(sizeof(int));

2.2 取地址操作符&

? ? ? ? 作用:用于獲取變量的內存地址。

#include <stdio.h>int main() 
{int num = 10;int *ptr = &num;  //使用取地址操作符&獲取變量num的地址并賦給指針ptrprintf("變量 num 的地址: %p\n", (void *)&num);printf("指針 ptr 存儲的地址: %p\n", (void *)ptr);return 0;
}

在使用 printf 函數輸出指針的值時,%p 格式說明符要求對應的參數是 void * 類型。這是由于 %p 用于以十六進制形式輸出指針所存儲的內存地址,而 void * 類型的指針可以存儲任意類型的地址,能確保輸出的是純粹的地址信息。

2.3 解引用操作符*

????????作用1:通過指針訪問所指向的值。

#include <stdio.h>int main() 
{int num = 10;int *ptr = &num;int value = *ptr;  //通過解引用操作符*獲取指針ptr所指向的值printf("指針 ptr 所指向的值: %d\n", value);  //輸出為10return 0;
}

????????作用2:修改指針指向的值。

#include <stdio.h>int main() 
{int num = 10;int *ptr = &num;*ptr = 20;  //通過解引用操作符*修改指針ptr所指向的值printf("變量 num 的新值: %d\n", num);  //輸出為20return 0;
}

2.4 空指針

????????空指針表示不指向任何有效內存地址的指針。?

  • 在 C 語言中,通常用 NULL 來表示空指針
  • 在 C++ 11 及以后的版本中,推薦使用 nullptr
int main() 
{//C環境下int *ptr = NULL;  //C語言中使用NULL初始化空指針printf("指針 ptr 的值: %p\n", (void *)ptr);//C++環境下int *ptr = nullptr;  //C++中使用nullptr初始化空指針std::cout << "指針 ptr 的值: " << ptr << std::endl;return 0;
}

3、指針的核心應用

3.1 函數參數傳遞

3.1.1 值傳遞

????????在值傳遞中,函數調用時會將實參的值復制一份給形參函數內部對形參的任何修改都只會影響形參本身,而不會影響到實參

#include <stdio.h>void changeValue(int num) 
{num = 20;printf("函數內部 num 的值: %d\n", num);  //輸出為20
}int main() 
{int num = 10;changeValue(num);printf("函數外部 num 的值: %d\n", num);  //輸出依舊為10,值傳遞不影響實參return 0;
}

3.1.2 指針傳遞

????????指針傳遞是將實參的地址傳遞給形參,形參是一個指針它指向實參所在的內存地址。因此,函數內部可以通過指針來修改實參的值

#include <stdio.h>void changeValue(int *ptr) 
{*ptr = 20;printf("函數內部指針指向的值: %d\n", *ptr);  //輸出為20
}int main() 
{int num = 10;changeValue(&num);printf("函數外部 num 的值: %d\n", num);  //輸出為20,指針傳遞會改變實參return 0;
}

3.2 動態內存分配

  • C 語言:malloc、calloc、realloc 和 free
  • C++ 語言:new 和 delete

3.2.1 C 語言?

malloc

????????用于在堆上分配指定大小的內存塊,返回一個指向該內存塊起始地址的指針。如果分配失敗,返回 NULL。

#include <stdio.h>
#include <stdlib.h>int main() 
{int *ptr = (int *)malloc(5 * sizeof(int));if (ptr == NULL){printf("內存分配失敗\n");return 1;}//初始化數組元素for (int i = 0; i < 5; i++) {ptr[i] = i;}//輸出數組元素for (int i = 0; i < 5; i++) {printf("%d ", ptr[i]);}printf("\n");//釋放內存free(ptr);ptr = NULL;return 0;
}

calloc

????????用于在堆上分配指定數量和大小的內存塊,并將其初始化為 0。返回一個指向該內存塊起始地址的指針。如果分配失敗,返回 NULL。

#include <stdio.h>
#include <stdlib.h>int main() 
{int *ptr = (int *)calloc(5, sizeof(int));if (ptr == NULL) {printf("內存分配失敗\n");return 1;}//輸出數組元素,由于calloc會初始化為0,所以輸出全為0for (int i = 0; i < 5; i++) {printf("%d ", ptr[i]);}printf("\n");//釋放內存free(ptr);ptr = NULL;return 0;
}

realloc

????????用于調整已分配內存塊的大小。可以擴大或縮小內存塊。返回一個指向新內存塊起始地址的指針。如果分配失敗,返回 NULL,原內存塊不會被釋放

#include <stdio.h>
#include <stdlib.h>int main() 
{int *ptr = (int *)malloc(3 * sizeof(int));if (ptr == NULL) {printf("內存分配失敗\n");return 1;}//初始化數組元素for (int i = 0; i < 3; i++) {ptr[i] = i;}//擴大內存塊int *newPtr = (int *)realloc(ptr, 5 * sizeof(int));if (newPtr == NULL) {printf("內存重新分配失敗\n");free(ptr);ptr = NULL;return 1;}ptr = newPtr;//初始化新增的數組元素for (int i = 3; i < 5; i++) {ptr[i] = i;}//輸出數組元素for (int i = 0; i < 5; i++) {printf("%d ", ptr[i]);}printf("\n");//釋放內存free(ptr);ptr = NULL;return 0;
}

分析代碼里的內存分配情況:

  • 借助 malloc 函數分配了 3 塊 int 類型的內存,并且把指向這塊內存的指針賦值給 ptr
  • 利用 realloc 函數把之前分配的 3 塊 int 類型內存重新分配為 5 塊 int 類型的內存。要是重新分配成功,realloc 函數會返回一個指向新內存塊的指針,然后把這個指針賦值給 newPtr
  • 把 newPtr 的值賦給 ptr,這樣 ptr 就指向了新分配的 5 塊 int 類型的內存

注意:先分配的 3 塊內存并沒有單獨釋放,而是在重新分配內存后,將其包含在新的內存塊中,最終一起釋放。

free

????????用于釋放之前通過 malloc、calloc 或 realloc 分配的內存塊。釋放后的內存可以被再次分配。

????????注意:釋放后的指針成為野指針,建議將其置為 NULL,避免誤操作。

3.2.2 C++ 語言

new

????????用于在堆上分配內存并構造對象。對于基本數據類型,直接分配內存;對于類類型,會調用構造函數。

#include <iostream>
using namespace std;int main() 
{//分配一個int型內存,并初始化為10,也可以不初始化,直接new int就可以int *ptr = new int(10);cout << *ptr << endl;//分配一個int型數組,長度為5int *arr = new int[5];for (int i = 0; i < 5; i++) {arr[i] = i;}for (int i = 0; i < 5; i++) {cout << arr[i] << " ";}cout << endl;// 釋放內存delete ptr;delete[] arr;  //釋放數組return 0;
}

delete

????????用于釋放通過 new 分配的內存。對于基本數據類型,直接釋放內存;對于類類型,會調用析構函數。

????????注意:釋放數組時需要使用 delete[ ],否則會導致內存泄漏。

3.2.3 結構體與指針的結合使用

????????結構體可以將不同類型的數據組合在一起,而指針可以方便地訪問和操作結構體。可以定義指向結構體的指針,通過指針來訪問結構體的成員。

#include <stdio.h>
#include <stdlib.h>//定義結構體
typedef struct 
{int age;char name[20];
} Person;int main() 
{//創建結構體變量Person p = {20, "John"};//創建指向結構體的指針Person *ptr = &p;//通過指針訪問結構體成員printf("Name: %s, Age: %d\n", ptr->name, ptr->age);return 0;
}

4、指針相關問題

4.1 野指針

4.1.1 產生原因

  • 指針未初始化:定義指針變量后沒有給它賦一個合法的地址值,此時指針指向的位置是隨機的,變成野指針。
int* ptr;  //ptr就是一個野指針
  • 指針所指向的內存被釋放后未置空:當使用 free 或 delete 釋放了指針所指向的內存后,如果沒有將指針設置為 NULL,指針仍然保存著原來已釋放內存的地址,就變成了野指針。
int* ptr = (int*)malloc(sizeof(int));
free(ptr);
//此時ptr成為野指針,如果再次訪問*ptr就會有問題
  • 指針越界操作:當指針進行了不恰當的運算,使其指向了不屬于原本所指向的內存區域,也會形成野指針。比如對數組指針進行越界的移動操作。
int main() 
{//定義一個包含5個元素的整型數組int arr[5] = {1, 2, 3, 4, 5};//定義一個指針指向數組的首元素int *ptr = arr;//正常訪問數組元素for (int i = 0; i < 5; i++) {printf("arr[%d] = %d\n", i, *(ptr + i));}//越界操作:將指針移動到數組范圍之外ptr = ptr + 5;//嘗試訪問越界后的指針指向的內存printf("越界訪問的值: %d\n", *ptr);return 0;
}

4.1.2 解決方法

  • 初始化指針:在定義指針變量時,將其初始化為 NULL 或者指向一個合法的內存地址。
//法一:初始化為 NULL
int* ptr = NULL;//法二:指向一個合法的內存地址
int num; 
int* ptr = &num;
  • 內存釋放后置空指針:在使用 free 或 delete 釋放內存后,立即將指針賦值為 NULL,這樣可以避免再次誤操作該指針。
int* ptr = (int*)malloc(sizeof(int));
free(ptr);
ptr = NULL;  //釋放后置空
  • 小心指針運算:進行指針運算時,要確保不超出所指向內存的范圍,對于數組指針,要根據數組的大小進行合理的指針移動。

4.2 內存泄漏

4.2.1 動態內存未釋放的后果

  • 內存浪費:程序占用的內存會不斷增加,導致系統可用內存減少,影響其他程序的運行,甚至可能導致系統性能下降。
  • 程序崩潰:當系統內存耗盡時,程序可能會因為無法分配到所需的內存而崩潰。
  • 資源耗盡:在一些資源有限的環境中,內存泄漏可能會導致系統無法正常工作,因為沒有足夠的內存來執行其他必要的操作。

4.2.2 解決方法

  • 及時釋放內存:在使用完動態分配的內存后,要及時使用 free 或 delete 釋放內存。
  • 使用智能指針(C++):C++ 提供了智能指針(如 std::unique_ptr、std::shared_ptr)來自動管理內存,當智能指針超出作用域時,會自動釋放所指向的內存,從而避免內存泄漏。

4.3 指針運算

4.3.1 指針加減整數的運算

????????指針加減整數的運算結果是一個新的指針,其指向的位置會根據指針所指向的數據類型的大小進行移動。

#include <stdio.h>int main() 
{int arr[5] = {1, 2, 3, 4, 5};int *ptr = arr;  //ptr指向數組的第一個元素//指針加1int *next_ptr = ptr + 1;printf("ptr 指向的值: %d\n", *ptr);  //輸出為1printf("ptr + 1 指向的值: %d\n", *next_ptr);  //輸出為2//指針減1int *prev_ptr = next_ptr - 1;printf("next_ptr - 1 指向的值: %d\n", *prev_ptr);  //輸出為1return 0;
}

4.3.2 指針間的減法運算

????????指針的減法運算通常用于計算兩個指針之間的距離,結果是一個整數,表示兩個指針之間相差的元素個數,前提是這兩個指針指向同一塊連續的內存區域(如數組)。

#include <stdio.h>int main() 
{int arr[5] = {1, 2, 3, 4, 5};int *ptr1 = &arr[0];  //指向數組第一個元素int *ptr2 = &arr[3];  //指向數組第四個元素//計算兩個指針之間的距離int distance = ptr2 - ptr1;printf("ptr2 和 ptr1 之間相差的元素個數: %d\n", distance);  //輸出為3,表示它們之間相差3個int型元素return 0;
}

4.3.3 指針間的比較

????????只有當兩個指針指向同一塊連續的內存區域(如數組)且有關聯時,進行比較才有意義。例如,比較數組中不同元素的指針,判斷它們的先后順序。

#include <stdio.h>int main() 
{int arr[5] = {1, 2, 3, 4, 5};int *ptr1 = &arr[0];  //指向數組第一個元素int *ptr2 = &arr[3];  //指向數組第四個元素//比較指針if (ptr1 < ptr2) {printf("ptr1 指向的元素在 ptr2 指向的元素之前\n");} else {printf("ptr1 指向的元素在 ptr2 指向的元素之后或相同\n");}return 0;
}

4.4 二級指針、三級指針

4.4.1 二級指針

????????二級指針是指向指針的指針。也就是說,二級指針所存儲的地址是一個指針變量的地址,而這個指針變量又指向實際的數據。

4.4.2 三級指針

????????三級指針是指向二級指針的指針,即它存儲的地址是一個二級指針變量的地址。

int num = 10;
int* ptr1 = &num;  //一級指針
int** ptr2 = &ptr1;  //二級指針
int*** ptr3 = &ptr2;  //三級指針

5、指針數組與數組指針

5.1 指針數組

  • 定義:元素為指針的數組
  • 語法格式:數據類型*? 數組名[數組長度]
#include <stdio.h>int main()
{//定義一個數組a,并給數組賦值int a[10];for (int i = 0; i < 10; i++){a[i] = i + 1;}//指針數組:數組中的每一個元素都是指針int* arr[10] = { a, a + 1, a + 2, a + 3, a + 4, a + 5, a + 6, a + 7, a + 8, a + 9 };//a + 1 == &a[0] + 1 == &a[1];//a[5] ? --> a數組中下標為5的元素是多少?//printf("%d %d", *arr[5], **(arr + 5));//**(arr + 5)的推導//arr == &arr[0];//arr + 5 == &arr[0] + 5 == &arr[5];//*(arr + 5) == *(&arr[5]) == arr[5];//**(arr + 5) == *arr[5] == a[5];return 0;
}    

5.2 數組指針

  • 定義:指向某個數組的指針
  • 語法格式:數據類型? (*指針名)? [數組長度]
#include <stdio.h>int main()
{//定義一個數組a,并給數組賦值int a[10];for (int i = 0; i < 10; i++){a[i] = i + 1;}//數組指針:本身是一個指針,存的是元素類型是int、元素個數為10的數組的地址int (*arry)[10];arry = &a;  //賦值printf("%d", *((int*)(arry + 1) - 1));  //輸出為10return 0;
}    

輸出語句 printf("%d", *((int*)(arry + 1) - 1)); 的詳細解釋:

  • arry + 1:由于 arry 是一個指向包含 10 個 int 元素數組的指針,arry + 1 會讓指針向后移動一個包含 10 個 int 元素數組的長度,也就是跳過整個數組 a 所占用的內存空間,指向數組 a 之后的內存位置。
  • (int*):將 arry + 1 的結果強制轉換為 int* 類型的指針。這一步的作用是將原本指向整個數組的指針轉換為指向單個 int 元素的指針,以便后續進行以 int 為單位的指針運算。
  • (int*)(arry + 1) - 1:在強制轉換為 int* 類型指針后,進行減 1 操作。因為現在是 int* 類型的指針,減 1 會讓指針向前移動一個 int 類型的長度,也就是回到數組 a 的最后一個元素的地址。
  • *((int*)(arry + 1) - 1):對前面得到的指針進行解引用操作,獲取該指針所指向的內存位置存儲的值,也就是數組 a 的最后一個元素的值,即 10。

6、指針函數與函數指針

6.1 指針函數

  • 定義:本身是一個函數,返回值是一個指針
  • 語法格式:數據類型*? 函數名(參數列表)
#include <stdio.h>//指針函數:返回值為指針的函數
//注意:這里返回局部變量的地址會導致未定義行為,因為局部變量在函數結束后會被銷毀
//可以使用靜態局部變量來解決上述問題int* fun() 
{static int a = 10;  //使用靜態局部變量return &a;
}int main() 
{int* ptr = fun();printf("訪問返回指針指向的值: %d\n", *ptr);return 0;
}

6.2 函數指針

  • 定義:本身是一個指針,存的是函數的地址
  • 語法格式:數據類型? (*指針名)? (參數列表)

?注:“數據類型”指的是函數的返回值類型,“參數列表”指的是函數的參數列表

#include <stdio.h>//函數的定義不允許嵌套
//函數的調用允許嵌套
//當函數體在主函數下方時,需要在函數上方進行函數聲明//聲明fff函數
int fff();int main() 
{//函數指針:本身是一個指針,存的是函數的地址int (*f)() = fff;  //fff等價于&fff//函數的調用方式fff();f();  //通過地址訪問,fff()等價于f()等價于(*f)()return 0;
}//定義fff函數
int fff() 
{printf("asd");return 0;
}  
  • fff():這是普通的函數調用方式。fff 是函數名,直接在函數名后面加上括號并傳入相應的參數( fff 函數沒有參數),就可以調用這個函數。當執行 fff() 時,程序會跳轉到 fff 函數的代碼塊中執行其中的語句,即輸出字符串 "asd"。
  • f():f 是一個函數指針,它存儲了函數 fff 的地址。當使用 f() 這種形式調用時,實際上是通過函數指針 f 來調用它所指向的函數(即 fff 函數)。因為 f 指向了 fff 函數的地址,所以 f() 的效果和直接調用 fff() 是一樣的,程序同樣會跳轉到 fff 函數的代碼塊中執行。
  • (*f)():這種寫法也是通過函數指針 f 來調用函數。在 C 語言中,函數指針本質上是一個指向函數的地址的指針變量。*f 是對函數指針 f 進行解引用操作,從概念上來說,*f 就表示 fff 函數。所以 (*f)() 同樣是調用 f 所指向的函數,它和 f() 以及 fff() 的作用是等價的,最終都會執行 fff 函數中的代碼。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/77420.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/77420.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/77420.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

VS遠程Linux_CMake項目搭建

VS遠程Linux CMake項目搭建 準備工作 遠程計算機上安裝 gcc: 一個開源的編譯器集合, GCC支持多種編程語言的編譯&#xff0c;包括C、C、Objective-C、Fortran、Ada、Go、D和Javagdb: GDB&#xff08;GNU Debugger&#xff09;是一個功能強大的調試工具&#xff0c;主要用于調…

替代升級VMware | 云軸科技ZStack構建山西證券一云多芯云平臺

通過云軸科技ZStack Cloud云平臺&#xff0c;山西證券打造了敏捷部署、簡單運維的云平臺&#xff0c;不僅兼容x86、海光、鯤鵬三種異構服務器實現一云多芯&#xff0c;還通過云平臺虛擬化納管模塊納管原有VMware虛擬化資源&#xff0c;并對接第三方集中式存儲&#xff0c;在保護…

MATLAB - 模型預測控制器(MPC)的穩定性和魯棒性問題

系列文章目錄 目錄 系列文章目錄 前言 一、被控對象模型 二、初始控制器設計 三、改進初始設計 五、查看軟約束 七、參考 前言 您可以檢查模型預測控制器設計是否存在潛在的穩定性和魯棒性問題。具體操作如下 在命令行中&#xff0c;使用審查功能。在 MPC Designer 中&a…

《GPT-4.1深度解析:AI進化新標桿,如何重塑行業未來?》

一、GPT-4.1:AI 領域的 “全能戰士” 降臨 1.1 發布背景與戰略意義 在 OpenAI 的技術迭代版圖中,GPT-4.1 被賦予了 “承前啟后” 的關鍵角色。它不僅是 GPT-4o 的全面升級版,更被視為向 GPT-5 過渡的重要橋梁。2025 年 4 月 15 日的發布會上,OpenAI 宣布 GPT-4.1 系列模型…

MySQL+Redis實戰教程:從Docker安裝部署到自動化備份與數據恢復20250418

MySQLRedis實戰教程&#xff1a;從Docker安裝部署到自動化備份與數據恢復 一、前言 在企業應用中&#xff0c;對MySQL和Redis運維的要求越來越高&#xff1a; 不能僅是啟動就算部署運行穩定、隔離、訪問控制、備份恢復、安全可靠&#xff0c;才是 企業級的基本功能 本文將手…

Linux系統編程之守護進程與調試技術

在Linux系統編程中&#xff0c;守護進程&#xff08;Daemon&#xff09;是非常重要的一種概念。它允許程序在后臺運行&#xff0c;不受用戶交互的影響&#xff0c;并且可以持續長時間地運行。通過了解如何創建和管理守護進程&#xff0c;我們能夠開發出更加穩定、高效的系統應用…

Linux中的管道

管道的概念 管道是一種進程間通信的方式。 管道是一種半雙工通信機制&#xff0c;數據只能讀或寫&#xff0c;如果要讀寫同時進行就要創建兩個管道 管道的類型 1、匿名管道PIPE&#xff1a;通常在親緣進程中使用&#xff08;兄弟、父子&#xff09; 函數參考&#xff1a;匿名管…

深度學習2.4 微積分

2.4.1 導數和微分 2.4.2 偏導數 ![在這里插入圖片描述](https://i-blog.csdnimg.cn/direct/17227e00adb14472902baba4da675aed.png 2.4.3 梯度 具體證明&#xff0c;矩陣-向量積

《軟件設計師》復習筆記(11.3)——需求獲取、分析、定義、驗證、管理

目錄 一、軟件需求概述 真題示例&#xff1a; 二、質量功能部署&#xff08;QFD&#xff09; 三、需求開發流程 需求獲取 需求分析 需求定義&#xff08;SRS&#xff09; 需求驗證 真題示例&#xff1a; 四、需求管理 真題示例&#xff1a; 一、軟件需求概述 軟件…

Spring Boot 依賴注入與Bean管理:JavaConfig如何取代XML?

大家好呀&#xff01;今天我們來聊一個超級實用的技術話題 —— Spring Boot 中的依賴注入和Bean管理&#xff0c;特別是JavaConfig是如何一步步取代XML配置的。我知道很多小伙伴一聽到"依賴注入"、"Bean管理"這些詞就頭大&#xff0c;別擔心&#xff01;我…

全志H5,NanopiKP1lus移植QT5.12記錄

移植步驟 機器環境下載QT5.12.0源碼安裝交叉編譯器修改qmake.conf文件配置編譯選項qt5的configure選項說明基本配置選項編譯器和鏈接器選項功能模塊配置第三方庫集成注意事項 配置過程報錯解決配置完成編譯過程報錯解決編譯完成將arm-qt文件夾傳送到開發板配置板子環境變量運行…

STM32單片機C語言

1、stdint.h簡介 stdint.h 是從 C99 中引進的一個標準 C 庫的文件 路徑&#xff1a;D:\MDK5.34\ARM\ARMCC\include 大家都統一使用一樣的標準&#xff0c;這樣方便移植 配置MDK支持C99 位操作 如何給寄存器某個值賦值 舉個例子&#xff1a;uint32_t temp 0; 宏定義 帶參…

【專題刷題】雙指針(四):最接近的三數之和,接雨水

&#x1f4dd;前言說明&#xff1a; 本專欄主要記錄本人的基礎算法學習以及LeetCode刷題記錄&#xff0c;按專題劃分每題主要記錄&#xff1a;&#xff08;1&#xff09;本人解法 本人屎山代碼&#xff1b;&#xff08;2&#xff09;優質解法 優質代碼&#xff1b;&#xff…

chili3d調試筆記3 加入c++ 大模型對話方法 cmakelists精讀

加入 #include <emscripten/bind.h> #include <emscripten/val.h> #include <nlohmann/json.hpp> 怎么加包 函數直接用emscripten::function&#xff0c;如&#xff1a; emscripten::function("send_to_llm", &send_to_llm); set (CMAKE_C…

[Redis]1-高效的數據結構P2-Set

按照慣例&#xff0c;先丟一個官網文檔鏈接。 上篇我們已經了解了高效的數據結構P1-String與Hash。 這篇&#xff0c;我們繼續來了解Redis的 Set 與 Sorted set。 目錄 有序集合 Sorted set底層實現 集合 Set總結資料引用 有序集合 Sorted set Redis 有序集合是一組唯一的字符…

Python + Playwright:使用正則表達式增強自動化測試

Python + Playwright:使用正則表達式增強自動化測試 前言一、 為什么選擇正則表達式?二、 Playwright 中集成正則表達式:途徑與方法三、 實戰應用:正則表達式解決典型測試難題場景 1:定位 ID 或 Class 包含動態部分的元素場景 2:驗證包含可變數字或文本的提示信息場景 3:…

VASP 6.4.1 Ubuntu系統編譯安裝手冊

VASP 6.4.1 Ubuntu系統編譯安裝手冊 &#xff08;基于Ubuntu 22.04 LTS&#xff0c;適用x86_64架構&#xff09; 文章目錄 VASP 6.4.1 Ubuntu系統編譯安裝手冊第一章 系統環境深度配置1.1 硬件兼容性驗證1.2 操作系統環境準備1.3 數學庫深度優化配置 第二章 編譯環境深度調優2…

uniapp h5接入地圖選點組件

uniapp h5接入地圖選點組件 1、申請騰訊地圖key2、代碼接入2.1入口頁面 &#xff08;pages/map/map&#xff09;templatescript 2.2選點頁面&#xff08;pages/map/mapselect/mapselect&#xff09;templatescript 該內容只針對uniapp 打包h5接入地圖選點組件做詳細說明&#x…

java輸出、輸入語句

先創建一個用于測試的java 編寫程序 #java.util使java標準庫的一個包&#xff0c;這里拉取Scanner類 import java.util.Scanner;public class VariableTest {public static void main(String[] args) {#創建一個 Scanner 對象Scanner scanner new Scanner(System.in);System.…

AI Agents系列之構建多智能體系統

&#x1f9e0; 向所有學習者致敬&#xff01; “學習不是裝滿一桶水&#xff0c;而是點燃一把火。” —— 葉芝 我的博客主頁&#xff1a; https://lizheng.blog.csdn.net &#x1f310; 歡迎點擊加入AI人工智能社區&#xff01; &#x1f680; 讓我們一起努力&#xff0c;共創…