将指针存储在函数中数组参数的文件范围内的数组中

时间:2012-07-03 14:10:46

标签: c misra

我正在重建一个符合MISRA规则的应用程序,并使用QA-C来分析我的代码。

其中一个恼人的规则涉及指针和数组。 你不能说:

char foo[10];
char * bar = &(foo[0]);

bar[5] = 'a';

你也不能这样做:

*bar = 'a';
bar++;

我的问题涉及两个函数和一个文件范围变量。

最初这段代码执行了以下操作(类比特伪代码):

static char * bufferPtr;

static void foo_a(char * buffer /* other params */)
{
    bufferPtr = buffer;

    /* some logic goes here */
    switch()
    {
        case 'b':
           foo_b(/* some param */);
}

static void foo_b(/* parameters */)
{
    if (/*something*/)
    {
        /*  some logic */
        foo_c(/* data-param */);
        /* some logic */
    }
    else
    {
        /*  some logic */
        foo_c(/* data-param */);
        /* some logic */
    }
}

static void foo_c(char data)
{
    *buffer++ = data;
}

我试图将其重写为以下内容:

static char (*bufferPtr)[];
static char bufferIndex;

static void foo_a(char buffer[] /* other params */)
{
    bufferPtr = &buffer;
    bufferIndex = 0;

    /* same */
}

static void foo_b(/* parameters */)
{
    /* same */
}

static void foo_c(char data)
{
    (*bufferPtr)[bufferIndex] = data;
    bufferIndex++;
}

然后,misra和我的编译器(softits,由Fujitsu)抱怨。 编译说:

  

CHAR **' to CHAR(*)[]'赋值不兼容的指针类型:operator` ='

米斯拉说:

  

[C]赋值的右操作数不兼容指针类型。   导出到具有链接或更宽范围的指针的自动对象的地址。

但是我确实需要能够在foo_c函数中索引数组。或者是否有其他方法来遵循misra并使我的代码有效。

如果我在同一个文件中执行以下操作:

static CHAR foo[10];
static CHAR (*bar)[];
static void f(void)
{
    bar = &foo;
}

然后,Misra和我的编译器都没有抱怨任何事情。

5 个答案:

答案 0 :(得分:0)

这对我来说没有意义:

static char (*bufferPtr)[];
static char bufferIndex;

我会这样做:

static char *bufferPtr_new;
static int bufferIndex_new;

用bufferPtr_new替换每个* bufferPtr [bufferIndex_new] 但根据MISRA的说法,也许向我们解释当前代码有什么问题。

答案 1 :(得分:0)

不确定你是否会喜欢这个:

static char *(bufferPtr[10]); /* must have a size */
static char bufferIndex;

static void foo_a(char buffer[])
{
    *bufferPtr = buffer;
    bufferIndex = 0;
    /* etc */ 
}

希望它有所帮助。

答案 2 :(得分:0)

static void foo_a(char * buffer /* other params */)

参数buffer是一个指针,而不是一个数组,因此尝试将其视为其他地方的数组将会失败。

明智的做法是让foo_a接受指向数组的指针(某些N为char (*buffer)[N])或指向包含适当大小数组的struct的指针。然后,您可以将文件分配给静态char (*bufferPtr)[N]或(更好)通过调用链传递数组指针。

答案 3 :(得分:0)

  

其中一个恼人的规则涉及指针和数组。你不能说:....

char foo[10];

非常好,除了不允许的字符类型。

char * bar = &(foo[0]);

如果使用数组语法声明foo,则很好。如果使用指针语法声明了foo,则它违反了规则17.4。请参阅下面的规则17.4的修复程序。 此外,对于MISRA和其他原因,括号都没有任何意义。

bar[5] = 'a';

非常好。

*bar = 'a';

非常好。

bar++;

规则17.4不允许这样做,它规定数组索引是唯一允许的指针算术形式。这确实是一个非常愚蠢的规则,我相信它将在下一版MISRA中删除。我实际上曾经与委员会讨论过这条规则,除了化妆品之外,他们无法给出任何理由。

解决方案是为此规则创建与MISRA-C的偏差,这是大多数MISRA实现似乎所做的。不要盲目跟随MISRA。 90%的规则都很好,但有些奇怪的规则缺乏理由。

答案 4 :(得分:0)

我已将此代码的流程更改为仅将缓冲区参数传递给每个后续版本。

它很难看,但它有效并且有些安全。 '根据misra'