c - 为什么 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 值),则不会出现编译错误。为什么?
另外,为什么声明零长度字符串没有错误。零长度字符串如何对编译器有意义但对负长度字符串没有意义?
解决方案
因为这不是一回事。
- 在第一种情况下,您正在定义一个数组,使用固定的编译时大小
- 在第二种情况下,您正在定义一个可变长度数组或 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];
至于零长度元素,不需要重复已经回答过的内容:零元素数组需要什么?(简而言之,在结构的末尾可以有不同的长度很有用)
推荐阅读
- tensorflow - 如何生成 N 堆随机张量?
- javascript - 单个请求多次调用下载处理程序(php 代码)
- java - 在 Parent 和 Child 类中创建相同的方法会提供一些奇怪的输出
- swift - 如何使用 SwiftUI 显示 UIImage?
- angular - 适用于多种角度环境的 Azure Devops
- html - 如何根据 django 中的查询创建用于提供多个对象条目的表单?
- spring - 从 ftp 读取大型 csv 文件时,Spring 集成堆空间错误
- vb.net - 在生产环境中部署后如何修复 System.InvalidCastException
- video - 如何使按钮(或矩形)浮动在 Corona SDK 中来自摄像头的实时视频上
- android - 我正在尝试在我的 android 应用程序中获取实时数据股票价格,是否可以通过改造来获取实时数据