【C語言】指針篇

目錄

  • C 語言指針概述
    • 指針的聲明和初始化
      • 聲明指針
      • 初始化指針
    • 指針的操作
      • 解引用操作
      • 指針算術運算
    • 指針的用途
      • 動態內存分配
      • 作為函數參數
  • 指針與數組
    • 數組名作為指針
    • 通過指針訪問數組元素
    • 指針算術和數組
    • 數組作為函數參數
    • 指針數組和數組指針
      • 指針數組
      • 數組指針
  • 函數指針
    • 函數指針的定義和聲明
    • 函數指針的初始化和使用
    • 函數指針作為函數參數(回調函數)
    • 函數指針數組
  • 動態內存分配
    • 概念
    • 動態內存分配函數
      • malloc 函數
      • calloc 函數
      • realloc 函數
      • free 函數
    • 示例代碼
    • 注意事項
  • 常見錯誤與規避
    • 內存泄漏(Memory Leak)
    • 空指針引用(Null Pointer Dereference)
    • 重復釋放內存(Double Free)
    • 越界訪問(Buffer Overflow)
    • realloc 使用不當

C 語言指針概述

在 C 語言中,指針是一個非常重要且強大的概念。它是一個變量,其值為另一個變量的地址,即內存位置的直接地址。可以把指針想象成一個特殊的變量,它存儲的不是普通的數據,而是內存中某個變量的地址。通過指針,我們可以直接訪問和操作該內存地址上存儲的數據。

指針的聲明和初始化

聲明指針

在 C 語言中,聲明指針的一般語法如下:

數據類型 *指針變量名;

其中,數據類型 表示該指針所指向的變量的數據類型,* 是指針聲明符,用于表明這是一個指針變量。例如:

int *p;  // 聲明一個指向整型變量的指針p
float *q; // 聲明一個指向浮點型變量的指針q

初始化指針

指針可以在聲明時進行初始化,也可以在聲明后再賦值。指針初始化時,需要將一個變量的地址賦給它。使用 & 運算符可以獲取變量的地址。示例如下:

#include <stdio.h>int main() {int num = 10;int *p = &num;  // 聲明并初始化指針p,使其指向變量numprintf("變量num的地址: %p\n", &num);printf("指針p存儲的地址: %p\n", p);return 0;
}

在上述代碼中,&num 表示變量 num 的地址,將其賦給指針 p,這樣 p 就指向了 num。

指針的操作

解引用操作

通過指針訪問其所指向的變量的值,需要使用 * 運算符,這稱為解引用操作。示例如下:

#include <stdio.h>int main() {int num = 10;int *p = &num;printf("變量num的值: %d\n", num);printf("通過指針p訪問num的值: %d\n", *p);*p = 20;  // 通過指針p修改num的值printf("修改后變量num的值: %d\n", num);return 0;
}

在上述代碼中,*p 表示指針 p 所指向的變量的值,通過 *p = 20; 可以修改 num 的值。

指針算術運算

指針可以進行一些算術運算,如加法、減法等。指針算術運算的結果取決于指針所指向的數據類型的大小。示例如下:

#include <stdio.h>int main() {int arr[5] = {1, 2, 3, 4, 5};int *p = arr;  // 指針p指向數組arr的首元素printf("p指向的元素的值: %d\n", *p);p++;  // 指針p向后移動一個位置printf("p移動后指向的元素的值: %d\n", *p);return 0;
}

在上述代碼中,p++ 使指針 p 向后移動一個 int 類型的位置,即移動了 sizeof(int) 個字節。

指針的用途

動態內存分配

C 語言提供了一些函數(如 malloc、calloc、realloc 等)用于動態分配內存,這些函數返回的是一個指針,通過指針可以訪問和管理動態分配的內存。示例如下:

