C++_const与指针_指向常量的指针(const int* p) 对比 常量指针 (int* const p = &a);

本文详细解析了C/C++中const限定符的应用场景,包括限定变量、指针及只读指针的概念与使用技巧,并通过实例展示了不同情况下const限定符的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1. const 限定一个变量时 

2. const 限定一个指针时

2.1 指向常量的指针 const int* p;

2.2 常量指针 int* const p = &a;

3. 只读指针(指向常量的常量指针)


名称说明:关于 常量指针 和 指针常量 各个参考书目的叫法会有所区别,本文采用较符合语法的叫法: 指向常量的指针 和 常量指针。

字面解读:

  • 指向常量的指针:有一个变量(也有可能是const修饰的变量)当被一个指针指向时,不能通过该指针改变这个变量,则这个指针称之为“指向常量的指针”, 这不意味着 指针不能改变,也不意味着这个变量不能改变,只是说,不能通过这个指针改变这个变量的值
  • 常量指针:具有常量性质的指针;首先有一个指针,这个指针具有常量的性质,即指针的值(或说指针的指向)不能改变,但可以通过指针去改变指向的变量的值。

1. const 限定一个变量时 

问题:const int a = 10; a是否可以改变?

答案: c语言中允许改变c++中不允许改变.

c语言改变一个const变量的方式:

#include <stdio.h>

int main() {
	
/*
	const 修饰的变量成为只读变量 常量
	可以通过一级指针修改
	*/

    const int a = 10;
    //a = 100; // err
    printf("a的值:%d\n", a); // a的值:10

    int *p = &a;

    *p = 100;
    
    printf("a的值:%d\n", a); // a的值:100

    return 0;
}

c++改变一个const变量,但不成功的例子:

#include <iostream>

int main() 
{
	const int a = 10;
	std::cout << "a = " << a << ", \t &a = " << &a << std::endl;

	// 尝试1:改变 a 的值 失败
	//a = 100;      // err: 不能改变一个常量类型的变量

	// 尝试2:改变 a 的值 失败
	//int* p = &a;         // err: c++中,不能从 const int* 默认转换成 int*
	//int* p = (int*)(&a); // ok: c++中,可以从 const int* 强制 转换成 int* // 但不建议这样写。
	int* p = const_cast<int*> (&a);
	std::cout << "a = " << a << ", \t &a = " << &a << ", \t p = " << p << ", \t *p = " << *p << ", \t &p = " << &p << std::endl;

	*p = 100; // 指针p 拿到了 a变量的地址,*p表示的就是 a, 但在 c++中这句话并不能改变a的值。//无效但不报错的一句话 //不建议这么写

	std::cout <<" ---- after *p = 100 ----" << std::endl;
	std::cout << "a = " << a << ", \t &a = " << &a << ", \t p = " << p << ", \t *p = " << *p << ", \t &p = " << &p << std::endl;

	return 0;
}

 可以看出, 即使我们拿到了 常量 a的地址(const int*),然后去掉const ,得到一个指针(int *)然后对这个指针的值进行改变(*p = 100)可以看出 a的值没有变化,虽然 p的值(指向的位置)仍然是a的地址。

2. const 限定一个指针时

当然 指针 也是一种变量。只不过,作为指针类型的变量,它存的值是地址(数值 如0X0020DF)。

对比 overview:

2.1 指向常量的指针 const int* p;

// 指向常量的指针: 你可以随便指向一个变量,但是你不能通过该指针改变指向的那个变量的值,
// 用途:防止通过指针 去改变 指向的变量的值
// 比如用在:函数参数列表中(当不希望该指针指向的变量被改变时)
// 指向常量的指针
void points_to_constants(void) {
    // 指向常量的指针: 指针的值可以改变,但是不能通过该指针 改变 指向的变量的值
    int a = 1;
    const int b = 2;
    int c = b;

    // 指向常量的指针: 你可以随便指向一个变量,但是你不能改变你指向的那个变量的值,
    // 用途:防止通过指针 去改变 指向的变量的值
    // 比如用在:函数参数列表中(当不希望该指针指向的变量被改变时)
    const int *p1 = &a; // ok, 等价于 int const * p1 = &a;
    const int *p2 = &b; // ok,
    const int *p3 = &c; // ok, 也可以先定义,再初始化一个值 const int *p3; p3 = &c;

    std::cout << "p1: " << *p1 << std::endl; // p1: 1
    std::cout << "p2: " << *p2 << std::endl; // p2: 2
    std::cout << "p3: " << *p3 << std::endl; // p3: 2

    // *p1 = 10; // ERR: 不能改变 "指向常量的指针(p1) 所指向的变量(a)的值"  // <<============
    a = 10;      // OK: 改变指向的变量的值,即使改变 *p1 (代表了a) 的值
    std::cout << "p1: " << *p1 << std::endl; // p1: 10

    p1 = p2;     // OK: 改变该指针的值                                 // <<============
    c = 20;

    std::cout << "p1: " << *p1 << std::endl; // p1: 2
    std::cout << "p2: " << *p2 << std::endl; // p2: 2
    std::cout << "p3: " << *p3 << std::endl; // p3: 20

    char str[] = "ab cd";
    change_str_no(str);     // 打印 [a][b][ ][c][d]
    change_str_yes(str);   // 打印 [a][b][-][c][d]
}

