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

C語言內存地址深度解析與sizeof/strlen本質區別

     編輯:關於C語言

C語言內存地址分析與sizeof/strlen核心差異

指針與內存地址是C語言的核心難點,也是區分初級與資深開發者的關鍵分水嶺。本文通過圖解與實戰代碼,深度剖析數組名、指針、取地址運算符的本質區別,並徹底釐清sizeof與strlen的根本差異。

一、 內存地址圖解與核心概念

經典面試題:數組地址表達式含義

假設int a[4],首元素地址為0x8000(32位系統,int佔4字節),分析以下表達式:

內存佈局圖解

表達式值含義類型
&a[0]0x8000首元素地址int*
a0x8000數組名(轉換為首元素指針)int*
&a0x8000整個數組地址int(*)[4]
a+10x8004第二個元素地址int*
&(a+1)錯誤非法:a+1是右值不能取址-
&a+10x8010數組結束後地址(跨過整個數組)int(*)[4]

核心結論:

  • a和&a[0]值相同但語義不同:前者是數組名(指針常量),後者是首元素地址
  • &a類型是int(*)[4](指向包含4個int的數組指針),&a+1跨越整個數組大小(16字節)
  • a+1按sizeof(int)步進,&a+1按sizeof(a)步進

二、 變量內存分佈實戰分析

 只讀數據區
    char str2[] = "good idea";     // 字符數組 -> 棧區(內容從只讀區拷貝)
    
    printf("%p\n", &a);   // 0x100001028 (較小地址)
    printf("%p\n", &b);   // 0x10000102c (緊隨a之後)
    printf("%p\n", &c);   // 0x7fff5fbff744 (棧區高地址)
    printf("%p\n", &d);   // 0x7fff5fbff740 (棧區,比c低)
    printf("%p\n", str);  // 0x100000f78 (只讀區,地址較小)
    printf("%p\n", &str); // 0x7fff5fbff738 (棆區指針變量)
    printf("%p\n", *(&str)); // 0x100000f78 (指針指向的內容)
    printf("%p\n", str2); // 0x7fff5fbff75e (棧區數組)
    printf("%p\n", &str2); // 0x7fff5fbff75e (數組名=首元素地址)
}

內存分佈圖

地址分佈規律:

  1. 代碼段 < 數據段(已初始化全局) < BSS段(未初始化全局) < 堆區(向上增長) < 共享庫 < 棧區(向下增長) < 內核空間
  2. 字符串常量存儲在只讀數據區,字符數組初始化時從只讀區拷貝到棧區
  3. 指針變量本身在棧區,指向的內容可能在只讀區/堆區/棧區

三、 sizeof與strlen本質區別深度解析

核心差異:

特性sizeofstrlen
性質編譯時期運算符運行時庫函數
計算對象類型/變量佔用內存字節數字符串實際長度(遇\0停止)
參數類型名或表達式字符指針(char*)
包含\0是(若屬於數組一部分)否

經典案例分析:


數組作函數參數退化為指針:


四、 字符數組初始化陷阱與最佳實踐

危險代碼模式:


三種可能後果:

  1. 後續內存恰好為\0 → 正常輸出
  2. 後續內存非\0 → 輸出hello+亂碼直到遇到\0
  3. 訪問非法內存 → 程序崩潰(Segfault)

安全初始化模式:


五、 實戰調試技巧

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