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

C 語言函數傳遞數組的本質:退化為指針與 PHP count() 實現對比

     編輯:關於C語言

核心結論

C 語言函數參數中數組退化為指針:void func(int arr[]) 等價於 void func(int *arr)。函數內無法獲取數組長度,必須額外傳遞 size_t len。修改參數指向的內容會影響原數組(傳址語義)。

代碼驗證

#include <stdio.h>

void changeArr(int arr[]) {  // 等價 int *arr
    arr[0] = 100;            // 修改原數組內容
}

int main() {
    int arr[2] = {1, 2};
    printf("Before: %d\n", arr[0]); // 1
    changeArr(arr);
    printf("After:  %d\n", arr[0]); // 100
    return 0;
}

輸出證明:changeArr 直接修改了主調函數的數組內容,無需像 PHP 那樣顯式傳引用 &$arr。

為什麼 C 不像 PHP 那樣有 count()?

PHP 變量是 zval 容器,內部攜帶類型、引用計數、長度等元數據。C 數組只是連續內存塊,編譯期只知道類型與大小,運行期無任何元數據。

PHP count() 內核實現簡析

源碼位於 ext/standard/array.c:

PHP_FUNCTION(count) {
    zval *array;
    long mode = COUNT_NORMAL;
    zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &array, &mode);

    switch (Z_TYPE_P(array)) {
        case IS_NULL:   RETURN_LONG(0);
        case IS_ARRAY:  RETURN_LONG(php_count_recursive(array, mode));
        case IS_OBJECT: // 實現 Countable 接口則調用 count()
            // ...
        default:        RETURN_LONG(1); // 標量視為 1
    }
}

核心 php_count_recursive 遍歷 HashTable 統計元素,支持遞歸計數。這一切建立在 PHP 變量自帶類型信息的基礎上——C 語言完全沒有這套機制。

C 語言模擬「帶長度數組」的常用模式

1. 結構體封裝

typedef struct { int *data; size_t len; } IntArray;

void print_arr(const IntArray *a) {
    for (size_t i = 0; i < a->len; i++) printf("%d ", a->data[i]);
}

2. 結構體柔性數組成員

typedef struct { size_t len; int data[]; } IntArrayFlex;

IntArrayFlex *create(size_t n) {
    IntArrayFlex *a = malloc(sizeof(IntArrayFlex) + n * sizeof(int));
    a->len = n;
    return a;
}

3. 宏封裝長度計算(僅限定長數組)


#define ARR_LEN(arr) (sizeof(arr) / sizeof((arr)[0]))

int a[10];
printf("%zu\n", ARR_LEN(a)); // 10
// 注意:傳入函數後退化為指針,宏失效!

總結對比

特性C 數組參數PHP 數組參數
傳遞機制退化為指針(傳址)複製 zval 引用(寫時複製)
長度信息丟失,需額外傳遞zval 內部攜帶
修改影響直接修改原內存觸發 COW 複製,隔離副作用
類型安全無(編譯期僅檢查指針類型)運行期類型檢查

最佳實踐

  1. 函數簽名統一為 void func(Type *arr, size_t len),名稱體現「指針+長度」。
  2. 使用 const 修飾只讀數組:void func(const int *arr, size_t len)。
  3. 動態分配數組採用「誰分配誰釋放」或「柔性數組」封裝所有權。
  4. 嚴禁在函數內對數組參數使用 sizeof 獲取長度(永遠返回指針大小)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved