計算機內存中的整型存儲奧秘、大小端字節序及其判斷方法

目錄

一、回顧與引入:整數在內存中的存儲方式

為什么要采用補碼存儲?

二、大小端字節序及其判斷方法

1、什么是大小端?

2、為什么存在大小端?

3、練習

練習1:簡述大小端概念并設計判斷程序(百度面試題)

參考代碼1:

關鍵原理:字節序(Endianness)

小端模式(Little-endian)

大端模式(Big-endian)

check_sys()?函數詳解

結果分析

參考代碼2(使用聯合體):

聯合體(union)的特性

內存布局分析

小端模式

大端模式

工作原理

練習2:有符號與無符號字符型的輸出

1. 變量聲明和初始化

2. 初始化時的賦值

3.?printf?輸出

4. 具體每個變量的提升和輸出

5. 最終輸出

注意:char?的符號性

練習3:字符型變量以無符號格式輸出

1. 變量?a?的聲明和初始化

2.?printf?格式化輸出

3. 不匹配的格式說明符

4. 實際輸出(在常見的二進制補碼系統中)

5. 另一種理解(直接從char到unsigned int的轉換)(了解即可)

6. 總結輸出

7. 最終答案

1. 變量?a?的聲明和初始化

2. 有符號char的溢出行為

3.?printf?格式化輸出

4. 類型不匹配的后果

5. 實際輸出計算(在32位系統,二進制補碼)

6. 另一種理解方式

7. 如果char是無符號的?

8. 最終輸出

練習4:字符數組與strlen

練習5:無符號變量的循環

問題原因

問題原因

練習6:指針運算與字節序(x86小端模式)

代碼分析

1.?ptr1[-1]?的值

2.?*ptr2?的值(小端序假設)

輸出

注意

總結


一、回顧與引入:整數在內存中的存儲方式

在介紹strlen操作符時,我們已經提到過以下內容:

整數的二進制表示方法有三種,分別是原碼、反碼和補碼。

????????對于有符號整數,三種表示方法都包含符號位和數值位兩個部分。符號位以“0”表示正數,“1”表示負數,通常位于最高位,其余部分為數值位。

  • 正整數的原碼、反碼和補碼完全相同。

  • 負整數的原碼、反碼和補碼則各不相同。

具體轉換方式如下:

  • 原碼:直接根據數值的正負形式翻譯成二進制表示。

  • 反碼:在原碼的基礎上,保持符號位不變,其余各位按位取反。

  • 補碼:在反碼的基礎上加 1 得到。

對于整型數據,其在內存中實際存儲的是二進制補碼形式。

為什么要采用補碼存儲?

在計算機系統中,數值一律采用補碼來表示和存儲,主要原因包括:

  1. 使用補碼可以統一處理符號位與數值部分,簡化硬件設計;

  2. 補碼能夠將加法和減法運算統一為加法操作(CPU 通常只內置加法器);

  3. 補碼與原碼之間的轉換過程一致,無需額外的硬件電路支持,提高了計算效率并降低了系統復雜度。


二、大小端字節序及其判斷方法

在我們了解整數在內存中的存儲方式后,通過以下代碼調試可以觀察到一個現象:

#include <stdio.h>
int main()
{int a = 0x11223344;return 0;
}

????????調試時會發現,變量?a?中的值?0x11223344?在內存中是以字節為單位倒序存儲的。為什么會這樣呢?

1、什么是大小端?

????????當一個數據超過一個字節時,在內存中的存儲順序就涉及字節序的問題。根據不同的存儲順序,可分為大端字節序(Big-Endian)和小端字節序(Little-Endian)。其具體定義為:

  • 大端模式:數據的低位字節(即權值較小的字節)保存在內存的高地址處,而數據的高位字節保存在內存的低地址處。

  • 小端模式:數據的低位字節保存在內存的低地址處,而數據的高位字節保存在內存的高地址處。

理解并記住這兩種模式有助于我們在不同平臺或網絡傳輸中正確處理多字節數據。

