为什么GCC编译器允许我们声明零长度的字符串(直接)和负长度的字符串(间接)?

时间:2018-08-21 09:50:57

标签: c string gcc

/*implementation of strrev i.e. string reverse function*/

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

/*length of the string i.e. cells in the string*/
static const unsigned int MAX_LENGTH = 100;
//static const int MAX_LENGTH = -100;

/*reverses the string*/
void reverseString(char[]);
/*swaps the elements in the cells of a string*/
void swap(char[], int, int);

/*runs the program*/
int main()
{
    char string[MAX_LENGTH];
    //char string[0];  //no error!
    //char string[-1]; //error! 

    gets(string);
    reverseString(string);
    printf("\n%s", string);

    return 0;
}

void reverseString(char string[])
{
    int i;
    for(i = 0; i < (strlen(string) / 2); i++)
    {
        swap(string, i, (strlen(string) - 1 - i));
    }
}

void swap(char string[], int i, int j)
{
    int temp = string[i];
    string[i] = string[j];
    string[j] = temp;
}

查看主要功能。如果替换第一行“ char string [MAX_LENGTH];”如果使用“ char string [-1];”,编译器将显示错误。 (因为负长度的字符串没有意义)。但是,如果用第8行的注释(其中MAX_LENGTH被指定为-ve值)中的代码替换该代码的第7行(我在其中声明const MAX_LENGTH),则不会出现编译错误。为什么?

此外,为什么声明零长度字符串没有错误。零长度字符串对编译器有意义,而对负长度字符串无效吗?

1 个答案:

答案 0 :(得分:4)

因为不是同一回事。

  • 在第一种情况下,您将使用固定的编译时大小来定义数组
  • 在第二种情况下,您要定义一个可变长度数组或VLA。

在第二种情况下,编译器在运行时进行分配(使用此-100值将不能很好地结束),因为const实际上不是C中的常数,它只是告诉编译器您不需要更改值(并且还可以进行一些优化)。因此结果是未定义的行为(更多信息:Declaring an array of negative length

如果您想要相同的行为,请使用#define

 #define MAX_LENGTH -100    // will raise a compilation error

或注释中建议的枚举常量

enum { MAX_LENGTH = -100 };    // will raise a compilation error

如果要保护声明,请使用assert

assert(MAX_LENGTH > 0);
char string[MAX_LENGTH];

对于零长度元素,无需重复已经回答的问题:What's the need of array with zero elements?(简而言之,在结构的末尾具有可变长度是很有用的)