热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在C++中使用变量而不是`#define`指定数组大小是不好的做法吗?(C错误:在文件范围内进行了可变修改)

如何解决《在C++中使用变量而不是`#define`指定数组大小是不好的做法吗?(C错误:在文件范围内进行了可变修改)》经验,为你挑选了1个好方法。

在C中,const不允许使用变量声明数组大小,即使它是变量.例如:这无法在C中编译:

#include 

const int SIZE = 2;
int a[SIZE];

int main()
{
    a[0] = 1;
    a[1] = 2;
    printf("%i, %i", a[0], a[1]);       
    return 0;
}

在C中运行此代码

输出:

$gcc -o main *.c
main.c:5:5: error: variably modified ‘a’ at file scope
 int a[SIZE];
     ^

但是,在C++中,它运行得很好.
在C++中运行上面的代码.

输出:

$g++ -o main *.cpp
$main
1, 2

要使其在C中运行,必须使用#define而不是变量.即:

这在C或C++中运行得很好:

#include 

#define SIZE 2
// const int SIZE = 2;
int a[SIZE];

int main()
{
    a[0] = 1;
    a[1] = 2;
    printf("%i, %i", a[0], a[1]);
    return 0;
}

在C中运行此代码

因此,在C++中,我几乎总是使用变量而不是#define声明我的数组大小.我只是使数组大小变量const,这一切都很好!最近我开始在纯C中进行大量的单片机编程,然而,当我遇到这个错误并找出问题时,一位高级开发人员告诉我使用除#define-ed常量之外的任何东西都是不好的做法(或者可能是硬编码的数字) )声明数组大小.

这是真的?在C++中使用const变量而不是#define在指定数组大小时是不好的做法?如果是这样,为什么?

在C中,显然你坚持#define:你别无选择.但是在C++中你显然至少有两个选择,那么一个比另一个好吗?使用一个比另一个有风险吗?

有关:

    C中文件范围的可变修改数组

    static const vs #define <- 这是一个可靠的问题,非常有帮助.这绝对与我的问题有关,但我的问题并不重复,因为虽然它们都是关于const vs #define,但我的问题是一个非常特殊的情况,其中一个选项甚至不能用一种定期的语言工作被认为是C++的一个子集.这是非常不寻常的,并使我的问题成为一个更窄的子集,符合这个其他问题的广泛范围.因此,不重复.

    https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es31-dont-use-macros-for-constants-or-functions

    "static const"vs"#define"vs"enum"

    https://en.wikipedia.org/wiki/Variable-length_array#C99

P.W.. 6

在这件事上遵循Scott Meyer的建议会很好.从他的书"Effective C++":
第2项:首选consts,enums和inline到#defines.

适用于您的示例的项目摘要.

这个项可能更好地被称为"更喜欢编译器到预处理器",因为它#define可能被视为它本身不是语言的一部分.这是其中一个问题.

当你做这样的事情时,

#define SIZE 2

SIZE 编辑器可能永远不会看到符号名称; 在源代码到达编译器之前,它可能被预处理器删除.因此,名称SIZE可能无法输入到符号表中.如果在编译过程中出现涉及使用常量的错误,这可能会造成混淆,因为错误消息可能2不是指代SIZE.如果SIZE在头文件中定义了你没有写,你就不知道它2来自哪里 ,而你却浪费时间跟踪它.此问题也可能出现在符号调试器中,因为您编程的名称可能不在符号表中.解决方案是用常量替换宏:
const double SIZE = 2; // uppercase names are usually for macros, hence the name change
作为语言常量,SIZE编译器肯定会看到它,并且肯定会输入到它们的符号表中.

✦对于简单常量,首选const对象或枚举到#defines.
✦对于类似函数的宏,首选内联函数为#defines.

另请参阅"第3项:尽可能使用const".有关其用法和使用例外的更多信息.

所以在标题中回答你的问题:
,使用变量而不是#defineC++ 指定数组大小并不是一个坏习惯.



1> P.W..:

在这件事上遵循Scott Meyer的建议会很好.从他的书"Effective C++":
第2项:首选consts,enums和inline到#defines.

适用于您的示例的项目摘要.

这个项可能更好地被称为"更喜欢编译器到预处理器",因为它#define可能被视为它本身不是语言的一部分.这是其中一个问题.

当你做这样的事情时,

#define SIZE 2

SIZE 编辑器可能永远不会看到符号名称; 在源代码到达编译器之前,它可能被预处理器删除.因此,名称SIZE可能无法输入到符号表中.如果在编译过程中出现涉及使用常量的错误,这可能会造成混淆,因为错误消息可能2不是指代SIZE.如果SIZE在头文件中定义了你没有写,你就不知道它2来自哪里 ,而你却浪费时间跟踪它.此问题也可能出现在符号调试器中,因为您编程的名称可能不在符号表中.解决方案是用常量替换宏:
const double SIZE = 2; // uppercase names are usually for macros, hence the name change
作为语言常量,SIZE编译器肯定会看到它,并且肯定会输入到它们的符号表中.

✦对于简单常量,首选const对象或枚举到#defines.
✦对于类似函数的宏,首选内联函数为#defines.

另请参阅"第3项:尽可能使用const".有关其用法和使用例外的更多信息.

所以在标题中回答你的问题:
,使用变量而不是#defineC++ 指定数组大小并不是一个坏习惯.


所以回答标题中的Q:不,恰恰相反.
推荐阅读
  • Igotthiscode(IknowitsinSpanishIcantranslateifneeded)wheretheygivemethefunctionS ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • 本文讨论了如何在codeigniter中识别来自angularjs的请求,并提供了两种方法的代码示例。作者尝试了$this->input->is_ajax_request()和自定义函数is_ajax(),但都没有成功。最后,作者展示了一个ajax请求的示例代码。 ... [详细]
  • 本文介绍了PHP常量的定义和使用方法,包括常量的命名规则、大小写敏感性、全局范围和标量数据的限制。同时还提到了应尽量避免定义resource常量,并给出了使用define()函数定义常量的示例。 ... [详细]
  • 数据结构-图详解(图基本概念、图的存储结构及C++实现)
    本文主要介绍关于数据结构,c++,图论的知识点,对【数据结构-图详解(图基本概念、图的存储结构及C++实现)】和【数据结构图的存储结构代码】有兴趣的朋友可以看下由【NUC_Dodamce】投稿的技术文 ... [详细]
  • c#中using-添加引用-程序集(详解) 以及与 c++中include等区别
    一、c#中Using无非就三个作用,引入名字空间,减少代码输入量;给名字空间或类型定义一个别名;try-catch的一种替代。二、c#中添加引用的作用是把其它程序集包含到本项目中,就好像在本项目中写的 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 热血合击脚本辅助工具及随机数生成器源码分享
    本文分享了一个热血合击脚本辅助工具及随机数生成器源码。游戏脚本能够实现类似真实玩家的操作,但信息量有限且操作不可控。热血合击脚本辅助工具可以帮助玩家自动刷图、换图拉怪等操作,并提供了雷电云手机的扩展服务。此外,还介绍了使用mt_rand函数作为随机数生成器的代码示例。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • Ihaveaworkfolderdirectory.我有一个工作文件夹目录。holderDir.glob(*)>holder[ProjectOne, ... [详细]
author-avatar
Rocky柱子
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有