2、為什么存在大小端?

????????計算機系統中以字節為單位編址,每個地址對應一個字節(8 bit)。但在C語言中,除了?char(8 bit)外,還有?short(16 bit)、int?和?long(32 bit 或更長,取決于編譯器和架構)等類型。對于寄存器寬度大于8位的處理器(如16位或32位CPU),如何排列多個字節就成為一個必須解決的問題,因此出現了大端和小端兩種存儲模式。

????????舉例來說,一個16位的變量?short x,其地址為?0x0010,值為?0x1122。其中?0x11?是高字節,0x22?是低字節。在大端模式下,0x11?存放在?0x0010(低地址),0x22?存放在?0x0011(高地址);小端模式則相反。常見的x86架構為小端模式,而KEIL C51通常為大端模式。許多ARM和DSP處理器默認為小端模式,部分ARM處理器還支持通過硬件配置選擇字節序。

3、練習

練習1:簡述大小端概念并設計判斷程序(百度面試題)

要求:簡述大端和小端字節序的概念,并編寫程序判斷當前機器的字節序。

參考代碼1
#include <stdio.h>
int check_sys() {int i = 1;return (*(char *)&i);
}
int main() {int ret = check_sys();if(ret == 1) {printf("小端\n");} else {printf("大端\n");}return 0;
}

關鍵原理:字節序(Endianness)

小端模式(Little-endian)
  • 低位字節存儲在低地址

  • 對于整數?1(0x00000001):

    • 內存布局(地址從低到高):01 00 00 00

大端模式(Big-endian)
  • 高位字節存儲在低地址

  • 對于整數?1(0x00000001):

    • 內存布局(地址從低到高):00 00 00 01

check_sys()?函數詳解
  1. int i = 1;在內存中分配4字節空間存儲整數1

  2. &i獲取變量i的起始地址(最低字節的地址)

  3. (char *)&i

    • 將int指針強制轉換為char指針

    • char指針指向內存的第一個字節

  4. *(char *)&i解引用char指針,獲取第一個字節的值

結果分析
  • 小端系統:第一個字節是?0x01,返回1

  • 大端系統:第一個字節是?0x00,返回0

參考代碼2(使用聯合體)
int check_sys() {union {int i;char c;} un;un.i = 1;return un.c;
}
聯合體(union)的特性
  • 聯合體的所有成員共享同一塊內存空間

  • 大小由最大的成員決定(這里int通常是4字節,char是1字節)

  • 對任何一個成員的修改都會影響其他成員的值

內存布局分析

當?un.i = 1?時:

  • 整數?1?的十六進制表示為:0x00000001

  • 在聯合體的共享內存中存儲這個值

小端模式
內存地址(低→高): 0x00  0x01  0x02  0x03
存儲數據:         0x01  0x00  0x00  0x00↑ 最低地址存儲最低有效字節
大端模式
內存地址(低→高): 0x00  0x01  0x02  0x03
存儲數據:         0x00  0x00  0x00  0x01↑ 最低地址存儲最高有效字節
工作原理
  1. un.i = 1:將整數1存入聯合體的4字節空間

  2. un.c:訪問聯合體的第一個字節(最低地址)

    • 小端:第一個字節是?0x01?→ 返回1

    • 大端:第一個字節是?0x00?→ 返回0

練習2:有符號與無符號字符型的輸出

#include <stdio.h>
int main() {char a = -1;signed char b = -1;unsigned char c = -1;printf("a=%d, b=%d, c=%d", a, b, c);return 0;
}
1. 變量聲明和初始化
  • char a = -1;在大多數系統中,char?默認是有符號的(相當于?signed char),但這一點取決于編譯器和平臺。通常,char?可以是有符號或無符號的,但常見的是有符號的。這里我們假設?char?是有符號的(如大多數x86系統)。

  • signed char b = -1;明確聲明為有符號字符,初始化為 -1。

  • unsigned char c = -1;無符號字符類型,初始化為 -1。

