使用数组时,C中的#define和int有什么区别?

使用数组时,C中的#define和int有什么区别?,c,arrays,C,Arrays,我正在学习C语言编程,我有一个问题,当我声明一个数组时,什么更好。我的老师告诉我,最好使用一个包含大小值的变量,如下所示: #include <stdio.h> #include <stdlib.h> int main (){ int size = 10; int array [size]; return 0; } #包括 #包括 int main(){ int size=10; int数组[大小]; 返回0; } 但我的逻辑是:如果我有一个永远不会在

我正在学习C语言编程,我有一个问题,当我声明一个数组时,什么更好。我的老师告诉我,最好使用一个包含大小值的变量,如下所示:

#include <stdio.h>
#include <stdlib.h>

int main (){
  int size = 10;
  int array [size];

  return 0;
}
#包括
#包括
int main(){
int size=10;
int数组[大小];
返回0;
}
但我的逻辑是:如果我有一个永远不会在代码中更改的变量。我可以这样申报吗?错了吗

#include <stdio.h>
#include <stdlib.h>

#define size 10

int main (){
  int array [size];

  return 0;
}
#包括
#包括
#定义尺寸10
int main(){
int数组[大小];
返回0;
}
首先,定义一个预处理器宏。正如其他人所提到的,大多数样式指南建议对常量使用
ALL_CAPS
。宏的内容将被直接替换,因此:

#定义尺寸10
无效测试(无效)
{
int-ar[大小];
}
将变成这样,它定义了一个正常的固定大小数组:

void测试(void)
{
int-ar[10];
}

这是一个C99:

void测试(void)
{
int size=10;
int-ar[大小];
}
在启用了优化的现代编译器上,可能没有什么不同。编译器将看到
size
从未更改,并且可能会生成相同的代码

在静态分析方面可能存在细微的差异,但在大多数情况下,它们的行为是相同的


然而,VLA比这更强大。请参见此示例:

无效测试(整数大小)
{
int-ar[大小];
}
现在,根据
size
参数,每次调用
test()
时,
ar
的大小都会改变。这意味着堆栈布局和消耗在运行时会有所不同。这与C99之前的代码类似,使用:

无效测试(整数大小)
{
int*const ar=alloca(size*sizeof(int));
}
关键区别在于,在VLA上使用
sizeof()
将返回其运行时大小,而在该示例中
sizeof(ar)
将返回指针的大小


因此,如果您要这样做:

int size=10;
无效测试(无效)
{
int-ar[大小];
}

然后,编译器将被迫生成读取全局
size
变量的代码,并在堆栈上动态分配数组。

您的老师认为最好使用变量的原因是,可以强制执行变量特定类型的约束

#define size 10
int main (){
  int array [size];

  return 0;
}
vs

第二种方法的意义是相同的,它可以防止您(或其他人)以很小的代价将错误的值放入大小,您明确地告诉下一个修改代码的人
size
常量应该是int

例如,您可以更改您的声明:

const unsigned int size = 10; 
告诉开发人员不要尝试将负值放入大小

使用define宏的一种有效方法是使用编译时定义(via)

请记住,源代码主要是人为的,以后由计算机解释、编译和执行。编写代码的主要目标是可读性


这就是为什么有些人建议使用可读的变量名,将常量名大写,使用一些常识来命名函数/过程,以便阅读代码的人在编写代码时能够理解您自己的意图(有些注释也很好,但可能会产生不利影响,其他地方会更好地讨论)

你是要做C专用的,还是C++的?您的C编译器目标是否支持
const
?一些编码风格建议使用
#define SIZE 10
,其中
SIZE
都是大写,以明确它是已定义的宏。
define
用于宏替换,在这种情况下
SIZE
将是一个运行时常量,因为在编译代码之前,预处理器将转换源代码以替换值。在第一种情况下(取决于优化),大小可能不是运行时常量,创建的数组将是可变长度数组,因为在某些更复杂的情况下,编译器在创建数组时不会确定大小的值。在这两种情况下,首选的表示法都是
int-array[size]
名称和方括号之间没有空格。是的,你可以这样做,实际上更好理解。但是,
定义
使用所有大写字母,因此当人们阅读您的代码时,他们会知道
大小
是一个常量。这是否回答了您的问题?请记住,VLA不能具有
静态
存储持续时间(它们不能用作全局变量),也不能是
结构
联合
类型的成员。
alloca()
示例并不完全等效,因为您有一个额外的指针变量(tr可以更改为指向其他位置)在另一个视图中没有指针。但如果您将其声明为:
int*const ar=alloca(…),那么它在功能上是等价的谢谢@Louis。我做了一些小的修改来反映这一点。另一点与调试有关<代码>定义
s通常不会被调试器很好地处理,因为它们可以在源文件中的某些点重新定义,而
const int size=无法更改,调试器可以随时显示
大小的值(只要它在适当的范围内)
const unsigned int size = 10;