#include <stdio.h>
#include <stdlib.h>int main() {int *p = (int *)malloc(sizeof(int));  // 動態分配一個int類型的內存空間if (p == NULL) {printf("內存分配失敗\n");return 1;}*p = 10;printf("動態分配內存中存儲的值: %d\n", *p);free(p);  // 釋放動態分配的內存return 0;
}

作為函數參數

指針可以作為函數參數,通過指針傳遞參數可以在函數內部修改實參的值。示例如下:

#include <stdio.h>void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}int main() {int x = 10, y = 20;printf("交換前: x = %d, y = %d\n", x, y);swap(&x, &y);printf("交換后: x = %d, y = %d\n", x, y);return 0;
}

在上述代碼中,swap 函數接受兩個指針作為參數,通過指針可以交換 x 和 y 的值。

指針與數組

在 C 語言中,指針和數組有著密切的聯系。

數組名作為指針

在 C 語言里,數組名在大多數表達式中會被隱式轉換為指向數組首元素的指針。也就是說,數組名代表了數組首元素的地址。
示例代碼:

#include <stdio.h>int main() {int arr[5] = {1, 2, 3, 4, 5};// 打印數組首元素的地址printf("數組首元素的地址(使用&arr[0]): %p\n", &arr[0]);// 打印數組名代表的地址printf("數組名代表的地址: %p\n", arr);return 0;
}

在上述代碼中,&arr[0] 是獲取數組 arr 首元素的地址,而 arr 本身在這個表達式中也被解釋為指向數組首元素的指針,所以它們的值是相同的。

通過指針訪問數組元素

由于數組名可以當作指針使用,因此可以借助指針來訪問數組中的元素。
示例代碼:

#include <stdio.h>int main() {int arr[5] = {1, 2, 3, 4, 5};int *p = arr;  // 指針p指向數組arr的首元素for (int i = 0; i < 5; i++) {// 通過指針訪問數組元素printf("arr[%d] = %d\n", i, *(p + i));}return 0;
}
  • int *p = arr;:將指針 p 指向數組 arr 的首元素。
  • *(p + i):p + i 表示指針 p 向后移動 i 個位置(每個位置的大小為 sizeof(int)),*(p + i) 則是對移動后的指針進行解引用操作,從而訪問對應位置的數組元素。

指針算術和數組

指針可以進行算術運算,這使得我們能更靈活地訪問數組元素。
示例代碼:

#include <stdio.h>int main() {int arr[5] = {1, 2, 3, 4, 5};int *p = arr;for (int i = 0; i < 5; i++) {// 先使用指針p指向的元素的值,然后指針p向后移動一個位置printf("%d ", *p++);}printf("\n");return 0;
}

*p++:由于 ++ 運算符的優先級高于 * 運算符,所以先取 p 所指向的元素的值,然后 p 向后移動一個位置(移動的字節數為 sizeof(int))。

數組作為函數參數

當數組作為函數參數傳遞時,實際上傳遞的是數組首元素的地址,也就是一個指針。
示例代碼:

#include <stdio.h>// 函數接受一個整型指針和數組的長度作為參數
void printArray(int *arr, int length) {for (int i = 0; i < length; i++) {printf("%d ", arr[i]);}printf("\n");
}int main() {int arr[5] = {1, 2, 3, 4, 5};// 調用函數并傳遞數組名和數組長度printArray(arr, 5);return 0;
}
  • void printArray(int *arr, int length):函數 printArray 的第一個參數是一個整型指針,它接收數組首元素的地址。
  • printArray(arr, 5);:在調用 printArray 函數時,傳遞的 arr 被隱式轉換為指向數組首元素的指針。

指針數組和數組指針

指針數組

指針數組是一個數組,數組中的每個元素都是一個指針。
示例代碼:

#include <stdio.h>int main() {int a = 1, b = 2, c = 3;// 定義一個指針數組int *ptrArr[3] = {&a, &b, &c};for (int i = 0; i < 3; i++) {printf("%d ", *ptrArr[i]);}printf("\n");return 0;
}

int *ptrArr[3] 定義了一個包含 3 個元素的指針數組,每個元素都是一個指向 int 類型的指針。

數組指針

數組指針是一個指針,它指向一個數組。
示例代碼:

#include <stdio.h>int main() {int arr[5] = {1, 2, 3, 4, 5};// 定義一個數組指針int (*p)[5] = &arr;for (int i = 0; i < 5; i++) {printf("%d ", (*p)[i]);}printf("\n");return 0;
}

int (*p)[5] 定義了一個數組指針 p,它指向一個包含 5 個 int 類型元素的數組。&arr 是數組 arr 的地址,將其賦值給 p,(*p)[i] 用于訪問數組中的元素。

函數指針

在 C 語言中,函數指針是一種特殊的指針,它指向的是函數而非普通的變量。函數指針在很多場景下都非常有用,比如實現回調函數、創建函數表等。

函數指針的定義和聲明

函數指針的聲明需要指定函數的返回類型和參數列表,其一般語法形式如下:

返回類型 (*指針變量名)(參數列表);
  • 返回類型:表示該指針所指向的函數的返回值類型。
  • 指針變量名:是函數指針的名稱。
  • 參數列表:指定該指針所指向的函數的參數類型和數量。

以下是一個簡單的函數指針聲明示例:

#include <stdio.h>// 聲明一個函數指針,指向返回值為int,接受兩個int類型參數的函數
int (*funcPtr)(int, int);

函數指針的初始化和使用

函數指針需要被初始化為指向一個具體的函數,在使用時可以通過該指針調用所指向的函數。
示例代碼:

#include <stdio.h>// 定義一個加法函數
int add(int a, int b) {return a + b;
}int main() {// 聲明一個函數指針,并初始化為指向add函數int (*funcPtr)(int, int) = add;// 使用函數指針調用add函數int result = funcPtr(3, 5);printf("3 + 5 = %d\n", result);return 0;
}
  • 函數定義:add 函數接受兩個 int 類型的參數,并返回它們的和。
  • 函數指針聲明和初始化:int (*funcPtr)(int, int) = add; 聲明了一個函數指針 funcPtr,并將其初始化為指向 add 函數。這里 add 是函數名,在這種上下文中,它會被隱式轉換為指向該函數的指針。
  • 通過函數指針調用函數:funcPtr(3, 5); 就像直接調用 add 函數一樣,通過函數指針 funcPtr 調用了 add 函數。

函數指針作為函數參數(回調函數)

函數指針的一個重要應用是實現回調函數。回調函數是指在某個事件發生時或某個特定條件滿足時被調用的函數,通常將回調函數的指針作為參數傳遞給另一個函數。
示例代碼:

#include <stdio.h>// 定義一個回調函數類型
typedef int (*Callback)(int, int);// 定義一個加法函數
int add(int a, int b) {return a + b;
}// 定義一個減法函數
int subtract(int a, int b) {return a - b;
}// 執行操作的函數,接受一個回調函數指針作為參數
int performOperation(int a, int b, Callback operation) {return operation(a, b);
}int main() {int num1 = 10, num2 = 5;// 使用加法函數進行操作int sum = performOperation(num1, num2, add);printf("%d + %d = %d\n", num1, num2, sum);// 使用減法函數進行操作int difference = performOperation(num1, num2, subtract);printf("%d - %d = %d\n", num1, num2, difference);return 0;
}
  • 定義回調函數類型:typedef int (*Callback)(int, int); 使用 typedef 定義了一個函數指針類型 Callback,它指向返回值為 int,接受兩個 int 類型參數的函數。
  • 定義具體的操作函數:add 和 subtract 分別實現了加法和減法功能。
  • 執行操作的函數:performOperation 函數接受兩個 int 類型的參數和一個 Callback 類型的函數指針,在函數內部通過該指針調用相應的函數。
  • 在 main 函數中使用:分別將 add 和 subtract 函數作為參數傳遞給 performOperation 函數,實現不同的操作。

