代码之家  ›  专栏  ›  技术社区  ›  MaSc. H.

大小与阵列大小

  •  1
  • MaSc. H.  · 技术社区  · 4 月前

    我有一个关于 sizeof() 操作员。显然,在浏览用C编写的开源项目时,一些开发人员倾向于使用 size() 运算符在一个位置和另一个位置显示文字数组大小。

    例如,有这样编写的代码:

    ...
    char   buf[2048];
    
    memset(buf, 0, sizeof(buf));
    
    ... = snprintf(buf, 2048, ...);
    
    ...
    

    开发者使用 sizeof(buf) 对于 memset() 但引用了文字缓冲区大小 2048 直接到 snprintf() 而不是坚持 size(buf) .这只是编写代码时的一个坏习惯/不一致吗 size() 不适合以下功能 snprintf() ?

    我经常看到这个,真的很想知道,为什么不总是使用 size() 在这种情况下?这难道不会简化代码的维护吗?想象一下 snprintf() 如果调用被放置在函数体中更低的位置,开发人员将函数顶部的缓冲区大小更改为例如1024, memset() 会抓住变化,但 snprintf() 可能会导致溢出。

    2 回复  |  直到 4 月前
        1
  •  8
  •   Andreas Wenzel    4 月前

    对数组大小或长度进行硬编码确实是一种有风险的习惯,因为如果数组长度更改为较小的值并且代码没有得到一致的更新,代码可能会变得不正确。

    使用 sizeof(buf) countof(buf) 定义为

    #define countof(a) (sizeof(a)/sizeof(*(a)))
    

    建议使用,但如果 buf 未在函数调用的范围内定义为数组。如果 缓冲器 是作为函数参数接收的指针, size(buf) 将是指针的大小,而不是它指向的数组的大小。使用数组语法指定函数参数的情况尤其令人困惑:

    void initialize_array(char buf[1024]) {
        // BUG! sizeof(buf) is sizeof(char *), much less than 1024
        memset(buf, 0, sizeof(buf));
    }
    

    C标准没有提供一种简单的方法来评估实际数组的数组长度,因此我建议使用这种方法:

        ...
        char buf[2048];
        const size_t buf_size = sizeof(buf); // always next to the array definition
        
        memset(buf, 0, buf_size);
        
        ... = snprintf(buf, buf_size, ...);
        
        ...
    

    编译器将消除 buf_size 变量并生成最优代码。如果你收到 缓冲器 作为一个参数,这个习惯用法将确保您还可以获得缓冲区大小或长度作为额外的参数。

    对于大于的类型 char ,最好传递数组长度并命名 buf_length buf_count 更安全:

        ...
        int buf[2048];
        const size_t buf_count = sizeof(buf) / sizeof(*buf);
        
        memset(buf, 0, buf_count * sizeof(*buf));
        
        for (size_t i = 0; i < buf_count; i++) {
            if (handle_case(i))
                bur[i] = 1;
        }
        ...
    
        2
  •  3
  •   Lundin    4 月前

    这只是编写代码时的坏习惯/不一致吗

    是的,代码使用了“幻数”等不良做法。它在使用硬编码大小和 sizeof 这太草率了。

    编写可读/可维护代码的正确方法是:

    #define BUF_SIZE 2048  // [comment about why 2048 was picked goes here]
    
    ...
    char buf[BUF_SIZE];
    
    memset(buf, 0, BUF_SIZE );
    
    ... = snprintf(buf, BUF_SIZE, ...);
    

    在这里 BUF_SIZE 始终如一地使用 每一次 我们需要缓冲区的大小。 KISS principle -没有胡闹,没有程序员通过使程序变得不必要的复杂来“冒充”他们对C的知识。


    sizeof()的使用是否不适合snprintf()等函数

    不使用 size 理论上应该没问题,但既然我们已经有了 BUF_SIZE ,该常数应在正确编写的程序中始终使用。

    程序员用 size 众所周知,bug的来源不是保持代码简单。