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

C語言指針與數組核心知識體系(上):基礎、區別、面試真題與大小端檢測

     編輯:關於C語言

一、指針基礎鐵律

  1. 指針本質:也是變量,有地址、有大小(32位 4B、64位 8B),存儲「另一個變量的地址」。
  2. 傳值 vs 傳址:函數參數傳遞本質是賦值/拷貝。值傳遞無法修改外部變量;傳址(傳指針)可修改外部變量、提升大結構體傳遞效率。
  3. const 修飾規則:int const* p / const int* p → 指向常量的指針(內容不可改);int* const p → 常量指針(指向不可改)。

二、數組基礎鐵律

  1. 數組 = 同類型變量有序集合,內存連續分佈。
  2. 數組名 = 首元素地址(&a[0]),但類型不同:a 類型 int(*)[N],&a 類型 int(*)[N](值相同,語義不同)。
  3. sizeof(a) = 整個數組字節數;sizeof(&a) = 指針大小。

三、指針與數組的核心區別

// 1.c 
char* p = "abcd"; 
// 2.c 
extern char* p[]; // 錯誤聲明:應為 extern char p[] 或 extern char* p 

// 直接打印 p:前者輸出字符串地址,後者若聲明正確則輸出數組首址。 
// 關鍵:數組名不佔存儲空間(無地址的地址),指針變量佔空間存地址。

四、經典面試題:指針算術陷阱

int a[] = {1,2,3,4,5}; 
int* p1 = (int*)(a + 1);      // a+1 → &a[1] → 值 2 
int* p2 = (int*)(&a + 1);     // &a+1 → 跳過整個數組 → &a[5](越界) 
int* p3 = (int*)((int)a + 1); // 地址+1 字節 → 截斷/對齊導致亂值 

printf("%d %d %d\n", p1[3], p2[-1], p3[0]); 
// 輸出:5  5  33554432 (視具體內存佈局而定)

核心公式:p + n = (uintptr_t)p + n * sizeof(*p)。a+1 步長 sizeof(int);&a+1 步長 sizeof(a)。

五、大小端檢測實戰

int main() { 
    int a = 0x1234; 
    char* p1 = (char*)&a; 
    char* p2 = (char*)&a + 1; 
    printf("p1=%p *p1=%x\n", p1, *p1); 
    printf("p2=%p *p2=%x\n", p2, *p2); 
    if (*p1 == 0x34 && *p2 == 0x12) 
        puts("Little Endian"); 
    else 
        puts("Big Endian"); 
}

輸出:*p1=34(低位在低地址)→ 小端模式(x86/ARM 默認)。

六、一行代碼實現 strlen(遞歸+斷言)

int strlen(char* s) { 
    return (assert(s), (*s ? strlen(s+1)+1 : 0)); 
}

利用逗號表達式、三元運算符、遞歸終止條件 *s=='\0'。僅供展示,生產環境用標準庫或迭代版。

總結

  • 指針算術步長由指向類型決定,a vs &a 是經典陷阱。
  • 大小端影響多字節類型在內存中的字節序,網絡傳輸需 htonl/ntohl 轉換。
  • 數組名在 sizeof / & / 字符串字面量初始化 三種情況下不退化為指針。

本文為「C語言指針和數組知識總結」系列上篇,下篇將覆蓋函數指針、多維數組、動態內存管理等進階主題。整理自 51CTO 技術博客筆記。

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