函數指針數組

函數指針數組是一個數組,數組中的每個元素都是一個函數指針。它可以用于根據不同的條件選擇調用不同的函數。
示例代碼:

#include <stdio.h>// 定義一個加法函數
int add(int a, int b) {return a + b;
}// 定義一個減法函數
int subtract(int a, int b) {return a - b;
}int main() {// 定義一個函數指針數組int (*funcArray[2])(int, int) = {add, subtract};int num1 = 10, num2 = 5;// 調用加法函數int sum = funcArray[0](num1, num2);printf("%d + %d = %d\n", num1, num2, sum);// 調用減法函數int difference = funcArray[1](num1, num2);printf("%d - %d = %d\n", num1, num2, difference);return 0;
}
  • int (*funcArray[2])(int, int) = {add, subtract}; 定義了一個包含兩個元素的函數指針數組 funcArray,分別指向 add 和 subtract 函數。
  • 通過數組下標可以選擇調用不同的函數。

動態內存分配

在 C 語言中,動態內存分配是一項重要的特性,它允許程序在運行時根據需要分配和釋放內存,而不是在編譯時就確定固定大小的內存。

概念

在程序運行過程中,有些情況下我們無法提前確定所需內存的大小,例如需要存儲用戶輸入的一組數據,但不知道用戶會輸入多少個元素。這時就需要使用動態內存分配,在程序運行時根據實際需求來分配適當大小的內存空間。動態分配的內存位于堆(heap)上,與棧(stack)上的自動變量內存分配方式不同。

動態內存分配函數

C 語言標準庫提供了幾個用于動態內存分配的函數,主要包括 malloc、calloc、realloc 和 free。

malloc 函數

功能:malloc 函數用于分配指定字節數的連續內存空間,并返回一個指向該內存空間起始地址的指針。如果分配失敗,返回 NULL。
原型:

void* malloc(size_t size);
  • 參數:size 表示需要分配的內存字節數。
  • 返回值:返回一個 void* 類型的指針,指向分配的內存空間的起始地址。

calloc 函數

功能:calloc 函數用于分配指定數量和大小的連續內存空間,并將分配的內存初始化為零。如果分配失敗,返回 NULL。
原型:

void* calloc(size_t num, size_t size);
  • 參數:num 表示需要分配的元素數量,size 表示每個元素的字節數。
  • 返回值:返回一個 void* 類型的指針,指向分配的內存空間的起始地址。

realloc 函數

功能:realloc 函數用于重新調整之前分配的內存空間的大小。可以擴大或縮小已分配的內存塊。如果分配失敗,返回 NULL,原內存塊內容保持不變。
原型:

void* realloc(void* ptr, size_t size);
  • 參數:ptr 是之前通過 malloc、calloc 或 realloc 分配的內存塊的指針,size 是重新分配后的內存塊大小。
  • 返回值:返回一個 void* 類型的指針,指向重新分配后的內存空間的起始地址。如果 ptr 為 NULL,則相當于調用 malloc(size);如果 size 為 0,則相當于調用 free(ptr)。

free 函數

功能:free 函數用于釋放之前通過 malloc、calloc 或 realloc 分配的內存空間,將其返回給系統,以便其他程序或代碼段可以使用。
原型:

void free(void* ptr);
  • 參數:ptr 是之前分配的內存塊的指針。
  • 返回值:無。

示例代碼

下面是使用這些函數進行動態內存分配的示例:

