《C 語言指針高級指南:字符、數組、函數指針的進階攻略》

目錄

一. 字符指針變量

二. 數組指針變量

三. 二維數組傳參

3.1 二維數組的本質

3.2 訪問方式與地址計算

3.3 二維數組的傳參方式

3.4 深入解析?*(*(arr+i)+j)?與?arr[i][j]?的等價性

四. 函數指針變量

4.1 函數指針變量的創建

4.2 函數指針變量的使用

4.3 兩段"有趣"代碼的講解

4.3.1 解析?(*(void(*)())0)();

4.3.2?解析void(* signal(int, void(*)(int)))(int);

4.4?typedef關鍵字講解

4.4.1 基本語法

4.4.2?常見用法

4.4.3?結合?typedef?解析?signal?函數

4.4.4?typedef?的優點

4.4.5?總結

五. 函數指針數組

5.1 基本概念

5.2 詳細用法

5.3 實際應用示例

六. 轉移表


一. 字符指針變量

什么是字符指針變量呢?

字符指針變量是指向字符類型數據的指針,在C/C++中通常用于處理字符和字符串和字符數組。

例如以下代碼? 處理字符

int main()
{char ch = 'w';char* pc = &ch;  ///字符指針變量return 0;
}

pc存放的是字符w的地址

例如以下代碼? 處理字符串

int main()
{const char* pc = "Hello, World!";//常量字符串 不可被修改printf(" %c\n", *pc);printf(" %s", pc); //注意: 打印字符串的時候 需要的參數是字符串的起始地址return 0;
}

pc存放的是首字符H的地址? 打印驗證結果如下

注意: 打印字符串的時候 需要的參數是字符串的起始地址

注意:pc此時指向的是常量字符串 即*pc現在是一個左值 無法被修改

由于*pc現在是一個左值 無法被修改 使用我們使用const來修飾它

例如以下代碼? 處理字符數組

int main()
{char arr[] = "ABCDE";char* pc = arr;printf(" %c\n", *pc);printf(" %s", pc); //注意: 打印字符串的時候 需要的參數是字符串的起始地址return 0;
}

pc存放的是數組第一個元素a的地址 同理 運行結果如下

注意:pc此時指向的是數組? 與指向字符串的區別是*pc現在可以被修改

現在讓我們來認真閱讀以下代碼 運行結果會是什么呢?

int main()
{char str1[] = "Hello world";char str2[] = "Hello world";const char* str3 = "Hello world";const char* str4 = "Hello world";if (str1 == str2)printf("str1=str2\n");elseprintf("str1!=str2\n");if (str3 == str4)printf("str3=str4\n");elseprintf("str3!=str4\n");return 0;
}

運行結果如下

可以看出str1與str2不相等 而str3和str4卻相等 這是為什么呢??

原因分析:

  1. str1?和?str2?的比較 (str1 == str2)

    • str1?和?str2?是兩個獨立的字符數組,分別存儲?"Hello world"
    • 數組名在比較時會被轉換為指向數組首元素的指針(即?&str1[0]?和?&str2[0])。
    • 由于?str1?和?str2?是兩個不同的數組,它們的地址不同,所以?str1 == str2?為?false,輸出?str1!=str2
  2. str3?和?str4?的比較 (str3 == str4)

    • str3?和?str4?是指向字符串常量的指針,且它們的值都是?"Hello world"
    • 編譯器會對相同的字符串常量進行優化(稱為?字符串池化,String Interning),即多個相同的字符串常量在內存中只存儲一份。
    • 因此,str3?和?str4?實際上指向同一個內存地址,所以?str3 == str4?為?true,輸出?str3=str4

關鍵區別:

  • 字符數組 (char[]) 會分配獨立的內存空間,即使內容相同,地址也不同。
  • 字符串常量 (const char*) 可能被優化為共享同一內存,因此相同內容的字符串常量可能指向同一地址。

而如果想比較字符串的內容是否相同,應該使用?strcmp?函數,而不是直接比較指針:

