电脑知识铺
第二套高阶模板 · 更大气的阅读体验

指针操作函数参数:C语言里那些绕不开的坑

发布时间:2025-12-16 08:57:46 阅读:127 次

写C代码的时候,总免不了跟指针打交道。尤其是把指针当函数参数传进去的时候,一不小心就踩了坑。比如你写了个函数想修改某个变量的值,结果跑完发现原变量纹丝不动,八成是没搞明白指针传递的门道。

传值和传址的区别

假设你要交换两个数,写了个函数:

void swap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}

调用后发现主函数里的变量根本没变。原因很简单:这是值传递,函数拿到的是副本。想要真正改到原来的变量,得传地址进去。

用指针做参数才能改外面的值

正确的做法是传指针:

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

调用时传地址:swap(&x, &y);。这样一来,函数里通过指针解引用操作,就能直接改到外面的变量。

常见错误:只想改指针本身

有时候你会遇到这种情况:函数里给指针重新赋值,想让它指向别的内存,结果调用完发现指针还是原来那样。比如:

void reassign_ptr(int *p) {
    p = (int *)malloc(sizeof(int));
    *p = 100;
}

这个函数看似分配了内存,但实际上外面的指针根本没变。因为p是形参,只在函数内有效。要想改变指针本身,得传二级指针:

void reassign_ptr_correct(int **p) {
    *p = (int *)malloc(sizeof(int));
    **p = 100;
}

调用时传 &my_ptr,这样才算真正改到了原始指针。

实际场景:读串口数据存到缓冲区

比如你在做端口映射相关的程序,要从串口读数据存进缓冲区。函数可能长这样:

int read_serial_data(int port_id, char *buffer, int max_len) {
    // 从指定端口读数据,填入buffer
    // 返回实际读取长度
    ...
    return bytes_read;
}

这里buffer是指针,函数通过它往外部内存写数据。如果传NULL进来,程序可能直接崩。所以调用前得确保buffer指向合法内存。

别忘了空指针检查

写这种函数时,最好加个判断:

if (buffer == NULL) {
    return -1;
}

不然用户一不小心传个空指针,程序一运行就段错误,查半天才发现是参数问题。

数组名传参的本质也是指针

当你把数组传进函数,其实传的是首元素地址:

void process_array(int arr[], int size)

等价于:

void process_array(int *arr, int size)

所以在函数里对arr的操作,直接影响原数组。但sizeof(arr)这时候就不再是数组长度了,而是指针大小,这点容易让人迷糊。