C/C++:Const总结

指针变量和它所指向的内存空间是两个不同的概念

由于Const在C和C++中存在差异,本篇将会对Const在两种语言的表现异同点上进行对比探讨。

实现方式不同

在C语言中,Const修饰的变量只是告诉编译器该变量是一个只读的变量,不能通过该变量改写器内存空间中的值,但是其本质上还是一个变量,既然是变量,就会有内存地址,因此可以通过指针间接修改该地址空间的值。

const int a = 10;
int* p = &a;
*p = 20;
printf("a = %d, *p = %d\n", a, *p);
-------------结果------------------
a = 20, *p = 20

在C++中Const修饰的变量被称为常量,其值存放在常量表中,在使用常量时,编译器回到常量表中查询对应的常量,并将其替换,这部分没有涉及内存分配,因此对其取地址是没有意义的。但是当我们非要对该常量去地址时,则编译器会为其临时分配一个内存,并将常量值存入该临时内存中,事实上,在C++中规定必须用const修饰的指针来指向const修饰的常量。虽然可以使用强制转换的方式,对Const修饰的常量进行去地址,并将其赋值给一个非Const修饰的指针(最好不要这样做),但打这个指针上的任何改动都只会影响到临时分配的内存空间,而不会影响到原常量上。

const int a = 10;
int* p = (int *)&a;
*p = 20;
printf("a = %d, *p = %d\n", a, *p);
-------------结果------------------
a = 10, *p = 20

变量的文件作用域

在C语言中,访问一个变量之前,该变量必须要被预先定义,当访问一个由外部文件定义的变量时,则必须要提前声明该变量。来看下面几个例子。

// main.c
extern int a;
int main() {
    printf("a = %d\n", a);
    return 0;
}
//ln_const.c
int a = 128;
--------结果-------
a = 128

上面的例子是一个标准C语言访问外部变量的例子。我们编写代码时也应该遵守这样的规则。但是,总有写人不是那么规范,例如可以在main.c文件中将extern关键字去掉。

// main.c
int a;
int main() {
    printf("a = %d\n", a);
    return 0;
}
//ln_const.c
int a = 128;
--------结果-------
a = 128

我们发现实际上结果并没有变化,因为编译器在编译时,如果在当前文件中该变量没有被定义,则会从其他文件中寻找定义并链接。因此结果是没有问题的。那么如果变量a的定义被设定成文件内私有时,将会发生什么呢?

// main.c
int a;
int main() {
    printf("a = %d\n", a);
    return 0;
}
// ln_const.c
static int a = 128;
--------结果-------
a = 0

发生这种现象的原因是,编译器没有找到该变量的外部定义,则直接将声明默认为定义,因此变量a是一个默认赋值。事实上extern关键字的作用就是,告诉编译器,该变量的值是由外部文件定义的。因此当我们声明一个外部变量时,如果编译器无法再外部找到该变量的定义,则会无法编译通过。

// main.c
extern int a;
int main() {
    printf("a = %d\n", a);
    return 0;
}
// ln_const.c
static int a = 128;
--------结果-------
编译失败,无法解析外部符号a

那么如果我们在外部定义了一个Const变量,情况是否会有不同呢?在标准情况下,声明和定义,应该是保持一致的。因此标准做法应该是这样的。

// main.c
extern const int a ;
int main() {
    printf("a = %d\n", a);
    return 0;
}

// ln_const.c
const int a = 128;
-----结果---------
a = 128

C语言的难点之一就是规范标准,总有人会在声明时忘记const关键字,但是结果也是正确的。

// main.c
extern int a ;
int main() {
    printf("a = %d\n", a);
    return 0;
}

// ln_const.c
const int a = 128;
-----结果---------
a = 128

既然a在声明时并没有Const修饰是不是意味着,可以直接修改a呢?

// main.c
extern int a ;
int main() {
    a = 20;
    printf("a = %d\n", a);
    return 0;
}

// ln_const.c
const int a = 128;
-----结果---------
编译失败,运行时异常

这里,我们可以看出,变量的声明帮助编译器进行语法检查,但变量的定义决定了运行时的行为。

static关键字和Const关键字同时修饰变量时,Const是否会修改变量的文件作用域呢?

// main.c
extern int a ;
int main() {
    printf("a = %d\n", a);
    return 0;
}

// ln_const.c
static const int a = 128;
-----结果---------
编译失败,无法解析外部符号a

总结:在C语言中,变量文件作用域一般都是外部链接,除非使用static关键字修饰,Const关键字并不会改变变量的文件作用域

你可能感兴趣的:(C/C++:Const总结)