双指针函数参数什么时候需要加 const,什么时候不能加?

我的理解是:如果函数的目的是修改输入参数代表的指针的值,则加 const 更安全;如果函数的目的是为了修改输入字符数组的内容,就不能加 const。

测试代码:

#include <stdio.h>
#include <string.h>
 
void parameter_no_qualifier_const_is_to_modify_chararray_contents(char** p_array);
void test__parameter_no_qualifier_const_is_to_modify_chararray_contents();
 
void parameter_with_qualifier_const_is_to_modify_pointer_value(const char** pp);
void test__parameter_with_qualifier_const_is_to_modify_pointer_value();
 
int main()
{
    test__parameter_no_qualifier_const_is_to_modify_chararray_contents();
 
    test__parameter_with_qualifier_const_is_to_modify_pointer_value();
 
    return 0;  
}
 
void parameter_no_qualifier_const_is_to_modify_chararray_contents(char** p_array)
{
    // 如果函数参数形式为 const char** p_array,则下面紧跟的行会编译出错:
    //   error C2440: “初始化”: 无法从“const char *”转换为“char *”
    char* array = *p_array;
    *array++ = 'c';
    *array++ = 'h';
    *array++ = 'i';
    *array++ = 'j';
    *array++ = 'k';
    *array = '\0';
 
    // 或,以下面的方式改变数组各元素的值。
 
    // 如果函数参数形式为 const char** p_array,则下面 4 行都会编译出错:
    //     error C3892: “p_array”: 不能给常量赋值
    // (*p_array)[0] = 'c';
    // (*p_array)[1] = 'h';
    // (*p_array)[2] = 'i';
    // (*p_array)[3] = 'j';
    // (*p_array)[4] = 'k';
    // (*p_array)[5] = '\0';
 
    // (*p_array)++;
}
 
void test__parameter_no_qualifier_const_is_to_modify_chararray_contents()
{
    char array[10] = {'a', 'e', 'f', '\0', 'x', 'y', 'z', '\0'};
    printf("%s\r\n", array); // aef
 
    char* p_array = array;
    parameter_no_qualifier_const_is_to_modify_chararray_contents(&p_array);
    printf("%s\r\n\r\n", array); // chijk
}
 
void parameter_with_qualifier_const_is_to_modify_pointer_value(const char** pp)
{
    // pp 的类型是 const char**,即 char const**,非常量。因函数参数是按值传递,所以内部修改不影响原值。
    // *pp 的类型是 const char*,即 char const*,非常量。函数内部可间接修改之。
    // **pp 的类型是 const char,即 char const,常量。编译器禁止修改其值。
 
    (*pp)++;
    // **pp = 'Q'; // error C3892: “pp”: 不能给常量赋值
}
 
void test__parameter_with_qualifier_const_is_to_modify_pointer_value()
{
    char* p = "AXY";  
    printf("%s\r\n", p); // AXY
 
    // error C2664: “parameter_use_qualifier_const_is_to_modify_pointer_value”: 不能将参数 1 从“char **”转换为“const char **”
    // parameter_with_qualifier_const_is_to_modify_pointer_value(&p);
 
    // 可编译通过的 C 风格强制类型转换
    parameter_with_qualifier_const_is_to_modify_pointer_value((const char**)&p);
    printf("%s\r\n\r\n", p); // XY
 
 
    char* p2 = "axy";  
    printf("%s\r\n", p2); // axy
 
    // 等价且正确的 C++ 风格强制类型转换是用:const_cast
    parameter_with_qualifier_const_is_to_modify_pointer_value(const_cast<const char**>(&p2));
    printf("%s\r\n\r\n", p2); // xy
 
 
    // char* p3 = "axy";
    // error C2440: “static_cast”: 无法从“char **”转换为“const char **”  
    // parameter_with_qualifier_const_is_to_modify_pointer_value(static_cast<const char**>(&p3));
 
 
    // char* p4 = "axy";  
    // error C2680: “const char **”: dynamic_cast 的目标类型无效
    // parameter_with_qualifier_const_is_to_modify_pointer_value(dynamic_cast<const char**>(&p4));
 
 
    // char* p5 = "axy";
    // error C2440: “reinterpret_cast”: 无法从“char **”转换为“const char **”
    // parameter_with_qualifier_const_is_to_modify_pointer_value(reinterpret_cast<const char**>(&p5));
 
 
    // 如果是 char ()[],而不是 char*。那么,。。。
 
    char p6[] = "DXY";  
    printf("%s\r\n", p6); // DXY
 
    // error C2664: “parameter_with_qualifier_const_is_to_modify_pointer_value”: 不能将参数 1 从“char (*)[4]”转换为“const char **”
    // parameter_with_qualifier_const_is_to_modify_pointer_value(&p6);
 
    // 输入参数是数组情况下,还想修改指针的值,向上面那样就不行了(数组名的值是不能被修改的)。
    // 可编译通过的 C 风格强制类型转换
    parameter_with_qualifier_const_is_to_modify_pointer_value((const char**)(&p6));
    printf("%s\r\n\r\n", p6); // EXY (?因为:'E' = 'D' + 1)
 
 
    // 正确的做法是:
    char* p6_ = p6;
    printf("%s\r\n", p6_); // EXY  
    parameter_with_qualifier_const_is_to_modify_pointer_value((const char**)(&p6_));
    printf("%s\r\n\r\n", p6_); // XY  
 
 
    // char p7[] = "dxy";
    // error C2440: “const_cast”: 无法从“char (*)[4]”转换为“const char **”
    // parameter_with_qualifier_const_is_to_modify_pointer_value(const_cast<const char**>(&p7));
 
 
    // char p8[] = "dxy";
    // error C2440: “static_cast”: 无法从“char (*)[4]”转换为“const char **”
    // parameter_with_qualifier_const_is_to_modify_pointer_value(static_cast<const char**>(&p8));
 
 
    // char p9[] = "dxy";
    // error C2680: “const char **”: dynamic_cast 的目标类型无效
    // parameter_with_qualifier_const_is_to_modify_pointer_value(dynamic_cast<const char**>(&p9));
 
 
    char p10[] = "dxy";  
    printf("%s\n", p10); // dxy
 
    // 可编译通过但错误的 C++ 风格强制类型转换是用:reinterpret_cast
    parameter_with_qualifier_const_is_to_modify_pointer_value(reinterpret_cast<const char**>(&p10));
    printf("%s\n\n", p10); // exy (?因为:'e' = 'd' + 1)
 
 
    char* p10_ = p10;  
    printf("%s\n", p10_); // exy
    parameter_with_qualifier_const_is_to_modify_pointer_value(const_cast<const char**>(&p10_));
    printf("%s\n\n", p10_); // xy
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值