void change_str_no(const char *str) {
    while (*str) {
        if (*str == ' ') {//遇到空格修改成—
            //*str = '-';//这里修改了常量指针所指向的数值。这是不允许,所以报错。 // <<-----------
        }
        printf("[%c]", *str);
        str++;
    }
    printf("\n");
}

void change_str_yes(char *str) {
    printf("========\n");
    while (*str) {
        if (*str == ' ') {//遇到空格修改成—
            *str = '-';//这里修改了指针所指向的值。这是允许的
        }
        printf("[%c]", *str);
        str++;
    }
    printf("\n");
}

2.2 常量指针 int* const p = &a;

// 常量指针: 指针的值(指向)不能改变,但是能通过 常量指针 改变 指向的那个变量 的值,当然 被指向的那个变量的值也可以改变
// 用途:约束指向关系,指向关系不能变
// 常量指针 (具有常量性质的指针) (类似于引用:一旦绑定,终身有效)
void const_pointers() {
    int a = 1;
    const int b = 2;
    int c = b;

    // 常量指针: 指针的值(指向)不能改变,但是能通过 常量指针 改变 指向的那个变量 的值,当然 被指向的那个变量的值也可以改变
    // 用途:约束指向关系,指向关系不能变
    // 比如用在:??
    int * const p1 = &a; // ok,
    //int * const p2 = &b; // ERR: 不能用常量指针,指向一个常量(不能改变的变量) // error C2440: “初始化”: 无法从“const int *”(&b) 转换为 “int *” (p2)
    int * const p3 = &c;   // ok, 定义一个常量指针时,必须直接初始化 //ERR:  int * const p3; p3 = &c;

    std::cout << "p1: " << *p1 << std::endl; // p1: 1
    std::cout << "p3: " << *p3 << std::endl; // p3: 2

    *p1 = 10;      // OK: 能通过 常量指针(p1) 改变 所指向的变量(a)的值"  // <<============
    std::cout << "p1: " << *p1 << std::endl; // p1: 10

    a = 100;       // OK: 改变指向的变量的值,即使改变 *p1 (代表了a) 的值
    std::cout << "p1: " << *p1 << std::endl; // p1: 100

    //p1 = p3;     // ERR: 不能改变 常量指针 的值(的指向)            // <<============
    c = 20;        // OK: 常量指针 指向的变量 的值 改变了,*p3(代表了c) 自然也变了

    std::cout << "p3: " << *p3 << std::endl; // p3: 20
}

3. 只读指针(指向常量的常量指针)

    // 只读指针: 指针的值(指向)不能改变,指针所指向的那个变量可以改变,不能通过指针改变指向的变量的值
    // 用途:只从指针中读取指向某变量的值,而不能对这个变量进行写操作。

// 只读指针 (指向常量的常量指针)
void read_only_pointer() 
{
    int a = 1;
    const int b = 2;
    int c = b;

    // 只读指针: 指针的值(指向)不能改变,指针所指向的那个变量可以改变,不能通过指针改变指向的变量的值
    // 用途:约束指向关系,指向关系不能变
    const int *const p1 = &a; // ok,
    const int *const p2 = &b; // ERR: 不能用常量指针,指向一个常量(不能改变的变量) // error C2440: “初始化”: 无法从“const int *”(&b) 转换为 “int *” (p2)
    const int *const p3 = &c;   // ok, 定义一个常量指针时,必须直接初始化 //ERR:  int * const p3; p3 = &c;

    std::cout << "p1: " << *p1 << std::endl; // p1: 1
    std::cout << "p2: " << *p2 << std::endl; // p2: 2
    std::cout << "p3: " << *p3 << std::endl; // p3: 2

    // *p1 = 10; // ERR: 不能通过只读指针改变 指向的变量 的值    // 指向常量的指针 的性质
    // p1 = p2;  // ERR: 不能改变指针的值(指向)               // 常量指针 的性质

    a = 10;      // OK:  可以通过改变 被指向变量的值,来改变 *p1 // <<============
    //b = 20;      // ERR: b 本身是常量,不能改变
    c = 30;      // OK:  可以通过改变 被指向变量的值,来改变 *p2 // <<============

    std::cout << "p1: " << *p1 << std::endl; // p1: 10
    std::cout << "p2: " << *p2 << std::endl; // p2: 2
    std::cout << "p3: " << *p3 << std::endl; // p3: 30

    int e = *p1 + *p2 + *p3; // OK: 只能读 该指针 指向的变量 的值
    std::cout << "e: " << e << std::endl; // p3: 42 (= 10 + 2 + 30)
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

惊鸿一博

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值