首页 > 解决方案 > 为什么 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];”,编译器会显示错误。(因为负长度的字符串没有意义)。但是,如果将此代码的第 7 行(我声明 const MAX_LENGTH)替换为第 8 行注释中编写的代码(其中 MAX_LENGTH 被分配了 -ve 值),则不会出现编译错误。为什么?

另外,为什么声明零长度字符串没有错误。零长度字符串如何对编译器有意义但对负长度字符串没有意义?

标签: cstringgcc

解决方案


因为这不是一回事。

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

编译器在第二种情况下在运行时进行分配(使用这个-100值它不会很好地结束),因为const在 C 中它并不是一个真正的常量,它只是告诉编译器你不要改变这个值(并且还允许一些优化)。所以结果是未定义的行为(更多在这里:声明一个负长度数组

如果您想要相同的行为,请使用#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];

至于零长度元素,不需要重复已经回答过的内容:零元素数组需要什么?(简而言之,在结构的末尾可以有不同的长度很有用)


推荐阅读