前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >多年老c++程序员在静态数组这里翻船了

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

作者头像
cpp加油站
发布2021-06-10 10:27:54
3420
发布2021-06-10 10:27:54
举报
文章被收录于专栏:cpp加油站cpp加油站
事情的起因

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

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

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

#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。

好了,有关我和静态数组的故事就介绍到这里了,因为没有留言功能,如果有问题需要咨询的,可以通过公众号菜单【联系作者】获取作者联系方式进行咨询哈。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-06-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 cpp加油站 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 事情的起因
  • 探索的过程
  • 欣喜的找到了结果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档