【问题标题】:warning: array subscript has type ‘char’ [-Wchar-subscripts]警告:数组下标的类型为“char”[-Wchar-subscripts]
【发布时间】:2015-02-13 23:47:22
【问题描述】:

当我使用gcc -Wall 运行我的程序时,我得到了

warning: array subscript has type ‘char’

请帮助我哪里出了问题。警告说它在第 20:7 和 21:7 行。我怎样才能摆脱警告?

/* This program asks the user for 2 words and tells the user if those 2 words
   are anagrams even if its capitalized or not. The maximum length of letters
   is 20.  */

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

int anagram(char* str1, char* str2)
{
    // Create two count arrays and initialize all values as 0
    int numOfChar = 20;
    char count1[123] = {0};
    char count2[123] = {0};
    int i;

    /* For each character in the strings, it increases in
       the corresponding count array */
    for (i = 0; str1[i] && str2[i];  i++)
    {
        count1[str1[i]]++;
        count2[str2[i]]++;
    }

    // If both strings are different lengths.
    if (str1[i] || str2[i]) // If one statement is true
    {
        return 0;
    }

    // Compares count arrays
    for (i = 0; i < numOfChar; i++)
    {
        if (count1[i] != count2[i]) // If dont equal to eachother
        {
            return 0;
        }

    }
    return 1;

}

// Construct function
void construct()
{
    int anagram(char*,char*); // Variables
    char str[20], str1[20];
    int check = 0;

    printf("Please enter the first word: ");
    scanf("%s", str);

    printf("Please enter the second word: ");
    scanf("%s", str1);


    check=anagram(str, str1);
    if (check==1)
    {               // If true then print
        printf("%s is an anagram of %s\n", str, str1);
    }
    else
    {               // If false then print
        printf("%s is NOT an anagram of %s\n", str, str1);
    }

    return ;
}

// Main function
int main()
{
  construct(); // Calls construct function
  return 0;
}

【问题讨论】:

  • 您可以将chars 转换为intsize_t
  • 快速修复count1[(int)str1[i]]++;
  • 我已经编辑了你的标题。标题是一条错误消息,但您将其更改为混合大小写。 C 和 gcc 命令行选项都区分大小写; Charchar 不同。

标签: c arrays string char gcc-warning


【解决方案1】:

问题是字符串可能包含来自非 us 字符集的字符(除了 us-ascii 之外的任何编码)。

表示为负值。我认为使用负索引访问数组并不完全符合您的期望。

将其处理为:

    count1[(unsigned char)str1[i]]++;
    count2[(unsigned char)str2[i]]++;

会抑制警告,但仍然会出现越界问题。

在 for 循环中添加以下检查将终止循环,以防字符值完全意外:

 str1[i] && str2[i] &&
 (unsigned char)str1[i] < countof(count1) &&
 (unsigned char)str2[i] < countof(count2)

其中countof定义为:

#define countof(x) sizeof(x)/sizeof(x[0])

【讨论】:

  • 情况比这更微妙。在某些平台上,纯 char 是有符号类型(如您所描述的),而在其他平台上,它是无符号类型。因此,当字符超出 7 位 ASCII 范围时,您无法确定索引是正值还是负值。因此,负索引(确实)是一个问题,但并非所有编译器都会遇到问题。但这就是出现警告的原因(在两种类型的平台上,AFAIK),以及为什么需要 (unsigned char) 强制转换(或等效操作)。它不仅修复了警告;它确保您访问正确的数据。
  • @JonathanLeffler 正确的解决方法是尽可能使用unsigned char *。理论上,演员表可以破坏字符的按位表示。假设字符具有位模式 10000001(代码 129),但 signed char 表示为 8 位符号大小:10000001 因此具有值 -1。但是(unsigned char) -1 会产生11111111,它是 255,而不是 129。
【解决方案2】:

编译器会向您发出关于第 20 行和第 21 行的索引的警告

count1[str1[i]]++;
count2[str2[i]]++;

可疑的索引来自函数参数。

int anagram(char* str1, char* str2)

请注意,它们指向 char 类型,默认情况下已签名。因此,如果您用于索引count1[] 的数组的一个元素的值在0x800xFF 的范围内,这将导致使用负索引,这显然不在数组@987654327 的范围内@。

虽然 count1[]count2[] 只有 123 个元素,所以您不会期望索引实际上是负数,但最好让数组通过 unsigned char,所以该函数将被声明为

int anagram(unsigned char* str1, unsigned char* str2)

那么你总是会得到一个积极的指数。至于警告,MSVC 没有给我一个警告,但是如果您随后将索引转换为int,正如您的问题下方所评论的那样,那应该会处理它。

【讨论】:

  • char 默认不是无符号的。 char 是有符号还是无符号是由实现定义的。
  • @Rob 这是真的。我应该说在我的实现中char 是默认签名的。
【解决方案3】:

编译器给出这样一个警告的原因是,当x[index] 其中index 是一个字符类型时,通常是一个编程错误。

如果这是您想要的,只需强制转换为int。例如,在您的代码中,count1[(int)str1[i]]++;

请记住,打印数字 '1' 的字符在数字上不等于 1。忘记这一点并假设它确实是编译器警告将拾取的常见错误之一。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多