多年老c++程序员在静态数组这里翻船了

事情的起因

事情是这样子滴,有一次我在代码评审的时候,发现有同事想使用运行时才能够获取到的值,去改变一个静态数组的元素个数,我当时就很诧异,因为我心里知道这样是不可行的,静态数组的元素个数在编译时就需要是固定不变的,一般只能是常量或者宏定义,否则编译就不能通过。

但是当时我提出来以后,把原因说了,包括写出这个代码的人和另外一位同事都没理解,弄得我有点怀疑自己了,难道是我搞错了?

我左思右想,最后我写了下面的代码来证实一下:

#include <iostream>
using namespace std;

int get()
{
	int size = 0;
	cout << "please input a num:";
	cin >> size;
	return size;
}

int main()
{
	int size = 1000;
	size = get();
	int arr[size] = {0};

	cout << "arr's size is " << sizeof(arr)/sizeof(arr[0]) << endl;

	return 0;
}

我打心底认为,这段程序肯定是编译不通过的,但是结果打脸了。编译后执行显示如下:

please input a num:10000
arr's size is 10000

不仅编译通过了,而且数组大小还在运行时修改了,可是我明明定义的是一个静态数组呀,而且就算我这里不给size赋初始值1000,结果也还是一样的。

探索的过程

简直是见了鬼了,我把代码看了又看,认为是我代码写错了,但是这么简单的一段代码,我不可能写错呀。后来我突然想到,会不会是有了新的语法?

因为我现在的gcc编译器,大家都知道是7.1.0的版本,基本上连c++17都能支持了,我就试了一下之前保留的gcc4.1.2的版本,结果报错啦,如下:

test.cpp: In function ‘int main()’:
test.cpp:15: 错误:可变大小的对象 ‘arr’ 不能被初始化

所以很显然,我的记忆没有错误,之前静态数组的元素个数它就必须是个不可变的,否则编译就会出错。

然后我又看了下生产上用的编译器,是gcc4.8.5的版本,它也是支持c++11的,难道这个新的特性是c++11支持的吗?然后我去cppreference把c++11的新特性从头到尾翻了一遍,并没有对这个修改有说明,并且网上搜索,所有的文章都在说c和c++想使用变长数组,就必须要使用动态数组,我一度陷入了僵局,但是我并没有死心,继续探索。

后来我忽然想到,假如不是c++的新特性,那是不是c语言的新特性呢,想到这里,我把代码做了如下修改:

#include <stdio.h>

int get()
{
	int size = 0;
	printf("please input a num:");
	scanf("%d", &size);
	return size;
}

int main()
{
	int size = 1000;
	size = get();
	int arr[size] = {0};

	printf("arr's size is %d\n", sizeof(arr)/sizeof(arr[0]));

	return 0;
}

然后直接使用gcc命令编译,而没有使用g++,结果跟上面那段代码是一模一样的,到这里我大致上就明白了,这就是c语言里面的新特性。

欣喜的找到了结果

最后我在cppreference这个链接里面看到了对于c99的说明:

  1. 新特性: Bool 、 long long 、 stdint.h 、 inttypes.h 、 restrict 、复合字面量、变长度数组、伸缩数组成员、指派初始化器、 fenv.h 、变参数宏、复数、 func 、十六进制浮点格式( %a )、 lconv 的货币格式化、 isblank 、窄与宽字符串字面量的连接、枚举的尾逗号、类函数宏的空参数、 STDC* pragma 、 va_copy 、 tmpnam 的空返回、 setvbuf 中的空指针、 printf 的 hh 与 ll 长度指定符、 snprintf 、 _Exit 、 tgmath.h 、仿 POSIX strftime 说明符
  2. 来自 C++ : inline 、声明与代码混合、 for 循环的 init 子句中的声明、 **//** 注释、源代码中的通用字符名
  3. 移除隐式函数声明和隐式 int

看看,是不是明确说明了新特性是变长度数组,并且是c语言99年的标准,有点灯下黑了,以后如果再看到有人说c语言和c++的静态数组都只支持固定长度,要想变长就必须要使用malloc和new,就可以唾弃一下啦。

另外有一点需要注意的是,如果我们的场景真的是需要使用固定大小的数组,那么最好使用常量和宏定义,再不然,就使用c++11里面新增加的array。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cpp加油站

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值