#include <stdio.h>
#include <stdlib.h>int main() {// 使用 malloc 分配內存int *arr1 = (int *)malloc(5 * sizeof(int));if (arr1 == NULL) {printf("內存分配失敗\n");return 1;}for (int i = 0; i < 5; i++) {arr1[i] = i;}printf("使用 malloc 分配的數組元素: ");for (int i = 0; i < 5; i++) {printf("%d ", arr1[i]);}printf("\n");// 使用 calloc 分配內存int *arr2 = (int *)calloc(5, sizeof(int));if (arr2 == NULL) {printf("內存分配失敗\n");free(arr1);return 1;}printf("使用 calloc 分配的數組元素(初始化為 0): ");for (int i = 0; i < 5; i++) {printf("%d ", arr2[i]);}printf("\n");// 使用 realloc 調整內存大小int *arr3 = (int *)realloc(arr1, 10 * sizeof(int));if (arr3 == NULL) {printf("內存重新分配失敗\n");free(arr1);free(arr2);return 1;}arr1 = arr3;  // 更新指針for (int i = 5; i < 10; i++) {arr1[i] = i;}printf("使用 realloc 調整大小后的數組元素: ");for (int i = 0; i < 10; i++) {printf("%d ", arr1[i]);}printf("\n");// 釋放內存free(arr1);free(arr2);return 0;
}

注意事項

  • 內存泄漏:如果動態分配的內存不再使用,但沒有調用 free 函數釋放,就會導致內存泄漏。這會使程序占用的內存不斷增加,最終可能導致系統資源耗盡。
  • 空指針檢查:在使用 malloc、calloc 或 realloc 分配內存后,應該檢查返回的指針是否為 NULL,以確保內存分配成功。
  • 避免重復釋放:不要對已經釋放的內存再次調用 free 函數,這會導致未定義行為。
  • 指針更新:在使用 realloc 函數重新分配內存時,如果返回的指針與原指針不同,需要更新原指針,以避免使用無效的指針。

常見錯誤與規避

在使用 C 語言進行動態內存分配時,會遇到一些常見的錯誤,以下為你詳細介紹這些錯誤以及相應的規避方法。

內存泄漏(Memory Leak)

錯誤描述
內存泄漏指的是程序在動態分配內存后,由于某些原因未能釋放這些內存,導致系統中可用內存逐漸減少。隨著程序的運行,內存泄漏會不斷累積,最終可能導致系統資源耗盡,程序崩潰或系統運行緩慢。
示例代碼:

#include <stdio.h>
#include <stdlib.h>int main() {int *ptr = (int *)malloc(10 * sizeof(int));// 忘記釋放內存return 0;
}

規避方法:

  • 確保每一次 malloc、calloc 或 realloc 調用都有對應的 free 調用:在使用完動態分配的內存后,及時調用 free 函數釋放內存。
  • 使用結構化的代碼:可以將內存分配和釋放操作封裝在函數中,確保在函數結束時釋放內存。例如:
#include <stdio.h>
#include <stdlib.h>void process() {int *ptr = (int *)malloc(10 * sizeof(int));if (ptr == NULL) {printf("內存分配失敗\n");return;}// 使用內存// ...free(ptr); // 釋放內存
}int main() {process();return 0;
}

空指針引用(Null Pointer Dereference)

錯誤描述
當對一個值為 NULL 的指針進行解引用操作時,會發生空指針引用錯誤。這是因為 NULL 指針不指向任何有效的內存地址,對其進行解引用會導致未定義行為,通常會使程序崩潰。
示例代碼:

#include <stdio.h>
#include <stdlib.h>int main() {int *ptr = (int *)malloc(10 * sizeof(int));if (ptr == NULL) {// 沒有檢查指針是否為 NULL 就進行解引用*ptr = 5; }free(ptr);return 0;
}

規避方法:
在使用指針之前檢查其是否為 NULL:在進行動態內存分配后,立即檢查返回的指針是否為 NULL,如果是則進行相應的錯誤處理。例如:

#include <stdio.h>
#include <stdlib.h>int main() {int *ptr = (int *)malloc(10 * sizeof(int));if (ptr == NULL) {printf("內存分配失敗\n");return 1;}*ptr = 5; // 確保指針不為 NULL 后再進行解引用free(ptr);return 0;
}

重復釋放內存(Double Free)