if (strcmp(str1, str2) == 0)  // 比較內容是否相同printf("str1 和 str2 內容相同\n");
elseprintf("str1 和 str2 內容不同\n");

strcmp函數簡要功能如下?

具體了解請訪問strcmp - C++ Reference

二. 數組指針變量

在學習數組指針前 讓我們來回顧一下 字符指針 整型指針

字符指針: char* p? ?----指向字符的指針 存放的是字符的地址 char *p=&ch;

整形指針: int* p? ? ? ----指向整型的指針 存放的是整形的地址? int a=10;? p=&a;

數組指針:? ? ? ? ? ? ? ?----指向數組的指針? 存放的是數組的地址

即數組指針變量是指向數組的指針,且在C/C++中用于處理多維數組和動態數組操作。

而數組的地址我們也曾經遇見過 同學們不妨通過以下代碼回想一下

int main()
{int arr[10] = { 0 };arr;  //首元素的地址&arr[0];&arr;//取出的是整個數組的地址---數組的地址return 0;
}

相信已經有同學分不清了? 現在讓我們來區別一下指針數組和數組指針

特性數組指針?(int (*p)[N])指針數組?(int *p[N])
本質一個指針,指向整個數組一個數組,元素全是指針
聲明方式int (*p)[5];int *p[5];
內存占用指針大小(通常8字節)N個指針的大小(如5個指針=40字節)
存儲內容存儲數組的首地址存儲多個指針(地址)
典型用途處理二維數組存儲多個字符串/動態數組
sizeof結果sizeof(p)=指針大小sizeof(p)=N×指針大小

直觀理解:

數組指針?→?指向數組的指針

int arr[3][4];
int (*p)[4] = arr;  // p指向arr的第一行(一個包含4個int的數組)
  • p+1會跳過整個子數組(移動4*sizeof(int)字節)

指針數組?→?存放指針的數組

char *strs[3] = {"Hello", "World", "!"};
  • strs[1]返回第二個字符串的地址("World"的首地址)

關鍵區別:?

操作數組指針?(int (*p)[4])指針數組?(int *p[4])
定義指向int[4]的指針包含4個int*的數組
p+1的偏移量16字節(假設int=4字節)8字節(指針大小)

記憶口訣

星號括起來是指針,星號不括是數組

  • int (*p)[N]?→ 星號被括號括住,強調是指針
  • int *p[N]?→ 星號沒被括,強調是數組

如何使用數組指針來打印數組里的值呢? 如下

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{int arr[] = {1,2,3,4,5,6,7,8,9};int (*p)[9] = arr;//(*p)得到arr的地址 [i]表示調用arr里的第幾個元素for (int i = 0;i < 9;i++){printf("%d  ", (*p)[i]);}
}

但這種寫法似乎更加復雜了 并沒有什么優勢

但其實我們并不會在這種情況使用數組指針 下面讓我們繼續深入學習

三. 二維數組傳參

3.1 二維數組的本質

二維數組是?“數組的數組”,在內存中仍然是連續存儲的線性結構。例如:

int arr[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}
};

內存布局:

