在C和C++中都有const关键字,如果用来装饰一个变量则改变量设为只读类型,且必须在声明时进行初始化,否则不能后续赋值了。
在C中常量的声明方式更为传统的方式是使用#define定义,但是在C++中这种方式已经不再被提倡了。那么是不是const定义的所谓常量和#define定义的常量在使用上一样呢?
实际上C和C++关于const关键字的处理并不相同,看下面几个例子。
一、C++中const关键字
在C++中const关键字修饰的int型变量可以当做常量来使用,这至少在使用上看不出太大区别。看下面实验。
实验一:C++中的const
如下代码:
// cpp_arr_right.cpp
#include <iostream>
using namespace std;
int main(void)
{
const int Size = 4;
int int_arr_1[Size] = {1,2,3,4};
cout << "sizeof(int_arr_1) = " << sizeof(int_arr_1) << endl;
for(int i = 0; i < Size; i++) {
cout << "int_arr_1(" << i << "): " << int_arr_1[i] << endl;
}
int int_arr_2[Size];
cout << "sizeof(int_arr_2) = " << sizeof(int_arr_2) << endl;
int_arr_2[0] = 11;
int_arr_2[1] = 12;
int_arr_2[2] = 13;
int_arr_2[3] = 14;
for(int i = 0; i < Size; i++) {
cout << "int_arr_2(" << i << "): " << int_arr_2[i] << endl;
}
char char_arr[Size] = "qwe";
cout << "sizeof(char_arr) = " << sizeof(char_arr) << endl;
for(int i = 0; i < Size; i++) {
cout << "char_arr(" << i << "): " << char_arr[i] << endl;
}
printf("use cout: ");
cout << char_arr << endl;
return 0;
}
将这个程序进行编译:
g++ cpp_arr_right.cpp -o cpp_arr_right.exe
将没有任何回显:
然后执行,得到如下信息:
这完全符合我们的预期。
二、C中const关键字
看如下的实验。
实验二:C中使用const声明数组——方式一
看如下代码:
/* c_arr_right.c */
#include <stdio.h>
int main(void)
{
const int Size = 4;
int int_arr[Size];
printf("sizeof(int_arr) = %zu\n", sizeof(int_arr));
int_arr[0] = 13;
int_arr[1] = 15;
int_arr[2] = 17;
int_arr[3] = 18;
for(int i = 0; i < Size; i++) {
printf("int_arr[%d] = %d\n", i, int_arr[i]);
}
char char_arr[Size];
printf("sizeof(char_arr) = %zu\n", sizeof(char_arr));
char_arr[0] = 'a';
char_arr[1] = 'c';
char_arr[2] = 'e';
char_arr[3] = '\0';
for(int i = 0; i < Size; i++) {
printf("char_arr[%d] = %c\n", i, char_arr[i]);
}
printf("use puts: ");
puts(char_arr);
return 0;
}
编译:
gcc c_arr_right.c -o c_arr_right.exe
同样没有任何回显,编译顺利通过,指向后,显示:
这同样完全符合预期。这种用法是正确的。
但是。
实验三:C中使用const声明数组——方式二
如下代码:
/* c_arr_error1.c */
#include <stdio.h>
int main(void)
{
const int Size = 4;
int int_arr[Size] = {1,2,3,4};
return 0;
}
编译将得到错误报告,如下:
数组大小为变动的不能初始化。
三、C语言编程数组
这个实际上是将int_arr数组看做编程数组,变长数组是C99引入的标准。这里声明时变动的长度只要是自动存储类就可以。如下实验。
实验三:C的变长数组
代码如下:
/* vla.c */
#include <stdio.h>
int main(void)
{
int Size = 4; // 注意,没有const修饰
int int_arr[Size];
printf("sizeof(int_arr) = %zu\n", sizeof(int_arr));
int_arr[0] = 13;
int_arr[1] = 15;
int_arr[2] = 17;
int_arr[3] = 18;
for(int i = 0; i < Size; i++) {
printf("int_arr[%d] = %d\n", i, int_arr[i]);
}
char char_arr[Size];
printf("sizeof(char_arr) = %zu\n", sizeof(char_arr));
char_arr[0] = 'a';
char_arr[1] = 'c';
char_arr[2] = 'e';
char_arr[3] = '\0';
for(int i = 0; i < Size; i++) {
printf("char_arr[%d] = %c\n", i, char_arr[i]);
}
printf("use puts: ");
puts(char_arr);
return 0;
}
编译一样会顺利通过,并得到预期的值。
这里的Size虽然没有const修饰了,仍然可以声明一个数组,但是依然不允许进行初始化。
所谓变长数组是指数组的维数可以由变量来指定,但是一旦确定便不可以更改为了。
实验四:变长数组维数不变
/* vla_2.c */
#include <stdio.h>
int main(void)
{
int Size = 4; // 注意,没有const修饰
int int_arr[Size];
Size = 6;
printf("sizeof(int_arr) = %zu\n", sizeof(int_arr));
char char_arr[Size];
Size = 7;
printf("sizeof(char_arr) = %zu\n", sizeof(char_arr));
return 0;
}
编译运行,输出为:
可见Size在声明数组使用后,其再发生变化,便不会影响数组的原始声明维数了。
四、总结
1、C中,声明数组时,可以采用变长数组,但是声明后其长度便固定了,且声明时不允许初始化;
2、在C++中,声明数组可以使用变量,但是可以初始化;
3、虽然C和C++中声明变长数组,其用于声明维数的变量可以改变,但还是建议将其设置为const类型,利于代码维护。
4、关于const变量在C和C++中的不同处理,这玩应看似简单,实则水很深,和C与C++的关系、C++的发展,已经C和C++的具体实现都有关系,有时间,给大家专门做个讨论,分析下GCC的码源。