錯誤描述
重復釋放內存是指對同一塊已經釋放的內存再次調用 free 函數。這會導致未定義行為,可能會破壞內存管理系統的數據結構,使程序崩潰或產生不可預測的結果。
示例代碼:

#include <stdio.h>
#include <stdlib.h>int main() {int *ptr = (int *)malloc(10 * sizeof(int));free(ptr);// 重復釋放內存free(ptr); return 0;
}

規避方法:
在釋放內存后將指針置為 NULL:在調用 free 函數釋放內存后,將指針賦值為 NULL。這樣,即使后續不小心再次調用 free 函數,也不會產生問題,因為 free(NULL) 是安全的操作。例如:

#include <stdio.h>
#include <stdlib.h>int main() {int *ptr = (int *)malloc(10 * sizeof(int));if (ptr == NULL) {printf("內存分配失敗\n");return 1;}free(ptr);ptr = NULL; // 將指針置為 NULL// 再次調用 free 不會有問題free(ptr); return 0;
}

越界訪問(Buffer Overflow)

錯誤描述
越界訪問是指程序訪問了動態分配的內存塊之外的內存區域。這可能會覆蓋其他重要的數據,導致程序崩潰或產生不可預期的結果,甚至可能引發安全漏洞。
示例代碼:

#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;}free(ptr);return 0;
}

規避方法:
確保訪問的內存位置在分配的內存塊范圍內:在訪問動態分配的內存時,要嚴格控制訪問的邊界,避免越界。可以使用循環控制變量和數組長度來確保不會越界。例如:

#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;}free(ptr);return 0;
}

realloc 使用不當

錯誤描述
在使用 realloc 函數時,如果處理不當,可能會導致內存泄漏或其他問題。例如,realloc 調用失敗時沒有妥善處理原指針,或者沒有更新指針導致使用了無效的指針。
示例代碼:

#include <stdio.h>
#include <stdlib.h>int main() {int *ptr = (int *)malloc(5 * sizeof(int));if (ptr == NULL) {printf("內存分配失敗\n");return 1;}// realloc 調用失敗時沒有處理原指針ptr = (int *)realloc(ptr, 10 * sizeof(int)); if (ptr == NULL) {// 此時原內存已丟失,造成內存泄漏printf("內存重新分配失敗\n");return 1;}free(ptr);return 0;
}

規避方法:
使用臨時指針處理 realloc 的返回值:在調用 realloc 時,先將返回值賦給一個臨時指針,檢查臨時指針是否為 NULL,如果不為 NULL 再更新原指針。例如:

#include <stdio.h>
#include <stdlib.h>int main() {int *ptr = (int *)malloc(5 * sizeof(int));if (ptr == NULL) {printf("內存分配失敗\n");return 1;}int *temp = (int *)realloc(ptr, 10 * sizeof(int));if (temp == NULL) {// 原內存仍然有效printf("內存重新分配失敗\n");free(ptr);return 1;}ptr = temp; // 更新指針free(ptr);return 0;
}

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

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

相關文章

嵌入式音視頻通話SDK組件EasyRTC:全平臺設備兼容,智能硬件里的WebRTC調用實踐

在萬物互聯時代&#xff0c;智能硬件設備對實時音視頻通信的需求呈現爆發式增長。傳統基于PC或移動端的WebRTC方案難以滿足嵌入式設備在資源占用、低延遲傳輸和硬件適配等方面的特殊需求。本文將深入探討如何通過EasyRTC嵌入式音視頻通信SDK在嵌入式設備中實現高效的WebRTC視頻…

Aim Robotics電動膠槍:機器人涂膠點膠的高效解決方案

在自動化和智能制造領域&#xff0c;機器人技術的應用越來越廣泛&#xff0c;而涂膠和點膠作為生產過程中的重要環節&#xff0c;也逐漸實現了自動化和智能化。Aim Robotics作為一家專注于機器人技術的公司&#xff0c;其推出的電動膠槍為這一領域帶來了高效、靈活且易于操作的…

