首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

從組合語言視角深度解析 C 語言:char *p 與 char p[] 的本質區別

     編輯:關於C語言

前言

在 C 語言中,char *p 與 char p[] 這兩種字串定義方式,雖然在高層代碼中看似相似,但在記憶體佈局與底層機制上卻有著本質不同。本文將通過 GDB 反組譯輸出,從組合語言層面揭示兩者的核心差異。

實驗環境與基礎代碼

測試代碼如下:

#include <stdlib.h>
#include <stdio.h>

void main() {
    char array1[] = { "123456" };
    char *pointer1 = "123456";
}

反組譯分析

使用 GDB 反組譯 main 函數:

(gdb) disassemble main
Dump of assembler code for function main:
 0x08048394 <+0>:   push   %ebp
 0x08048395 <+1>:   mov    %esp,%ebp
 0x08048397 <+3>:   sub    $0x10,%esp
 0x0804839a <+6>:   movl   $0x34333231,-0xb(%ebp)
 0x080483a1 <+13>:  movw   $0x3635,-0x7(%ebp)
 0x080483a7 <+19>:  movb   $0x0,-0x5(%ebp)
 0x080483ab <+23>:  movl   $0x8048484,-0x4(%ebp)
 0x080483b2 <+30>:  leave
 0x080483b3 <+31>:  ret
End of assembler dump.

數組 array1 的記憶體分配

觀察指令 <+6>、<+13>、<+19> 三條指令:

  • movl $0x34333231, -0xb(%ebp) —— 寫入 "1234" (小端序:0x31='1', 0x32='2', 0x33='3', 0x34='4')
  • movw $0x3635, -0x7(%ebp) —— 寫入 "56" (0x35='5', 0x36='6')
  • movb $0x0, -0x5(%ebp) —— 寫入結束符 '\0'

程式在堆疊上為 array1 分配了 7 bytes 空間,直接存放字串內容 "123456\0"。數組名 array1 代表這塊記憶體的首地址,內容可修改。

指標 pointer1 的記憶體行為

指令 <+23>:movl $0x8048484, -0x4(%ebp) 將地址 0x8048484 存入堆疊變量 pointer1。查看該地址內容:

(gdb) x/7xb 0x8048484
0x8048484:  0x31  0x32  0x33  0x34  0x35  0x36  0x00

字串字面量 "123456" 存放在唯讀資料段,pointer1 僅持有其地址,未在堆疊為字串內容分配空間。嘗試修改 *pointer1 將導致未定義行為(通常是段錯誤)。

進階驗證:多實例對比

擴展代碼增加兩個數組與兩個指標:

char array1[] = { "123456" };
char array2[] = { "123456" };
char *pointer1 = "123456";
char *pointer2 = "123456";

反組譯顯示:

  • array1 與 array2 各自在堆疊分配獨立的 7 bytes,內容相同但地址不同(指令 <+6>~<+19> 與 <+23>~<+36>)
  • pointer1 與 pointer2 均指向同一地址 0x8048494(指令 <+40>、<+47>),編譯器優化合併了相同字串字面量

不同字串字面量的情況

若指標指向不同字串:

char *pointer1 = "123456";
char *pointer2 = "12345678";

反組譯指令 <+40>、<+47> 分別載入 0x8048494 與 0x804849b,記憶體檢查確認兩地址存放不同字串內容。

核心差異總結表

特性char p[]char *p
記憶體分配堆疊分配,含字串副本堆疊僅分配指標變量,字串在唯讀區
內容可修改性可修改不可修改(UB)
多實例行為每個數組獨立擁有副本相同字面量共享地址(編譯器優化)
sizeof 結果字串長度+1指標大小(4/8 bytes)

結語

從組合語言視角可見,char p[] 是「擁有數據的容器」,char *p 是「指向數據的引用」。理解這一區別,對避免緩衝區溢出、正確處理字串修改、優化記憶體佈局至關重要。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved