我在Code :: Block IDE上得到了一个“警告:数组下标有类型'char'”?

时间:2017-09-03 19:45:46

标签: c

当我运行这个可变参数函数时,我收到警告array subscript has type 'char',然后它崩溃了。我怀疑问题发生在while循环的某个地方。我已经尝试了很多方法来防止这个函数崩溃。例如:我尝试将(argp, char)更改为(argp, int),但这不会产生正确的输出。我也不允许改变原型功能。请帮忙!

char fancyMostFrequentChar(char c, ...) {
    char j;
    int max = 0;
    int fre[255] = { 0 };
    char temp;
    va_list argp;

    if (c == '\0')
        return '\0';
    va_start(argp, c);

    //This for loop will run through the arguments
    //and record their frequencies into fre[] array
    while ((temp = va_arg(argp, char)) != '\0') {
        ++fre[temp];
        if (fre[temp] > max) {
            max = fre[temp];
            j = temp;
        }
    }
    va_end(argp);

    return j;
}

3 个答案:

答案 0 :(得分:2)

你绝对应该temp unsigned char或使用强制转换来使用它来索引数组fre。默认情况下,char可以并且通常是签名的,因此任何负值都可以访问数组边界之外。顺便说一句,您应该将fre一个项目放大,以适应所有8位值,包括255

请注意,您不计算第一个参数,因此fancyMostFrequentChar('a', 'b', 'a', '\0')将返回'b'而不是'a'

另请注意(由M.M评论)第一个参数应定义为intva_start具有已定义的行为:

  

7.16.1.4 va_start

     

<强>概要

#include <stdarg.h>
void va_start(va_list ap, parmN);
     

<强>描述

     

在访问未命名的参数之前,应调用va_start宏。

     

va_start宏初始化ap以供va_argva_end宏后续使用。 [...]

     

参数parmN是函数定义中变量参数列表中最右边参数的标识符(就在......之前)。如果使用parmN存储类,函数或数组类型声明参数register,或者使用与应用默认参数提升后生成的类型不兼容的类型,则行为char fancyMostFrequentChar(char c, ...)未定义。

你提到你不应该改变原型......不幸的是,发布char fancyMostFrequentChar(int c, ...) { int fre[256] = { 0 }; char temp, res = (char)c; if (res != '\0') { va_list argp; va_start(argp, c); ++fre[(unsigned char)res]; //This for loop will run through the arguments //and record their frequencies into fre[] array while ((temp = va_arg(argp, char)) != '\0') { if (++fre[(unsigned char)temp] > fre[(unsigned char)res]) { res = temp; } va_end(argp); } return res; } 的原型不能用于访问第一个之后的参数。

以下是更正后的版本:

@Query("SELECT d FROM Data d WHERE ((?2) IS NULL OR d.categories IN (?2))")

答案 1 :(得分:1)

va_arg(argp, char)是未定义的行为。 va_arg宏的使用要求类型在default argument promotions下保持不变 - 这意味着您不能使用float,也不能使用比int更窄的任何整数类型。 (字符类型是整数类型)。参考:C11 7.16.1.1/2

va_start的第二个参数设置为在默认参数提升下更改的类型,也是未定义的行为。因此,实际上无法正确访问声明为char fancyMostFrequentChar(char c, ...)的函数的可变参数。

要解决此问题,您必须更改该功能的原型,例如:

char fancyMostFrequestChar(int c, ...)

并且循环的相关部分应为:

int temp;

while ((temp = va_arg(argp, int)) != '\0')
{
    unsigned char index = (unsigned char)temp;

然后使用index作为数组索引。然后保证在1UCHAR_MAX范围内(通常为255)。对于迂腐的正确性,您可以将数组定义更改为int fre[UCHAR_MAX+1]

答案 2 :(得分:0)

你的代码有很多问题,我希望我能抓住所有问题。

unsigned char fancyMostFrequentChar(unsigned char c, ...) // resolve ambigity of char
{
    unsigned char j = '\0';   // was not initialized 
    int max = 0;
    int fre[256] = {0};    // max unsigned char is 255 -> array length = 256 (0..255)
    unsigned char temp;
    va_list argp;

    if (c == '\0')
        return '\0';
    va_start(argp, c);

    //This for loop will run through the arguments
    //and record their frequencies into fre[] array
    while ((temp = va_arg(argp, unsigned char)) != '\0')
    {
        ++fre[temp];
        if (fre[temp] > max)
        {
            max = fre[temp];
            j = temp;
        }
    }

    va_end(argp);

    return j;
}