2. 初始化時的賦值
  • 對于有符號類型(a?和?b),-1 可以直接表示(二進制補碼形式)。

  • 對于無符號類型(c),初始化賦值為 -1。由于無符號類型不能表示負數,所以會發生轉換:-1 會被轉換為無符號類型所允許的最大值(因為無符號類型是模運算)。
    具體來說,對于?unsigned char(通常是8位),范圍是 0 到 255。
    -1 的二進制補碼表示是?11111111(所有位為1),當解釋為無符號時,就是 255。

3.?printf?輸出
  • printf?使用?%d?格式化輸出,它期望的是?int?類型參數。
    所以?a,?b,?c?都會先被提升為?int?類型(整數提升),然后傳遞給?printf

  • 整數提升規則:

    • 對于有符號類型(如?signed char),提升時進行符號擴展(即高位填充符號位)。

    • 對于無符號類型(如?unsigned char),提升時高位填充0。

4. 具體每個變量的提升和輸出
  • a(假設是有符號 char):

    • 初始值:-1(二進制?11111111

    • 提升為?int:符號擴展,高位全填1(即?11111111 11111111 11111111 11111111),這仍然是 -1。

    • 輸出:a=-1

  • b(signed char):

    • 與?a?相同:-1(二進制?11111111

    • 提升為?int:符號擴展,得到 -1。

    • 輸出:b=-1

  • c(unsigned char):

    • 初始值:-1 被轉換為無符號值 255(二進制?11111111)。

    • 提升為?int:因為是無符號,高位填充0(即?00000000 00000000 00000000 11111111),所以是 255。

    • 輸出:c=255

5. 最終輸出

因此,輸出為:a=-1, b=-1, c=255

注意:char?的符號性

????????如果系統默認將?char?定義為無符號(如某些ARM編譯器),那么?a?的行為會與?c?相同(輸出255)。但常見情況下(如GCC在x86上),char?是有符號的,所以輸出為 -1。

練習3:字符型變量以無符號格式輸出

#include <stdio.h>
int main() {char a = -128;printf("%u\n", a);return 0;
}
1. 變量?a?的聲明和初始化
  • char a = -128;:這里聲明了一個char類型的變量a,并初始化為-128

  • 在大多數系統中,char默認是有符號的(signed char),其范圍通常是-128127(假設是8位二進制補碼表示)。

  • -128正好是char類型能表示的最小值(二進制表示為10000000)。

2.?printf?格式化輸出
  • printf("%u\n", a);:這里使用%u格式說明符來輸出a的值。%u用于輸出無符號十進制整數

  • 但注意:achar類型(本質上是一個整數類型),當傳遞給printf時,由于可變參數函數的默認參數提升規則(default argument promotion),a會被提升為int類型(因為char是比int更小的整數類型)。

    • 具體來說:char(無論是signed char還是unsigned char)在傳遞給可變參數函數(如printf)時,會被提升為int(如果int可以表示所有char的值)或unsigned int(但通常int可以表示)。

    • 對于有符號的char a = -128,提升為int后仍然是-128(因為int可以表示-128)。

3. 不匹配的格式說明符
  • %u期望一個unsigned int類型的參數,但實際傳遞的是int類型的-128(由于提升)。

  • 這會導致未定義行為(undefined behavior),因為C標準規定:如果格式說明符和實際參數類型不匹配,行為是未定義的。

  • 然而,在大多數實現中,會直接按位解釋(即:將傳遞的int類型的二進制表示直接當作unsigned int來解讀)。

4. 實際輸出(在常見的二進制補碼系統中)
  • a的原始值(char類型)是-128,其二進制表示(8位)是:10000000

  • 當提升為int時(假設32位int),由于符號擴展,-128int表示是:二進制:11111111 11111111 11111111 10000000(即全1填充到最高位,直到第8位為1,其余低位為0)。

  • 當用%u解釋這個int值時(即把相同的二進制位模式當作無符號整數),得到的無符號整數值是:

    • 11111111 11111111 11111111 10000000(二進制) =?4294967168(十進制)。

    • 計算:最高位是1,所以這是一個很大的正數(2^32 - 128 = 4294967168)。

5. 另一種理解(直接從charunsigned int的轉換)(了解即可)
  • 實際上,在傳遞過程中,char先被提升為int(值為-128),然后被printf%u解讀(即強制轉換為unsigned int)。

  • 有符號整數到無符號整數的轉換規則:C標準規定,如果源值是負數,則轉換結果為“該值加上無符號類型最大值加1”(即模運算)。

    • 所以,(unsigned int)(-128)?=?-128 + UINT_MAX + 1?=?UINT_MAX - 127

    • 在32位系統中,UINT_MAX4294967295,所以結果是4294967295 - 127 = 4294967168

6. 總結輸出
  • 因此,在常見的系統(32位,二進制補碼)上,輸出將是4294967168

  • 注意:如果char是無符號的(某些系統可能定義charunsigned char),那么a = -128實際上會賦值128(因為無符號char的范圍是0-255),但這里我們假設char是有符號的(這是大多數系統的默認行為)。

7. 最終答案

所以,這段代碼的輸出是:

#include <stdio.h>
int main() {char a = 128;printf("%u\n", a);return 0;
}
1. 變量?a?的聲明和初始化
  • char a = 128;:聲明了一個char類型的變量a,并初始化為128

  • 在大多數系統中,char默認是有符號的(signed char),其范圍是-128127(8位二進制補碼表示)。

  • 128超出了signed char的正數范圍(127是最大值),所以這里會發生整數溢出

2. 有符號char的溢出行為
  • 在C語言中,有符號整數溢出是未定義行為(undefined behavior)。

  • 但在大多數實現(使用二進制補碼)中,數值會"環繞"(wrap around):

    • 127(01111111) + 1 =?-128(10000000)

    • 所以?128?會被解釋為?-128(因為128 = 127 + 1)

3.?printf?格式化輸出
  • printf("%u\n", a);:使用%u格式說明符輸出a的值。

  • 由于可變參數函數的默認參數提升規則,char類型的a會被提升為int類型。

  • %u期望一個unsigned int類型的參數,但實際傳遞的是提升后的int類型值(-128)。

4. 類型不匹配的后果
  • 這是未定義行為,因為格式說明符%u與實際參數類型(int)不匹配。

  • 但在大多數系統中,會直接按位解釋(將int的二進制表示當作unsigned int來解讀)。

5. 實際輸出計算(在32位系統,二進制補碼)
  • a的實際值:由于溢出,a = 128?被存儲為?-128(二進制:10000000)

  • 提升為int-128?的32位二進制補碼表示是:11111111 11111111 11111111 10000000

  • 當用%u解釋這個位模式時,被當作無符號整數:

    • 二進制:11111111 11111111 11111111 10000000

    • 十進制值:232 - 128 = 4294967296 - 128 = 4294967168

6. 另一種理解方式
  • 從有符號到無符號的轉換規則:(unsigned int)(-128) = -128 + UINT_MAX + 1

  • 在32位系統中,UINT_MAX = 4294967295

  • 所以:4294967295 + 1 - 128 = 4294967168

7. 如果char是無符號的?
  • 如果系統默認charunsigned char(范圍0-255),那么:

    • a = 128?是有效的

    • 提升為int時是128(正數)

    • %u輸出:128

  • 但大多數系統(如x86)默認char是有符號的。

8. 最終輸出

在常見的系統(32位,二進制補碼,char有符號)上,輸出為:

練習4:字符數組與strlen

#include <stdio.h>
#include <string.h>
int main() {char a[1000];int i;for(i = 0; i < 1000; i++) {a[i] = -1 - i;}printf("%d", strlen(a));return 0;
}
  1. 數組?a?的初始化

    • a?是一個長度為1000的字符數組(char類型,在大多數系統中是有符號的,范圍是-128到127)。

    • 循環中,a[i] = -1 - i?對每個元素賦值。

      • 當?i=0a[0] = -1 - 0 = -1

      • 當?i=1a[1] = -1 - 1 = -2

      • ...

      • 當?i=127a[127] = -1 - 127 = -128(這是char能表示的最小值)

      • 當?i=128a[128] = -1 - 128 = -129,但char只能表示-128到127,所以會發生溢出。

        • 在補碼表示中,-129的二進制是(假設8位char):-129的補碼是(超出8位范圍),實際會截斷為8位。

        • 計算:-129的二進制(16位表示)是1111111101111111,截取低8位是01111111(即127)。

        • 類似地,-130截斷為126,依此類推。

    ????????實際上,我們可以用取模的方式來計算溢出后的值(因為C標準規定有符號整數溢出是未定義行為,但通常實現是環繞的):

    • 對于有符號char,值會以256為模環繞(因為8位有符號數的表示范圍是-128~127,共256個值)。

    • 所以,-1 - i?的實際值可以通過?(-1 - i) % 256?來得到(但需要調整到在-128~127之間)。

    更直接的方式是考慮序列:

    • i=0: -1

    • i=1: -2

    • ...

    • i=127: -128

    • i=128: -129 -> 由于溢出,實際為127(因為-129 + 256 = 127)

    • i=129: -130 -> 126

    • ...

    • i=255: -256 -> 0

    • i=256: -257 -> -1(因為-257 + 256*2 = 255?不對,實際上應該模256,但注意有符號數的表示)

    實際上,我們可以寫出前幾個值:
    i: 0 1 2 ... 127 128 129 130 ... 255 256 ...
    a[i]: -1, -2, -3 ... -128,127,126,125 ... 0, -1, ...

    ????????注意,當i=255時:-1-255 = -256,模256后是0(因為-256正好是256的倍數,所以余0)。
    ????????當i=256時:-1-256=-257,模256:-257 % 256 = -1(因為-257 = -256*1 -1,所以余-1?但實際在8位中,它表示成-1)。

    ????????但這里我們不需要所有值,我們只需要知道第一個0出現在哪里?因為strlen計算的是從開始到第一個'\0'(即0)的字符數。

  2. strlen的工作strlen(a)?從a[0]開始掃描,直到遇到第一個值為0的字節(即'\0'),然后返回之前的字符個數(不包括0本身)。

  3. 尋找第一個0

    • 我們需要找到最小的i,使得a[i] == 0

    • 根據上面的賦值:a[i] = -1 - i

    • a[i] == 0,即-1 - i == 0?但這樣i=-1,顯然不對(因為i從0開始)。

    • 實際上,由于溢出,我們需要解方程:(-1 - i) mod 256 = 0(即-1-i是256的倍數)。

    • -1 - i = 256 * k(k為整數),因為值在0時停止。

    • 取k=-1(因為i非負,所以k應為負):-1 - i = -256?=>?i = 255
      所以當i=255時,a[255] = -1-255 = -256,模256后為0(因為-256是256的整數倍,所以余0)。

    因此,第一個0出現在索引255處。

  4. 驗證

    • i=255時:a[255] = -1-255 = -256。在8位有符號表示中,-256的二進制(補碼)本需要9位(100000000),截斷低8位后是00000000(即0)。

    • 所以a[255] = 0

  5. strlen(a)的返回值strlena[0]開始計數,直到a[254](因為a[255]是0,不計入),所以總共255個字符。

因此,程序輸出的是255。

練習5:無符號變量的循環

#include <stdio.h>
unsigned char i = 0;
int main() {for(i = 0; i <= 255; i++) {printf("hello world\n");}return 0;
}
問題原因
  1. unsigned char i?的范圍是 0 到 255(8位無符號字符)

  2. 當?i?增加到 255 后,執行?i++?會導致整數溢出

  3. 在無符號整型中,溢出會回繞:255 + 1 = 0

  4. 因此條件?i <= 255?永遠為真,循環永遠不會結束

#include <stdio.h>
int main() {unsigned int i;for(i = 9; i >= 0; i--) {printf("%u\n", i);}return 0;
}
問題原因
  1. unsigned int i?是無符號整型,范圍是?0?到?UINT_MAX(通常是 0 到 4,294,967,295)

  2. 當?i = 0?時,執行?i--?會導致下溢

  3. 在無符號整型中,下溢會回繞:0 - 1 = UINT_MAX(非常大的正數)

  4. 因此條件?i >= 0?永遠為真(因為無符號數永遠 ≥ 0),循環永遠不會結束

練習6:指針運算與字節序(x86小端模式)

#include <stdio.h>
int main() {int a[4] = {1, 2, 3, 4};int *ptr1 = (int *)(&a + 1);int *ptr2 = (int *)((int)a + 1);printf("%x, %x", ptr1[-1], *ptr2);return 0;
}

????????這段代碼涉及指針運算和類型轉換,行為是未定義的(UB),但在小端序機器上可能有特定輸出。我們來分析:

代碼分析
int a[4] = {1, 2, 3, 4};
int *ptr1 = (int *)(&a + 1);      // 指向數組末尾之后
int *ptr2 = (int *)((int)a + 1);  // 將地址轉為整數加1再轉回指針
printf("%x, %x", ptr1[-1], *ptr2); // 輸出
1.?ptr1[-1]?的值
  • &a?是「指向整個數組的指針」,類型是?int (*)[4]

  • &a + 1?會跳過整個數組(16字節),指向數組末尾之后

  • (int *)?強制轉換為?int*,現在?ptr1?指向?a[4](不存在)

  • ptr1[-1]?等價于?*(ptr1 - 1),即從末尾回退一個int,指向?a[3]

  • 所以?ptr1[-1]?是?4

2.?*ptr2?的值(小端序假設)
  • a?是數組首地址(假設為?0x1000

  • (int)a?將地址轉為整數(假設?0x1000

  • (int)a + 1?得到?0x1001

  • (int *)?再轉回指針,現在?ptr2?指向?0x1001(非對齊訪問,UB!)

在小端機器上,數組?a?在內存中的布局(每個int占4字節):

地址      數據(字節序,小端)
0x1000:   01 00 00 00   // a[0] = 1
0x1004:   02 00 00 00   // a[1] = 2  
0x1008:   03 00 00 00   // a[2] = 3
0x100C:   04 00 00 00   // a[3] = 4

ptr2?指向?0x1001,會讀取從?0x1001?開始的4字節:

  • 取?0x10010x10020x10030x1004?這4個字節

  • 字節數據:00 00 00 02(小端序)

  • 解釋為int:0x02000000(十進制 33554432)

輸出

所以輸出可能是:4, 2000000(%x輸出十六進制)

注意
  • 未定義行為(int)a + 1?破壞了對齊要求,可能崩潰或得到意外值

  • 依賴字節序:僅在小端機器得到上述結果,大端會不同

  • 依賴編譯器/平臺:實際結果因實現而異

總結

在小端序x86系統上,輸出可能是:

但這段代碼不應該在實際中使用,因為它包含了多個未定義行為和對齊問題。

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

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

相關文章

Redis 最常用的 5 種數據類型

Redis 支持多種靈活的數據類型&#xff0c;每種類型針對特定場景優化。以下是 **Redis 最常用的 5 種數據類型**及其核心特點和應用場景&#xff1a;1. 字符串&#xff08;String&#xff09;描述&#xff1a;最基本的數據類型&#xff0c;可存儲文本、數字&#xff08;整數/浮…

【嵌入式】RK3588 對比 NVIDIA Jetson,Radxa Rock 5B vs Orange Pi 5 Max

RK3588這個芯片,適合AI應用么,為什么這么貴呢 AI 邊緣盒子里的旗艦芯 深度分析一下 RK3588(瑞芯微 Rockchip RK3588) 為什么被很多人關注在 AI 應用,以及它價格偏高的原因。 ?? 1. RK3588 的基本情況 制程:8nm(Samsung 8nm LP) CPU:8 核 big.LITTLE 架構(4 Cortex-…

暴雨讓高性能計算更“冷靜”

當AI大模型的參數突破萬億&#xff0c;當深地探測的精度邁向微米&#xff0c;當數字經濟的脈搏與千行百業深度共振&#xff0c;算力已成為驅動時代向前的核心引擎。然而&#xff0c;傳統風冷技術在高密度算力需求面前漸顯乏力——機柜內的熱浪如同無形的枷鎖&#xff0c;既制約…

SpringAI集成MCP

文章目錄1_調用公用MCP2_Stdio方式3_Stdio實現原理4_SSE方式5_自定義MCP客戶端6_MCP Server權限控制SpringAI 通過 SpringBoot 集成擴展了 MCP Java SDK &#xff0c;提供了客戶端和服務端 starter&#xff0c;讓 AI 應用程序快速支持 MCP。接下來直接演示。 1_調用公用MCP 在…

Spring Start Here 讀書筆記:第10章 Implementing REST services

REST 服務可用于實現兩個應用之間的通訊&#xff0c;包括 Web 應用中的客戶端和服務器之間&#xff0c;移動應用與后端服務之間&#xff0c;或兩個后端服務之間。 10.1 使用 REST 服務在應用之間交換數據 REST端點是應用程序通過 Web 協議公開服務的方式&#xff0c;因此也稱…

SYBASE ASE、Oracle、MySQL/MariaDB、SQL Server及PostgreSQL在郵件/短信發送功能上的全面橫向對比報告

以下是對SYBASE ASE、Oracle、MySQL/MariaDB、SQL Server及PostgreSQL在郵件/短信發送功能上的全面橫向對比報告&#xff08;截至2025年8月最新版本&#xff09;&#xff0c;涵蓋技術實現、配置復雜度、適用場景及權威評測&#xff1a;??一、郵件發送能力對比????1. Orac…

服務器與客戶端

目錄 一、服務器&#xff08;Server&#xff09; 核心特點 常見類型 二、客戶端&#xff08;Client&#xff09; 核心特點 常見類型 客戶端與服務器的交互流程 補充&#xff1a;與 “對等網絡&#xff08;P2P&#xff09;” 的區別 C/S模式 一、C/S 模式的核心原理 …

GaussDB 并發自治事務數達到最大值處理案例

1 業務背景自治事務&#xff08;Autonomous Transactions&#xff09;是一種高級特性&#xff0c;允許你在一個事務中執行另一個獨立的事務。這種機制特別有用&#xff0c;尤其是在需要在一個事務中執行多個操作但又不想因為其中一個操作失敗而影響整個事務的場景。2 業務影響在…

【傳奇開心果系列】Flet分頁自定義組件CustomPaginationComponent封裝版自定義模板

Flet分頁自定義組件CustomPaginationComponent封裝版自定義模板一、效果展示GIF動圖二、應用場景三、特色說明四、源碼下載地址一、效果展示GIF動圖 二、應用場景 圖片瀏覽應用&#xff1a; 用戶可以通過分頁組件瀏覽多張圖片&#xff0c;每點擊一次“上一頁”或“下一頁”按鈕…

數據安全——39頁解讀數字化轉型大數據安全基礎培訓方案【附全文閱讀】

適應人群為企業數據安全管理人員、IT 運維人員、數字化轉型決策者、網絡安全工程師及關注大數據安全的從業人員。主要內容圍繞數字化轉型中大數據安全展開,核心包括基礎概念(信息、數據與大數據的定義及區別,大數據 4V 特點與來源);安全風險(企業面臨的數據資產管理缺失、…

week3-[二維數組]小方塊

week3-[二維數組]小方塊 題目描述 如果四個數 a,b,c,da,b,c,da,b,c,d 可以分成兩組&#xff0c;每組兩個數&#xff0c;滿足每組里面的兩個數一樣&#xff0c;那么稱這四個數是好的。 比如&#xff0c;2,5,2,52,5,2,52,5,2,5 是好的&#xff0c;因它滿足兩組&#xff1a;222 與…

Swift 項目結構詳解:構建可維護的大型應用

Swift 項目結構詳解&#xff1a;構建可維護的大型應用一、基礎結構&#xff08;推薦新手使用&#xff09;二、組件化結構&#xff08;企業級應用推薦&#xff09;層級架構&#xff1a;MVVM Coordinator路由實現&#xff08;Coordinator模式&#xff09;三、通用組件實現DI&…

【實時Linux實戰系列】基于實時Linux的數字轉換器設計

在現代電子系統中&#xff0c;數字轉換器&#xff08;如模數轉換器ADC和數模轉換器DAC&#xff09;扮演著至關重要的角色。它們負責將模擬信號轉換為數字信號&#xff0c;或將數字信號轉換為模擬信號&#xff0c;從而實現信號的數字化處理和傳輸。在實時系統中&#xff0c;如工…

FastTracker:實時準確的視覺跟蹤

摘要 https://arxiv.org/pdf/2508.14370 傳統的多目標跟蹤(MOT)系統主要設計用于行人跟蹤&#xff0c;通常對其他物體類別的泛化能力有限。本文提出了一種能夠處理多種物體類型的通用跟蹤框架&#xff0c;特別強調在復雜交通場景中的車輛跟蹤。所提出的1方法包含兩個關鍵組件&a…

國產輕量級桌面GIS軟件Snaplayers從入門到精通(20)

國產輕量級桌面GIS軟件Snaplayers實操&#xff1a;打開圖層并顯示屬性信息1、根據數據格式選擇圖層文件2、加載圖層到地圖中&#xff0c;并在左側顯示圖層的屬性表格3、屬性表格分頁顯示Snaplayers研發團隊承諾&#xff1a;國產輕量級桌面GIS軟件Snaplayers永久免費并持續更新

快速入門flask應用(從入門到實戰)

目錄 前言&#xff1a; 了解一些網絡通信的概念 什么是網絡通信&#xff1a; 當我們訪問一個網址的時候發生了什么&#xff1a; 1. 解析 URL&#xff1a;明確訪問目標 2. DNS 域名解析&#xff1a;將 “名字” 轉為 “地址” 3. 建立連接&#xff1a;TCP 三次握手&#x…

C++/QT 開發技能樹詳解

一、 編程語言 (C)1. C基礎語法&#xff08;數據類型、模板、命名空間&#xff09;是什么&#xff1a; 這是構建C程序的基石。數據類型定義了變量存儲的數據種類和大小&#xff1b;模板允許編寫與數據類型無關的通用代碼&#xff1b;命名空間用于避免大型項目中的名稱沖突。如何…

Java多線程進階-死鎖與面試題解析

文章目錄Java多線程進階&#xff1a;死鎖與面試題解析一、并發編程的噩夢——死鎖1. 什么是死鎖&#xff1f;四個缺一不可的條件2. 如何避免死鎖&#xff1f;從破壞循環等待開始二、并發編程面試題全景解析1. 鎖與同步機制2. CAS 與原子操作3. JUC 工具與線程池4. 線程安全集合…

ZYNQ啟動流程——ZYNQ學習筆記11

ZYNQ SoC 的啟動由片上的 BootROM 開始。片上 BootROM 是 ZYNQ 芯片上的一塊非易失性存儲器&#xff0c;它包含了 ZYNQ 所支持的配置器件的驅動&#xff0c; 而且里面的代碼是不可修改的。 BootROM 中的代碼首先會在片外的非易失性存儲器中尋找一個頭文件&#xff0c; 頭文件里…

C++利用CerateProcess創建WPF進程并通過命名管道通訊

引言原因是我需要在C程序中調用另外一個WPF窗體打開或則關閉&#xff0c;進程之前通過通訊協議進行交互。由于使用不同語言開發&#xff0c;兩者都比較復雜不方便重寫&#xff0c;最方便的方法就是使用進程間通信&#xff0c;WPF窗體應用程序根據消息進行Show/Hide/Exit操作。函…