c语言好难——关于形参传递中有const的情况

本文探讨了C语言中关于形参传递时涉及`const`的情况。通过两个例子,解释了当形参为数组时,数组退化为一维指针,导致类型不匹配引发的编译错误。文章分析了`const`在形参和实参匹配中的作用,以及C语言赋值操作的要求,指出在形参传递中,需满足赋值操作的限制条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是在逛论坛的时候看到的一个问题。

 

例1:

 char *ptr;
void demo(const char* p)
{
         ;
}

 

int main(void)

{

demo(prt);

}

 

编译后不报错。

 

例2:

char *ptr[];

void demo(const char* p[])

{

;

}

 

int main(void)

{

demo(prt);

}

 

 

编译后报错,..\APP\main.c(37): error:  #167: argument of type"char *" is incompatible with parameter of type "const char**" ,错误意为形参传递不合适。

 

先分析例2:

报错原因是形参与实参的指针类型不一致。

以下是原因分析,在c语言中,形参为数组时候,会退化为一维指针,所以const char* p[]  等价于 const char **p,

当 *prt[] 变量作为形参传递的时候,等价于 char **ptr,

当执行demo(ptr)的时候,实参传递给形参,等价于实参赋值给形参,即下面这条语句,

**p = **ptr;

本质上是两个指针数值的传递,但是形参是指向const char类型 的指针,而实参是指向 char p类型的指针,由于两个指针的类型不一致,报错。

 

然后是例1:

本质上等价于*p = *ptr;

形参p指向const char类型的变量,实参是指向char类型的变量,两种变量的类型是一致的,且满足赋值语句的限制项的要求,不报错。

 

这里要理解两件事情:

1、 指针是不存在限制项的;

2、 函数形参传递类同于变量初始化;

例2中的“指针指向const char 的指针”这句话里面的“const char的指针”就是指针的类型,而实参的指针类型是“指向char 的指针”,两者的类型不一致,所以报错。而例1中的是实参传递给形参,是两个变量间的赋值操作,变量是有限制项。在例1中形参为char型变量,实参也为char型变量,两者均为char型变量,满足了c语言赋值操作的一个条件,而形参,即左操作符的有const限制项,实参没有,符合c语言中的赋值操作中的左操作符需要包含右操作符的限制项的要求。(这里的参考文献请看c89中关于赋值的介绍)

 

关于c语言的赋值需要满足以下的要求(C89)



以上均为一家之言,如果错误,恳请斧正。

 

                                                                                                                                                                                                                                                                                                                   写于2017-2-6午 深圳


### C语言中 `const` 修饰形参的作用和意义 #### 1. 防止意外修改传入参数 当函数的形参被声明为 `const` 类型时,表示该参数在函数体内不可更改。这有助于防止开发者无意间修改传递到函数中的数据[^2]。 ```c void printValue(const int arg) { // 下面这一行会引发编译错误,因为arg是一个只读变量 // arg = 20; printf("The value of arg is: %d\n", arg); } ``` 通过这种方式,程序的安全性和稳定性得到了提升,同时也减少了潜在的逻辑错误风险。 --- #### 2. 提高代码可读性与维护性 使用 `const` 可以清楚地表明某些参数不应该被修改,从而提高代码的可读性和清晰度。其他开发人员阅读代码时能够快速理解哪些值是不变的,进而更容易理解和调试代码[^3]。 --- #### 3. 改善性能优化的可能性 虽然现代编译器通常会对代码进行高度优化,但在某些情况下,标记为 `const` 的变量可能允许编译器做出更激进的优化假设。这是因为编译器知道这些值不会发生变化,因此可以在运行时减少不必要的计算或内存访问操作[^4]。 --- #### 4. 增强接口契约约束力 对于函数的设计者来说,在函数签名中标记某个参数为 `const` 是一种强有力的承诺:调用方可以放心地将重要数据传递给这个函数而无需担心其内容会被篡改。这种做法增强了 API 或库之间的信任关系[^1]。 --- #### 使用场景分析 以下是几种常见的使用场景: - **保护输入数据不被修改** 当函数只需要读取而不是修改外部提供的数据时,应该将其设置为 `const` 参数。例如字符串处理函数经常会接受 `const char*` 类型作为输入来确保原始字符串保持原样。 - **配合指针类型一起工作** 如果需要传递指向某对象或者数组的地址但又不想让接收端改变所指向的内容,则可以通过如下方式实现: ```c void displayArray(const int *arr, size_t length) { for (size_t i = 0; i < length; ++i) { printf("%d ", arr[i]); } printf("\n"); } int main() { int numbers[] = {1, 2, 3}; displayArray(numbers, sizeof(numbers)/sizeof(int)); return 0; } ``` 在这里,即使我们拥有对整个数组元素逐一打印的能力,也无法直接利用此方法去调整它们的实际数值。 - **结合返回值增强安全性** 有时还会遇到这样的需求——希望从某一特定功能获取的结果仅限于临时用途而不应长期保存下来供后续反复改动;此时就可以考虑采用带有 `const` 属性的方法重载形式加以区分对待。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值