C++ 中固定长度的数组作为参数,编译器能越界检查吗 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
iqoo
V2EX    程序员

C++ 中固定长度的数组作为参数,编译器能越界检查吗

  •  
  •   iqoo 2023-03-13 11:40:42 +08:00 2755 次点击
    这是一个创建于 945 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如下代码:

    void F(char x[10]) { char y[10]; y[11] = 0; // warning: array index 11 is past the end of the array x[11] = 0; } 

    数组 y 越界访问时编译器会给出告警,但 x 却不会,因为编译器会忽略参数数组的长度,是否有方案可让编译器检查参数数组的长度?

    20 条回复    2023-03-13 23:24:45 +08:00
    Noicdi
        1
    Noicdi  
       2023-03-13 12:10:37 +08:00 via iPhone
    你把 y 修改正确,x 依旧保持错误,看看会不会有警告呢?
    我下意识的猜想是,按顺序警告
    Thymolblue
        2
    Thymolblue  
       2023-03-13 12:11:58 +08:00 via Android
    好像是你这个函数并不会把数组长度这个信息传进去。下面这样可以把数组的长度传进去。我的编译器是 MinGW 7.3.0
    template <typename T>
    void foo(T &t)
    {
    // 可以直接使用迭代器迭代整个数组
    for (auto &item: t)
    {
    item = 0;
    }
    t[11] = 0; // 传一个长度为 10 的数组这里会触发警告
    }
    Thymolblue
        3
    Thymolblue  
       2023-03-13 12:12:29 +08:00 via Android
    @Thymolblue 手机编辑排版乱了,见谅
    sosilver
        4
    sosilver  
       2023-03-13 12:12:54 +08:00 via Android
    函数参数是 T*,不是 T[N],试试传 reference
    geelaw
        5
    geelaw  
       2023-03-13 12:19:04 +08:00   9
    因为 C 的缘故,void foo(char x[10]) 和 void foo(char *x) 是一个意思。要传递数组引用而不是指针的话,应该 void foo(char (&x)[10])。
    VZXXBACQ
        6
    VZXXBACQ  
       2023-03-13 12:21:23 +08:00
    这种情况传递引用可解
    ALLROBOT
        7
    ALLROBOT  
       2023-03-13 12:25:29 +08:00
    @geelaw C++还有这种用法,写起来真是麻烦。。。

    请问一般开发建议用什么标准的 C++?虽然写起来是麻烦了点,但跑起来挺快的
    SMGdcAt4kPPQ
        8
    SMGdcAt4kPPQ  
       2023-03-13 12:33:27 +08:00 via Android
    用 std::array
    tyzandhr
        9
    tyzandhr  
       2023-03-13 12:34:00 +08:00 via Android
    为什么不用 span 呢?
    tool2d
        10
    tool2d  
       2023-03-13 12:36:57 +08:00
    还是用 std::vector 中括号操作符重载吧,重载在 debug 时候检测一下越界问题。

    这裸指针直接赋值,也太吓人了。
    yolee599
        11
    yolee599  
       2023-03-13 12:38:18 +08:00 via Android
    形参的 x[10] 完全等同于 *x ,指针不能确定数组大小
    yolee599
        12
    yolee599  
       2023-03-13 12:40:44 +08:00 via Android
    通常做法是再加一个形参来描述数组大小:
    void F(char *x, int len)
    leonshaw
        13
    leonshaw  
       2023-03-13 12:42:51 +08:00
    数组、std::array, std::span, std::vector 越界都是 UB ,告警是编译器的行为。
    tool2d
        14
    tool2d  
       2023-03-13 12:48:20 +08:00
    5 楼的代码很完美,但我总觉得看着好奇怪哦。

    nightwitch
        15
    nightwitch  
       2023-03-13 13:39:33 +08:00 via Android
    没什么特殊理由不要用 c style arr ,用 std::array 有效消除这种问题
    pipapa
        16
    pipapa  
       2023-03-13 14:08:04 +08:00
    有工具是可以扫描出来的,这种应该编码应该强制传长度参数进去
    rozbo
        17
    rozbo  
       2023-03-13 14:59:17 +08:00
    一个指针哪来的长度。。你得传数组的引用
    daveh
        18
    daveh  
       2023-03-13 15:39:06 +08:00 via iPhone
    试试用 CLion ,Inspections - Data flow analysis 里面有专门的数组越界检查,能查出问题。
    另外确实如前面有 V 友所说,函数入参并不是你想的那样,有可能你传入的数组够长,所以后一个编译器没法识别出问题。
    但 CLion 的 Data flow analysis ,会识别调用 F(x)的上下文,如果你传入数组 x 不够长,后一个也会报数组越界;如果 x 长度够则不报问题;如果没有 F 的函数调用,也不报问题。
    LuffyWong
        19
    LuffyWong  
       2023-03-13 17:44:24 +08:00
    最近刚好在读 the c++ programming language, 刚好 12.2.2 讲到了这个
    lzyliangzheyu
        20
    lzyliangzheyu  
       2023-03-13 23:24:45 +08:00 via Android
    数组传参会退化为指针,会丢失数组的大小信息,至少 C 是这样的,一般都是把数组当成指针传过去,至于数组的大小再单独一个参数传过去,至于 CPP 有没有什么更高级的特性就不清楚了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1073 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 23:03 PVG 07:03 LAX 16:03 JFK 19:03
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86