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

为何MISRA C禁止修改函数形参但MISRA C++却允许?

为什么C++也应当禁止修改函数形参

MISRA C的现有规则

MISRA C规则17.8明确禁止在函数体内修改函数形参,这条规则的制定初衷很直接:C语言初学者经常会误解形参修改的实际语义,以为函数内改形参会影响调用方传入的原值。

MISRA C++的规则缺口

但MISRA C中并没有对应规则。实际上,“不要修改函数形参”这条实践准则在C里反而更有必要——C++支持引用传递,被调用函数可以直接修改调用方作用域的变量,很多时候形参列表里差一个&,就会导致完全相反的逻辑,甚至引发灾难性故障。

引用传递的预期行为

和C语言不同,C++里如果形参是引用类型,修改形参确实会同步修改调用方的原值,比如下面的代码逻辑是完全符合预期的:

void g(int32_t& x){
    if (x == 42) {
       x = 43; // 修改x避免触发后续崩溃逻辑
    }

    do_something(x);
}

void g_caller(void) {
    int32_t x = get_value();

    g(x);

    if (x == 42) {
        crash_and_burn();
    }
}

这段代码里,g接收x的引用,函数内把值为42的x改成43,调用方拿到的x也会变成43,不会触发crash_and_burn()。

值传递的隐蔽陷阱

如果把形参的引用符&去掉,变成值传递,行为就和C语言完全一致:函数内对形参的修改只会作用于本地副本,调用方完全感知不到。就这一个符号的差异,就会直接导致代码触发崩溃。
这类bug的诱因非常多,根本不是只有新手会踩:

  • 开发者是不是故意写逻辑要触发崩溃?
  • 是不是写代码时没注意当前形参是值传递,误以为修改会同步到外部?
  • 会不会是早期版本里x是引用传递,后续接口迭代改成了值传递,开发者只记得要在函数里改x防崩溃,没注意接口已经变了?
    很多有经验的C++开发者也会在这个点上翻车。对应的值传递错误代码如下:
void g(int32_t x){
    if (x == 42) {
       x = 43; // 仅修改本地副本,调用方的x不会变化
    }

    do_something(x);
}

void g_caller(void) {
    int32_t x = get_value();

    g(x);

    if (x == 42) {
        crash_and_burn(); // 必然触发,和预期逻辑完全相反
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 23:09:23