c語言筆記 數組進階題目的理解

題目&#xff1a;聲明一個二維 int 型數組 a&#xff0c;再聲明另一個一維數組指針數組 b&#xff0c;使該數組 b 的每一個指針分別指向二維數組 a 中的每一個元素(即每一個一維數組)&#xff0c;然后利用數組 b 計算數組 a 的和。 圖解&#xff1a;畫圖幫助理解 我們要清楚什…

Photo Works在線圖片編輯器:一鍵修復老照片,輕松煥新記憶

★【概況介紹】 今天突然收到我的朋友電腦出故障了,截圖給我,我一看就知道這個是缺少必要的組件引起的故障。結合這個問題,我來談談自己的解決思路和方法,希望能夠幫助到大家。幫助大家是我最開心的事情。以前只是幫朋友解決問題,沒有記錄下來,剛剛接觸到這個平臺,剛好可…

FANformer:融合傅里葉分析網絡的大語言模型基礎架構

近期大語言模型(LLM)的基準測試結果引發了對現有架構擴展性的思考。盡管OpenAI推出的GPT-4.5被定位為其最強大的聊天模型&#xff0c;但在多項關鍵基準測試上的表現卻不及某些規模較小的模型。DeepSeek-V3在AIME 2024評測中達到了39.2%的Pass1準確率&#xff0c;在SWE-bench Ve…

【 IEEE出版 | 快速穩定EI檢索 | 往屆已EI檢索】2025年儲能及能源轉換國際學術會議(ESEC 2025)

重要信息 主會官網&#xff1a;www.net-lc.net 【論文【】投稿】 會議時間&#xff1a;2025年5月9-11日 會議地點&#xff1a;中國-杭州 截稿時間&#xff1a;見官網 提交檢索&#xff1a;IEEE Xplore, EI Compendex, Scopus 主會NET-LC 2025已進入IEEE 會議官方列表!&am…

藍橋杯練題順序

有重復,適當選擇題目~共229道題&#xff01; 后續會發題解~ STL&#xff1a;9 3100 反轉字符串 [string簡單]---3100 -CSDN博客 2470 單調棧 [stack簡單]---2470 單調棧 [stack簡單]-CSDN博客 2254 括號匹配&#xff01; [stack簡單]---2254: 括號匹配&#xff01;-CSDN博客 …

react基礎語法視圖層類組件

react基礎語法視圖層&類組件 MVVM *區別mvc&mvvm 兩者的區別&#xff1a; 數據模型去渲染視圖。數據層改了&#xff0c;vue自己會監聽到幫我們拿最新的數據去渲染視圖&#xff1b;構建數據構建視圖&#xff0c;數據驅動的思想。這一套是非常相似的。 視圖中的內容改變&…

開發、科研、日常辦公工具匯總(自用,持續更新)

主要記錄匯總一下自己平常會用到的網站工具&#xff0c;方便查閱。 update&#xff1a;2025/2/11&#xff08;開發網站補一下&#xff09; update&#xff1a;2025/2/21&#xff08;補充一些AI工具&#xff0c;剛好在做AI視頻相關工作&#xff09; update&#xff1a;2025/3/7…

requests中post中data=None, json=None兩個參數區別

在 requests.post() 方法中&#xff0c;data 和 json 主要用于發送請求體&#xff0c;但它們的作用和格式有所不同。 1. data 參數 用途&#xff1a;用于發送表單數據或原始二進制數據。格式&#xff1a; 可以是 字典&#xff08;dict&#xff09;&#xff08;默認會編碼為 a…

51c大模型~合集10

我自己的原文哦~ https://blog.51cto.com/whaosoft/11547799 #Llama 3.1 美國太平洋時間 7 月 23 日&#xff0c;Meta 公司發布了其最新的 AI 模型 Llama 3.1&#xff0c;這是一個里程碑時刻。Llama 3.1 的發布讓我們看到了開源 LLM 有與閉源 LLM 一較高下的能力。 Meta …

架構演變 之 超市進化

1. 單機架構 → 小賣部&#xff08;夫妻店&#xff09; 場景&#xff1a;一個老板包攬所有工作——進貨、擺貨、收銀、打掃&#xff0c;店里只有一個小倉庫。對應架構&#xff1a;所有功能&#xff08;數據庫、業務邏輯、頁面&#xff09;都擠在一臺服務器上。問題&#xff1a…

ubuntu 和 RV1126 交叉編譯Mosqutiio-1.6.9

最近需要交叉編譯mosquitto&#xff0c;遇到一些小問題記錄一下。 1.眾所周知使用它自帶的Makefile編譯的時候&#xff0c;只需要在編譯前&#xff0c;指定它config.mk中的變量&#xff1a;CFLAGS頭文件路徑 和 LDFLAGS庫文件路徑就ok&#xff0c;例子如下&#xff1a; expor…

Photoshop 中如何快速摳圖?

Photoshop 中如何快速摳圖&#xff1f; 摳圖是 Photoshop 中的常見操作&#xff0c;無論是去除背景還是提取特定對象&#xff0c;都需要掌握高效的摳圖技巧。本文將介紹幾種快速摳圖的方法&#xff0c;幫助你輕松完成設計任務。 1. 快速選擇工具&#xff08;Quick Selection T…

解決 React 中的 Hydration Failed 錯誤

解決 React 中的 Hydration Failed 錯誤 React 的 服務器端渲染&#xff08;SSR&#xff09;通過在服務器端生成 HTML 并將其發送給客戶端&#xff0c;幫助提高頁面加載速度和搜索引擎優化&#xff08;SEO&#xff09;。然而&#xff0c;在進行 SSR 后&#xff0c;React 需要進…

如何使用postman來測試接口

一、postman的介紹與下載 可參考&#xff1a; https://blog.csdn.net/freeking101/article/details/80774271 二、api獲取網站 阿里云API應用市場 地址&#xff1a;云市場_鏡像市場_軟件商店_建站軟件_服務器軟件_API接口_應用市場 - 阿里云 三、具體測試過程 可模擬瀏覽…

數據庫系統概論(二)數據模型

數據庫系統概論&#xff08;二&#xff09;數據模型 數據庫系統概論&#xff08;二&#xff09;數據模型前言一、數據建模二、概念模型三、數據模型的三要素四、層次模型五、網狀模型六、關系模型 總結&#xff08;核心概念速記&#xff09;&#xff1a; 數據庫系統概論&#x…

清華同方國產電腦能改windows嗎_清華同方國產系統改win7教程

清華同方國產電腦能改windows嗎&#xff1f;清華同方國產電腦如果采用的是兆芯kx-6000系列或kx-7000系列以及海光c86 3250 3350 X86架構處理器可以安裝windows。在安裝win7時bios中要關閉“安全啟動”和開啟legacy傳統模式支持&#xff0c;如果是NVME接口的固態硬盤&#xff0c…

安卓Android與iOS設備管理對比:企業選擇指南

目錄 一、管理方式差異 Android Enterprise方案包含三種典型模式&#xff1a; Apple MDM方案主要提供兩種模式&#xff1a; 二、安全防護能力 Android系統特點&#xff1a; 三、應用管理方案 四、設備選擇建議 五、典型場景推薦 需求場景 推薦方案 六、決策建議要點…

再聊 Flutter Riverpod ,注解模式下的 Riverpod 有什么特別之處,還有發展方向

三年前我們通過 《Flutter Riverpod 全面深入解析》 深入理解了 riverpod 的內部實現&#xff0c;而時隔三年之后&#xff0c;如今Riverpod 的主流模式已經是注解&#xff0c;那今天就讓我們來聊聊 riverpod 的注解有什么特殊之處。 前言 在此之前&#xff0c;我們需要先回憶…