[1][2][3][4]  [5][6][7][8]  [9][10][11][12]
  • 每行?arr[i]?是一個一維數組,類型是?int[4]
  • arr?本身是?“指向int[4]的指針”(即?int (*)[4]

3.2 訪問方式與地址計算

  • arr[i][j]?的地址&arr[0][0] + i * 4 + j
    (假設?int?占4字節,4是列數)
  • 行指針?arr[i]:等價于?*(arr + i)
  • 元素?arr[i][j]:等價于?*(*(arr + i) + j)

3.3 二維數組的傳參方式

(1) 標準方式(必須指定列數)

void print(int arr[][4], int rows){for(int i=0; i<rows; i++){for(int j=0; j<4; j++){printf("%d ", arr[i][j]);}printf("\n");}
}

本質arr[][4]?會被編譯器轉換為?int (*)[4]

(2) 數組指針方式

void print(int (*arr)[4], int rows) {// 與上述代碼完全等價
}

關鍵點

  • arr+1?會跳過?16字節(4個int
  • 必須指定列數,否則無法計算步長

(3) 錯誤方式

void print(int **arr, int rows, int cols) { // 錯誤!靜態二維數組不是二級指針
}

下面讓我們具體運行來觀察一下二維數組傳參

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
text(int(*arr)[5], int r,int c)
{for (int i = 0;i < r;i++){for (int j = 0;j< c;j++){printf("%d  ", *(*(arr + i)+j));}}
}
int main()
{int arr[3][5] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};text(arr, 3, 5);return 0;
}

注意:

*(arr+i) = arr[i] 因為二維數組的數組名表示第一行的地址? +i表示跳過 i 行? 并且*(*(arr+i)+j) = arr[ i ][ j?]??

二維數組傳參本質上也是傳遞了地址 傳遞的是第一行這個一維數組的地址?

3.4 深入解析?*(*(arr+i)+j)?與?arr[i][j]?的等價性

1. 關鍵概念拆解

表達式類型含義
arrint (*)[3]指向第一行({1,2,3})的指針
arr + iint (*)[3]指向第i行的指針
*(arr + i)int *第i行的首元素地址(退化成一維)
*(arr+i) + jint *第i行第j個元素的地址
*(*(arr+i)+j)int第i行第j個元素的值

2. 與下標訪問的對應關系

arr[i][j]  ≡  *(*(arr + i) + j)

編譯器實際處理
所有?arr[i][j]?最終都會被轉換為指針運算形式。

3. 為什么需要列數?

  • arr + i?的步長取決于列數(sizeof(int[N])
  • 若未指定列數(如?int arr[][]),編譯器無法計算?arr + i?的偏移量

4. 典型考題示例

題目:以下代碼輸出什么?

int arr[2][3] = {{1,2,3}, {4,5,6}};
printf("%d\n", *(*(arr + 1) + 2));

答案6
解析
*(arr + 1)?指向第二行?{4,5,6}*(arr + 1) + 2?指向?6,解引用后得到值?6

掌握這個核心等價關系,就能徹底理解二維數組的指針運算! 🎯

四. 函數指針變量

4.1 函數指針變量的創建

讓我們回憶一下之前的指針內容

字符指針: 存放的是字符的地址 指向的就是字符變量

整型指針: 存放的是整型的地址 指向的是整行變量

數組指針: 存放的是數組的地址 指向的是數組

函數指針: 存放的是函數的地址 指向的是函數

那函數的地址怎么得到的呢?

我們知道數組的地址是通過&+數組名得到的 那函數的地址是通過&+函數名得到的嗎?

答案是 是的 函數的地址就是通過&+函數名獲得

可以看到 地區打印了函數的地址

那函數和數組一樣嗎? 數組名代表了數組首元素的地址? 那函數名代表什么呢? 讓我們來試試

可以看到 打印出來的一模一樣 那函數名是首函數的地址嗎?? 顯然沒有這個說法?

他們倆所得到的都是函數的地址 并沒有什么區別?

那什么是函數指針變量呢?

函數指針變量是一個指向函數的指針,它存儲了函數的地址,可以通過該指針間接調用函數。函數指針的類型由函數的返回類型參數列表決定。

1. 函數指針的聲明

函數指針的聲明語法如下:

返回類型 (*指針變量名)(參數類型1, 參數類型2, ...);

示例

#define _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int Add(int x, int y)
{return x + y;
}
int main()
{int(*pf)(int,int) = &Add;//pf就是函數指針變量return 0;
}

那存放下面這個函數的函數指針變量該如何寫呢?

int* text(int n, char* p)
{}

通過類比 不難寫出

int* (*pf)(int, char*)=&text;//pf就是函數指針變量

4.2 函數指針變量的使用

我們知道通過解引用操作符 可以通過地址來找到存放的變量 那解引用函數指針變量是否就可以使用函數了呢?? 答案是 是的 例子如下

可以看到 我通過*pf 實現了對函數的調用 并且傳入參數( 3 , 5 )用r來接受 因為函數返回值是int類型 所以r也是int類型

其次 我們知道我們可以通過函數名來調用函數 即Add( 3 , 5 ) 那函數指針變量存放的又是函數名

那我們是否可以直接通過函數指針變量來使用函數呢?? 不妨讓我們試試

可以看到 無論是函數名調用 還是函數指針變量調用? 還是解引用函數指針變量調用 都可以實現對函數的使用

4.3 兩段"有趣"代碼的講解

那讓我們來思考思考下面這段代碼的含義是什么呢?

(*(void(*)())0)();

相信大家看了之后都會感覺 渾身不自在吧 現在讓我們一起來解讀一下這段代碼

4.3.1 解析?(*(void(*)())0)();

這個表達式看起來復雜,但它實際上是一個?函數指針強制轉換 + 調用?的典型例子。我們可以一步步拆解它的含義。


1. 表達式拆解

(*(void(*)())0)();

可以分解為:

  1. (void(*)())0:將?0?強制轉換為一個?函數指針
  2. *(void(*)())0解引用?這個函數指針,得到函數本身。
  3. (*(void(*)())0)();調用?這個函數。

2. 詳細分析

(1)?void(*)()?是什么?

  • void(*)()?是一個?函數指針類型,表示:
    • 返回類型:void(無返回值)
    • 參數列表:()(無參數)
  • 所以,void(*)()?是一個?指向無參無返回值函數的指針

(2)?(void(*)())0:將?0?強制轉換為函數指針

  • 0?是一個整數,代表?內存地址?0x0(NULL 指針)。
  • (void(*)())0?表示?把?0?強制轉換為一個函數指針,即:
    void (*func_ptr)() = (void(*)())0;  // 現在 func_ptr 指向地址 0
    

(3)?*(void(*)())0:解引用函數指針

  • *(void(*)())0?相當于:
    void (*func_ptr)() = (void(*)())0;
    *func_ptr;  // 解引用,得到函數本身
    
  • 在 C 語言中,函數指針解引用后仍然是函數,所以?*func_ptr?和?func_ptr?是等價的(見上一節分析)。

(4)?(*(void(*)())0)();:調用這個函數

  • 最終,(*(void(*)())0)();?相當于:
    void (*func_ptr)() = (void(*)())0;
    (*func_ptr)();  // 調用地址 0 處的函數
    
  • 或者更簡單的寫法(因為?func_ptr()?和?(*func_ptr)()?等價):
    ((void(*)())0)();  // 直接調用
4.3.2?解析void(* signal(int, void(*)(int)))(int);

這個聲明?void(* signal(int, void(*)(int)))(int);?是一個函數聲明,它定義了一個名為?signal?的函數。為了理解這個聲明,我們可以逐步解析它:

  1. 最內層部分?void(*)(int):

    • 這是一個函數指針類型,指向一個接受?int?參數并返回?void?的函數。

    • 例如,void handler(int sig);?這樣的函數可以匹配這個指針類型。

  2. 中間部分?signal(int, void(*)(int)):

    • signal?是一個函數,它接受兩個參數:

      • 第一個參數是?int?類型。

      • 第二個參數是?void(*)(int)?類型(即上述的函數指針)。

    • 因此,signal?的函數原型可以理解為:
      void (*signal(int sig, void (*handler)(int)))(int);
      
  3. 最外層部分?void(* ... )(int):

    • signal?函數的返回值也是一個函數指針,類型為?void(*)(int)

    • 也就是說,signal?函數返回一個指向“接受?int?參數并返回?void?的函數”的指針。

簡化理解:

  • signal?是一個函數,它接受一個?int?和一個函數指針,并返回一個同類型的函數指針。

總結:

void(* signal(int, void(*)(int)))(int);?聲明了一個函數?signal,它:

  1. 接受兩個參數:int?和?void(*)(int)(函數指針)。
  2. 返回一個?void(*)(int)?類型的函數指針。

這種寫法在 C 語言中很常見,尤其是在處理回調函數或函數指針時。

4.4?typedef關鍵字講解

typedef?關鍵字解釋

typedef?是 C/C++ 中的一個關鍵字,用于為現有的數據類型(包括基本類型、結構體、聯合體、枚舉、函數指針等)定義一個新的別名,使代碼更易讀、更簡潔。


4.4.1 基本語法
typedef <原類型> <新別名>;
  • <原類型>:可以是?intfloatcharstructunionenum?或函數指針等。
  • <新別名>:你給這個類型取的新名字。

4.4.2?常見用法

(1) 為基本類型定義別名

typedef unsigned int uint;  // 定義 uint 代替 unsigned int
typedef float real;         // 定義 real 代替 floatuint age = 25;              // 等同于 unsigned int age = 25;
real weight = 65.5f;        // 等同于 float weight = 65.5f;

(2) 為結構體定義別名

傳統寫法(需要?struct?關鍵字)

struct Point {int x;int y;
};struct Point p1;  // 必須寫 struct Point

使用?typedef?簡化

typedef struct {int x;int y;
} Point;  // 定義 Point 代替 struct { ... }Point p1;  // 直接使用 Point,不需要寫 struct

(3) 為指針類型定義別名

typedef int* IntPtr;  // IntPtr 是 int* 的別名int a = 10;
IntPtr p = &a;        // 等同于 int* p = &a;

(4) 為函數指針定義別名

原始寫法(復雜)

void (*funcPtr)(int);  // funcPtr 是一個指向 void(int) 函數的指針

使用?typedef?簡化

typedef void (*FuncPtr)(int);  // FuncPtr 是 void(*)(int) 的別名void foo(int x) { printf("%d\n", x); }FuncPtr fp = foo;  // 等同于 void (*fp)(int) = foo;
fp(10);            // 調用 foo(10)

4.4.3?結合?typedef?解析?signal?函數

原聲明:

void (*signal(int, void(*)(int)))(int);

使用?typedef?簡化:

typedef void (*SignalHandler)(int);  // 定義 SignalHandler 代替 void(*)(int)SignalHandler signal(int sig, SignalHandler handler);  // 更清晰的聲明
  • SignalHandler?是一個函數指針類型,指向?void(int)?函數。
  • signal?是一個函數,接受?int?和?SignalHandler,并返回?SignalHandler

4.4.4?typedef?的優點
  1. 提高可讀性:復雜的類型(如函數指針)可以用更直觀的名字表示。
  2. 減少重復代碼:避免反復寫冗長的類型聲明。
  3. 便于維護:修改類型時只需改?typedef?定義,而不需要修改所有使用的地方。

4.4.5?總結
用途示例
基本類型別名typedef int Int32;
結構體別名typedef struct { ... } Point;
指針別名typedef int* IntPtr;
函數指針別名typedef void (*FuncPtr)(int);

typedef?是 C/C++ 中非常重要的關鍵字,能顯著提升代碼的可讀性和可維護性,尤其是在處理復雜類型(如函數指針)時非常有用。

五. 函數指針數組

首先我們要明白什么是函數指針數組?

5.1 基本概念

1. 函數指針

函數指針是指向函數的指針變量。聲明一個函數指針需要指定它指向的函數的返回類型和參數類型。

// 函數原型
int add(int a, int b);
int subtract(int a, int b);// 函數指針聲明
int (*funcPtr)(int, int);// 指向add函數
funcPtr = add;

2. 函數指針數組

函數指針數組是存儲多個函數指針的數組。

// 聲明一個包含兩個函數指針的數組
int (*funcArray[2])(int, int);// 初始化數組
funcArray[0] = add;
funcArray[1] = subtract;

5.2 詳細用法

1. 聲明函數指針數組

// 返回類型 (*數組名[數組大小])(參數列表)
double (*operations[4])(double, double);

2. 初始化函數指針數組

double add(double a, double b) { return a + b; }
double sub(double a, double b) { return a - b; }
double mul(double a, double b) { return a * b; }
double div(double a, double b) { return a / b; }// 初始化數組
operations[0] = add;
operations[1] = sub;
operations[2] = mul;
operations[3] = div;

3. 使用函數指針數組

double result;
int choice = 2; // 假設用戶選擇乘法
double x = 5.0, y = 3.0;// 通過索引調用函數
result = operations[choice](x, y);
printf("結果: %.2f\n", result); // 輸出: 15.00

5.3 實際應用示例

1. 計算器實現

#include <stdio.h>// 定義運算函數
double add(double a, double b) { return a + b; }
double sub(double a, double b) { return a - b; }
double mul(double a, double b) { return a * b; }
double div(double a, double b) { return a / b; }int main() {// 聲明并初始化函數指針數組double (*ops[4])(double, double) = {add, sub, mul, div};int choice;double x, y;printf("選擇運算:\n0. 加\n1. 減\n2. 乘\n3. 除\n");scanf("%d", &choice);printf("輸入兩個數字: ");scanf("%lf %lf", &x, &y);// 調用選中的函數double result = ops[choice](x, y);printf("結果: %.2f\n", result);return 0;
}

運行結果如下:

六. 轉移表

轉移表(Jump Table)

轉移表(也稱為跳轉表)是一種使用函數指針數組來實現多路分支的技術,它比傳統的switch-case語句更高效、更靈活。

基本概念

轉移表本質上是一個函數指針數組,通過數組索引來選擇和調用不同的函數,避免了冗長的條件判斷。

轉移表 vs switch-case

switch-case實現

void handleCommand(int cmd) {switch(cmd) {case 0: cmd0(); break;case 1: cmd1(); break;case 2: cmd2(); break;// ...default: defaultHandler();}
}

轉移表實現

// 定義命令處理函數
void cmd0() { /* ... */ }
void cmd1() { /* ... */ }
void cmd2() { /* ... */ }
void defaultHandler() { /* ... */ }// 創建轉移表
typedef void (*CommandHandler)(void);
CommandHandler jumpTable[] = {cmd0, cmd1, cmd2};void handleCommand(int cmd) {if (cmd >= 0 && cmd < sizeof(jumpTable)/sizeof(jumpTable[0])) {jumpTable[cmd]();} else {defaultHandler();}
}

轉移表優勢

  1. 效率更高:直接通過索引訪問,時間復雜度O(1),而switch-case可能需要多次比較

  2. 代碼更簡潔:特別是當分支很多時

  3. 更易維護:添加新功能只需擴展數組,不需要修改邏輯結構

  4. 動態性:可以在運行時修改函數指針

實際應用示例

1. 簡單計算器

#include <stdio.h>// 運算函數
double add(double a, double b) { return a + b; }
double sub(double a, double b) { return a - b; }
double mul(double a, double b) { return a * b; }
double div(double a, double b) { return a / b; }// 定義轉移表
typedef double (*Operation)(double, double);
Operation operations[] = {add, sub, mul, div};int main() {int choice;double x, y;printf("選擇運算(0-3): ");scanf("%d", &choice);printf("輸入兩個數字: ");scanf("%lf %lf", &x, &y);if (choice >= 0 && choice < sizeof(operations)/sizeof(operations[0])) {double result = operations[choice](x, y);printf("結果: %.2f\n", result);} else {printf("無效選擇\n");}return 0;
}

以上就是本篇內容 希望能對你有所幫助

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

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

相關文章

Unity:場景管理系統 —— SceneManagement 模塊

目錄 &#x1f3ac; 什么是 Scene&#xff08;場景&#xff09;&#xff1f; Unity 項目中的 Scene 通常負責什么&#xff1f; &#x1f30d; 一個 Scene 包含哪些元素&#xff1f; Scene 的切換與管理 &#x1f4c1; 如何創建與管理 Scenes&#xff1f; 什么是Scene Man…

內容中臺重構企業知識管理路徑

智能元數據驅動知識治理 現代企業知識管理的核心挑戰在于海量非結構化數據的有效治理。通過智能元數據分類引擎&#xff0c;系統可自動識別文檔屬性并生成多維標簽體系&#xff0c;例如將技術手冊按產品版本、功能模塊、適用場景進行動態標注。這種動態元數據框架不僅支持跨部…

Vue3:腳手架

工程環境配置 1.安裝nodejs 這里我已經安裝過了&#xff0c;只需要打開鏈接Node.js — Run JavaScript Everywhere直接下載nodejs&#xff0c;安裝直接一直下一步下一步 安裝完成之后我們來使用電腦的命令行窗口檢查一下版本 查看npm源 這里npm源的地址是淘寶的源&#xff0…

悅數圖數據庫一體機發布,讓復雜關聯計算開箱即用

在金融風控、政務治理、能源監測等關鍵領域&#xff0c;復雜數據關聯分析已成為業務決策的核心需求。然而&#xff0c;信創場景的特殊性——全棧自主可控、海量實時計算、系統高可用性——對傳統技術架構提出了近乎苛刻的要求。悅數圖數據庫一體機應運而生&#xff0c;以軟硬協…

收放卷“材料停機減速距離“計算FC(算法公式+ST源代碼+C++代碼)

PLC運動控制基礎系列之梯形速度曲線 PLC運動控制基礎系列之梯形速度曲線_三菱運動控制模塊梯形加減速-CSDN博客文章瀏覽閱讀3.2k次,點贊3次,收藏7次。本文是關于PLC運動控制的基礎教程,重點介紹了梯形速度曲線的概念、計算和應用。討論了梯形加減速在啟動和停止階段的作用,…

Centos7系統(最小化安裝)安裝zabbix7版本詳細文章、nginx源代碼配置、php源代碼、mysql-yum安裝

zabbix官網鏈接下載zabbix源代碼安裝包 選擇zabbix版本&#xff08;此文章使用zabbix7.0版本&#xff09; 安裝之前由于是最小化安裝centos7安裝一些開發環境和工具包 文章使用國內阿里源 cd /etc/yum.repos.d/;curl -O https://mirrors.aliyun.com/repo/epel-7.repo;curl -…

描述性統計圖表

一、核心圖表類型與用途 1、直方圖(Histogram) (1)定義:用連續矩形表示數據分布,橫軸為數據區間,縱軸為頻數或頻率。 (2)用途:展示數據分布形態(對稱、偏態)、識別離群值。 (3)適用場景:分析連續型變量的分布特征,如收入分布、考試成績分布。 2、箱線圖(Box P…

ThinkPad X250電池換電池芯(理論技術儲備)

參考&#xff1a;筆記本電池換電芯的經驗與心得分享 - 經典ThinkPad專區 - 專門網 換電池芯&#xff0c;需要克服以下問題&#xff1a; 1 拆電池。由于是超聲波焊接&#xff0c;拆解比較費力&#xff0c;如果暴力撬&#xff0c;有可能導致電池殼變形... 2 替換電池芯的時候如…

Java(基礎) day01 初識Java

目錄 一、運行Java程序 二、基本數據類型 1、整數類型 ?編輯2、浮點型 3、字符型 4、布爾類型 一、運行Java程序 Java是一門半編譯型、半解釋型語言。先通過javac編譯程序把xxx.java源文件進行編譯&#xff0c;編譯后生成的.class文件是由字節碼組成的平臺無關、面向JVM的文…

【美團】Java后端一面復盤|網絡+線程+MySQL+Redis+設計模式+手撕算法

&#x1f4cd; 面試公司&#xff1a;美團 &#x1f3af; 面試崗位&#xff1a;Java后端開發工程師 &#x1f4de; 面試形式&#xff1a;電話面試 &#x1f552; 面試時長&#xff1a;約 50 分鐘 &#x1f501; 面試輪次&#xff1a;第一輪技術面 ? 面試整體節奏&#xff1a; …

Go語言八股文之Mysql鎖詳解

&#x1f49d;&#x1f49d;&#x1f49d;歡迎來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 非常期待和您一起在這個小…

實戰案例:采集 51job 企業招聘信息

本文將帶你從零開始&#xff0c;借助 Feapder 快速搭建一個企業級招聘信息數據管道。在“基礎概念”部分&#xff0c;我們先了解什么是數據管道和 Feapder&#xff1b;“生動比喻”用日常場景幫助你快速理解爬蟲組件&#xff1b;“技術場景”介紹本項目中如何使用代理等采集策略…

GMT之Bash語言使用

GMT的操作有自己的邏輯和“命令”&#xff0c;但GMT是可以用Bash語言控制的&#xff0c;所以常常以.sh為后綴寫GMT程序。 GMT程序運行步驟如下&#xff1a; 采用cd &#xff0c;定位到指定文件夾&#xff1b;以sh ***.sh運行GMT&#xff0c;得到結果。 另外&#xff0c;遇到…

整合Redis

整合Redis 引入依賴 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency><groupId>org.apache.commons</groupId><art…

Vue3——Watch偵聽器

目錄 手動指定監聽對象 偵聽ref對象 偵聽ref對象中的某個屬性 reactive寫法 watchEffect 自動偵聽 多源偵聽 一次性偵聽器 watch 是?個?于觀察和響應Vue響應式系統中數據變化的?法。它允許你指定?個數據源&#xff08;可以是 響應式引?、計算屬性、組件的屬性等&#xf…

1、數據結構與算法(Python版-啃書)-緒論

1.1 計算機問題求解 一般而言&#xff0c;人們需要的不是解決一個具體問題的程序&#xff0c;而是解決一類問題的程序。 對于求平方根這樣的簡單問題&#xff0c;人們希望的也不是專用于求某個數(例如2)的平方根的函數&#xff0c;而是能求任何數的平方根的函數。 用計算機解…

微信小程序之將輪播圖設計為組件

在components文件夾上點右鍵&#xff0c;新建component&#xff0c;命名為swiper 然后將我們之前的代碼都拷貝到對應文件中&#xff0c; 然后我們的頁面要引用這個組件&#xff0c; 在pages\index\index.json中引入&#xff1a; { "usingComponents": {"van…

【視頻】解決FFmpeg將RTSP轉RTMP流時,出現的卡死、出錯等問題

【視頻】郭老二博文之:圖像視頻匯總 1、簡述 如果不修改圖像內容,可以使用FFmpeg命令來將RTSP轉RTMP流。 SRS視頻服務器就是這么干的,它沒有使用FFmpeg接口,而是直接使用FFmpeg命令來轉流。 但是在使用中,約到了一些問題,比如轉流時卡死、轉流出錯等等,下面描述怎么解…

報銷單業務筆記

文章目錄 業務點業務點-對公對私業務點-多系統標志 特殊業務入參入參報文 出參出參報文中間的邏輯多對多關系 其他應該是整體成功還是可以部分成功這種多對多關多關系有沒有優雅的判斷方式 報銷單是個通用場景&#xff0c;有通用邏輯&#xff0c;在此基礎上進行適度定制&#x…

25軟考【軟件評測師】:10天極限沖刺攻略(附知識點解析+沖刺攻略)

距離2025上半年“軟件評測師”考試已經只剩最后一周多了&#xff0c;還沒有準備好的小伙伴趕緊行動起來。為了幫助大家更好的沖刺學習&#xff0c;特此提供一份考前沖刺攻略。本指南包括考情分析、沖刺攻略兩個部分&#xff0c;可以參考此指南進行最后的復習要領&#xff0c;相…