【问题标题】:Correct size of static array正确的静态数组大小
【发布时间】:2013-10-10 15:49:21
【问题描述】:

我有一个可以工作的函数,但我想知道为什么static char out[0]; 在需要在范围内静态分配内存时不会产生警告?在此示例中,out 的大小的正确值是多少?:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *hex(char *s)
{
    int i, l = (int)strlen(s);
    static char out[0]; // should it be 7 ?
    for(i = 0; i < l; i++) {
        s[i] -= 5;
        sprintf(&out[i*6], "0x%02x, ", (unsigned char)s[i]);
    }
    return out;
}

int main(void)
{
    char s[] = "hello";
    printf("%s", hex(s)); // 0xa8, 0xa5, 0xac, 0xac, 0xaf, 
    return 0;
}

【问题讨论】:

    标签: c string memory static


    【解决方案1】:

    据我所知,没有任何 C 编译器会针对越界数组访问发出警告。你自己来确保数组索引在界限内。

    【讨论】:

      【解决方案2】:

      我认为你必须使用 malloc 动态分配:

      char *out = malloc(6 * strlen(s) + 1); // 6 = strlen("0xXX, ")
      

      而且别忘了在你使用后释放“out”

      【讨论】:

      • 为了清楚起见,您必须在分配的大小上加 1,因为 C 字符串必须以空值结尾:en.wikipedia.org/wiki/Null-terminated_string
      • 对 \0 使用 malloc + 1 是我可以使用的另一个选项。我想尝试另一种使用静态内存的方式来看看发生了什么。这是一个很好的提示,谢谢。
      【解决方案3】:

      为什么是静态字符输出[0];不抛出警告

      这是undefined behavior 指定一个零大小的数组,编译器没有义务在这种情况下产生诊断。如果我们查看C99 draft standard 部分6.7.5.2 数组声明符 段落1 说(强调我的):

      [..]如果他们分隔了一个表达式(它指定了一个数组的大小),那么 表达式应具有整数类型。 如果表达式是一个常量表达式,它的值应该大于零.[...]

      尽管在这种情况下gcc 会警告您,如果您使用-pedantic 标志,我会收到以下警告:

      警告:ISO C 禁止零大小数组“输出”[-pedantic]

      如果它也 undefined 访问数组越界,这里同样适用于警告。

      如果我们查看第 2 段中3.4.3 部分中未定义行为的定义,则表示(强调我的):

      注意可能的未定义行为范围从完全忽略具有不可预测结果的情况到在翻译或程序执行期间以环境特征的记录方式表现(有或没有发出诊断消息) , 终止翻译或执行(发出诊断消息)。

      使用static 变量作为输出是一个有问题的设计,这意味着该方法的每个调用者都将共享相同的输出。更好的选择是使用 malloc 动态分配内存,这意味着您必须记住在完成后释放内存。

      【讨论】:

      • 零大小的数组不是为什么这不会引发警告。 ideone.com/ejmIdU
      • 好吧 malloc 是上帝,我有第一个问题的答案,谢谢。对于第二个问题,我不应该使用零,那么正确的值是多少?为了我的理解,我打算在这种情况下使用静态字符。
      • @HansZ 有多个问题,此时我想我已经解决了所有问题。如果您有更具体的问题,请告诉我。
      • @pipe3r 您必须确定所需的最大空间,在这种情况下这似乎是不可能的,除非您对函数施加最大限制。
      • 有趣的是,我启动了 Visual Studio 2008 的旧副本,char out[0]; 是与 Ideone 使用 gcc 相比的编译器错误,我刚刚在自己的机器上使用 gcc 进行了验证。我要回家用 armcc 试一试,看看我们得到了什么。 (另外,是的,总是使用 malloc 或 new,如果你做的事情太复杂以至于你都不能使用,那么你做错了)。
      猜你喜欢
      • 1970-01-01
      • 2018-01-24
      • 2014-07-21
      • 1970-01-01
      • 2017-05-23
      • 2012-03-18
      • 2012-05-04
      • 1970-01-01
      • 2011-09-11
      相关资源
      最近更新 更多