You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言字符数组传参疑问:为何可传char*却不可传char**?

为什么字符数组能传给char*函数,而数组地址不能传给char**函数?

这个问题的核心在于C语言里数组和指针的微妙区别,尤其是数组退化为指针的规则,以及不同指针类型的本质差异。咱们一步步拆解清楚:

1. 为什么foo(str)能正常工作?

当你把数组名str作为参数传递给函数时,C语言会自动触发数组到指针的隐式转换:数组名会被转换成指向数组第一个元素的指针。这里str是char[12]类型的数组,第一个元素是char,所以转换后的指针类型是char*——正好和foo的参数char* qux完全匹配,所以编译器不会报错,函数也能正常打印字符串。

2. 为什么bar(&str)会触发警告?

&str的类型并不是你以为的char**,而是指向整个数组的指针,具体类型是char (*)[12](读作“指向包含12个char的数组的指针”)。而bar的参数是char**(指向char指针的指针),这两个类型完全不兼容:

  • char**期望接收的是一个char*变量的地址,但&str指向的是一块12字节的连续char内存,根本不是char*类型的变量;
  • 两者的指针逻辑完全不同:比如对char**做+1操作,会跳过一个char*的大小(通常4或8字节);而对char (*)[12]做+1,会直接跳过整个12字节的数组。强行传递会导致类型不匹配,编译器必然警告,甚至可能引发未定义行为。

3. 为什么char* qux[12]和char** qux没区别?

你发现把baz的参数写成char* qux[12],编译器警告还是没变?这是C语言的一个特殊规则:在函数的参数列表中,数组类型会自动退化为对应的指针类型。不管你写的数组长度是多少,char* qux[12]都会被编译器直接解析成char** qux——因为函数参数里的数组本质上就是指针,数组长度会被直接忽略。所以baz和bar的参数类型其实完全一样,&str传进去自然还是类型不匹配。

怎么让代码合法?

如果你想传递数组的地址给函数,有两种正确的方式:

方式一:修改函数参数为指向数组的指针

#include <stdio.h>
void foo(char* qux) { puts(qux); }
// 参数改为指向12个char的数组的指针
void bar(char (*qux)[12]) { puts(*qux); }
void baz(char* qux[12]) { puts(*qux); }

int main() {
    char str[12] = "Hello there";
    foo(str);
    bar(&str); // 现在类型完全匹配,无警告
}

方式二:先把数组转成char*变量,再传变量地址

如果你非要用char**类型的参数,可以先把数组退化为char*存在一个变量里,再传递这个变量的地址:

#include <stdio.h>
void foo(char* qux) { puts(qux); }
void bar(char** qux) { puts(*qux); }
void baz(char* qux[12]) { puts(*qux); }

int main() {
    char str[12] = "Hello there";
    char* ptr = str; // 数组退化为char*,存入ptr
    bar(&ptr); // &ptr是char**,和bar的参数匹配
}

内容的提问来源于stack exchange,提问作者sleighty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:59:04