04一篇彻底理解 指针常量和常量指针 指向常量的常指针

2023-05-16

1、在汉语中,定语一般都放在中心词的前面,像C语言和C++语言这种技术性语言,更是如此。
所以定语重要还是中心词重要,肯定是中心词重要。
如:美丽的女孩 美丽的是定语 女孩是中心词
女孩肯定是重要,是本质。

2、同理:我们先不讲技术,先从字面意思来理解:
指针常量 常量指针
函数指针 指针函数

指针常量:指针是定语,常量是中心词,所以指针常量本质是一个常量。
常量指针:常量是定语,指针是中心词,所以常量指针本质是一个指针。
函数指针:本质上是一个指针。那就是指向函数的指针。
指针函数:
数组指针:本质上是一个指针,只不过是指向数组的指针。
指针数组:本质上是一个数组,只不过数组元素都是指针。

3、本文正文:

1、指针常量——指针类型的常量(int * const p)

巧记:const的作用就是将被修饰者限定为常量,所以const修饰谁,谁就是常量。

指针常量(指针本身是常量)
定义:
本质是一个常量,而用指针修饰它。指针常量的值是指针,这个值因为是常量,所以不能被赋值。

关键点:
1、它是个常量!
2、指针本身是常量,指向的地址不可以变化,但是指向的地址所对应的内容可以变化;
代码形式:

int* const p;

大话解释:
本质上一个常量,指针用来说明常量的类型,表示该常量是一个指针类型的常量。在指针常量中,指针自身的值是一个常量,不可改变,始终指向同一个地址。在定义的同时必须初始化。用法如下:

int a = 10, b = 20;
int * const p = &a;
*p = 30;      // p指向的地址是一定的,但内存地址空间中的内容可以修改

2、常量指针——指向“常量”的指针(const int *p, int const *p)

巧记:常量在指针前面, 程序语言: const在星号之前即可。

定义:
又叫常指针,可以理解为常量的指针,指向的是个常量

关键点:
1、常量指针指向的对象不能通过这个指针来修改,可是仍然可以通过原来的声明修改;
2、常量指针可以被赋值为变量的地址,之所以叫常量指针,是限制了通过这个指针修改变量的值;
3、指针还可以指向别处,因为指针本身只是个变量,可以指向任意地址; 
代码形式:

int const* p;  const int* p;

常量指针本质上是一个指针,常量表示指针指向的内容,说明该指针指向一个“常量”。在常量指针中,限制了通过这个指针修改变量的值,指针看起来好像指向了一个常量。用法如下:

int a = 10, b = 20;
const int *p = &a;
p = &b;    // 指针可以指向其他地址,但是内容不可以改变

3、例题
例题(1)

int main() {
    int m = 10;
    const int n = 20; // 必须在定义的同时初始化
 
    const int *ptr1 = &m; // 指针指向的内容不可改变
    int * const ptr2 = &m; // 指针不可以指向其他的地方
 
    ptr1 = &n; // 正确
    ptr2 = &n; // 错误,ptr2不能指向其他地方
 
    *ptr1 = 3; // 错误,ptr1不能改变指针内容
    *ptr2 = 4; // 正确
 
    int *ptr3 = &n; // 错误,常量地址不能初始化普通指针吗,常量地址只能赋值给常量指针
    const int * ptr4 = &n; // 正确,常量地址初始化常量指针
 
    int * const ptr5; // 错误,指针常量定义时必须初始化
    ptr5 = &m; // 错误,指针常量不能在定义后赋值
 
    const int * const ptr6 = &m; // 指向“常量”的指针常量,具有常量指针和指针常量的特点,指针内容不能改变,也不能指向其他地方,定义同时要进行初始化
    *ptr6 = 5; // 错误,不能改变指针内容
    ptr6 = &n; // 错误,不能指向其他地方
 
    const int * ptr7; // 正确
    ptr7 = &m; // 正确
 
    int * const ptr8 = &n;
    *ptr8 = 8;
 
    return 0;
}

例题(2)判断下面程序对错,并说明理由

int main()
{
char * const str = “apple”;
* str = “orange”;
cout << str << endl;
getchar();
}
错误

“apple"是字符串常量放在常量区,str指向"apple”,那么str指向的是字符串常量"apple"的首地址,也就是字符a的地址,因此str指向字符a,str就等于字符a,对str的修改就是对字符串首字符a的修改,但"apple"是一个字符串常量,常量的值不可修改。

根据字符串赋值规则,可以修改整个字符串,方法是对指向字符串的指针str进行赋值,如下:

str = “orange”;
但依旧是错误的,在该赋值语句中,系统会在常量区一块新的空间写入字符串"orange"并返回其首地址,此时str由指向字符串常量"apple"的首地址变为指向字符串常量"orange"的首地址,str指向的地址发生了变化,但str是指针常量不能被修改,所以错误。

如果想要程序编译通过,就不能将str声明为指针常量,否则str在初始化之后就无法修改。因此将const修饰符去掉,并修改字符串赋值语句,修改后程序如下:

int main()
{
char * str = “apple”;
str = “orange”;
cout << str << endl;
getchar();
}
参考《程序员面试笔记》
例题3:自己亲自试验过,经历过
int main()
{
char * str = “apple”;
str = “orange”;
cout << str << endl;
getchar();
}
这个在vs2015上能够编译通过,但是在vs2017和vs2019上是不能编译通过的。
分析:因为"apple" 是存储在全局(静态变量)区,是只读的,不能修改。所以指向只读常量的指针必须声明为常量指针才能编译通过。

int main()
{
   const char * str = "apple";
    str = "orange";
    cout << str << endl;
    getchar();
}

这样写就能在vs2017和vs2019上编译通过了。

3、指向常量的常指针
定义:
指向常量的指针常量就是一个常量,且它指向的对象也是一个常量。

关键点:
一个指针常量,指向的是一个指针对象;
它指向的指针对象且是一个常量,即它指向的对象不能变化;
代码形式:

const int* const p;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

04一篇彻底理解 指针常量和常量指针 指向常量的常指针 的相关文章

  • stm32f103 hal库中timer使用

    stm32f103 hal库中timer使用 使用步骤1 初始化定时器2 HAL TIM Base Init amp htim2 基本参数配置3 重写void HAL TIM Base MspInit TIM HandleTypeDef t
  • hal库中的UART使用

    1 初始化串口 UART initStruct span class token punctuation span Instance span class token operator 61 span USART1 span class t
  • f103 hal库中gpio外部中断使用

    1初始化引脚 与配置通用管脚一样 xff0c 只是mode改成中断触发条件 GPIO InitTypeDef GPIO InitStruct span class token punctuation span GPIO InitStruct
  • f103 hal RTC_alarm使用方法

    1 初始化RTC RTC handle span class token punctuation span Instance span class token operator 61 span span class token consta
  • 系统的TPS不达标,此时如何优化

    对系统进行压测 xff0c 比如每秒压个几百请求到几千请求 xff0c 甚至上万请求 xff0c 此时发现死活压不上去 xff0c 压来压去 xff0c 你的系统最多每秒就处理几百个请求 xff0c 根本到不了几千个请求 xff0c 此时就
  • f103 hal库中PWM的使用方法

    1 初始化复用管脚 span class token keyword void span span class token function BEEP Init span span class token punctuation span
  • EFR32FG14 使用定时器TIMER做毫秒级定时

    EFR32FG14 使用定时器TIMER做毫秒级定时 1 添加头文件 span class token macro property span class token directive keyword include span span
  • EFR32FG14 UART的使用方法

    EFR32FG14 UART的使用方法 1 初始化串口 xff08 PA0 gt TX PA1 gt RX xff09 span class token keyword void span span class token function
  • EFR32解锁方法

    EFR32锁住的解锁方法 在某些情况下 xff0c 芯片可能会被锁住 xff0c 导致J LINK等工具连接不上 xff0c 可以参考如下方法 xff1a 1 进入commander exe所在的目录 xff1b 按住Shift 43 右键
  • TFT1.44寸屏ST7735S屏幕使用-stm32f103c8t6

    TFT1 44寸屏ST7735S屏幕使用 stm32f103c8t6 K xff1a 背景灯 RESET xff1a tft复位 RS xff1a 控制线 xff08 数据或者命令 xff09 SDA xff1a 数据线 xff08 SPI
  • 8421拨码器 R7H3-16 的使用

    8421拨码器 R7H3 16 的使用 使用方法极其简单 xff0c 1 2 4 8脚分解与单片机的4个IO脚连接 xff0c IO配置为输入即可 0代表低电平 xff0c 1代表高电平 档位 脚位124801111101112101130
  • Ubuntu 18 上不了网解决方法

    Ubuntu 18 出现网络异常 1 打开命令行 Ctrl 43 Alt 43 t 2 关闭网络 sudo service network manager stop 3 删除网络 sudo rm var lib NetworkManager
  • GPIO引脚 模拟 IIC(软件IIC)

    GPIO引脚 模拟 IIC 软件IIC IIC总线在传输数据的过程中一共有三种类型信号 xff0c 分别为 xff1a 开始信号 结束信号和应答信号 IIC总线的时序图 xff1a 空闲状态 当IIC总线的数据线SDA和时钟线SCL两条信号
  • ESP32/ESP8266 MQTT协议接入阿里云(一)

    ESP32 ESP8266 MQTT协议接入阿里云 xff08 一 xff09 1 搭建阿里云环境 xff08 1 xff09 跳转连接 xff1a https iot console aliyun com lk summary new x
  • ESP32/ESP8266 MQTT协议接入阿里云(二)

    ESP32 ESP8266 MQTT协议接入阿里云 xff08 二 xff09 1 在连接阿里云之前 xff0c 需要先了解MQTT的连接协议 CONNECT 协议格式 xff1a 固定包头 43 可变包头 43 有效载体 xff08 1
  • https是如何验证证书的有效性的

    证书验证的过程是使用非对称加密的 xff0c 客户端对服务器端发起请求 xff0c 服务器返回一个证书 xff0c 客户端验证这个证书的合法性 xff0c 如果这个证书是合法的 xff0c 那么就生成一个随机值 xff0c 利用这个随机值作
  • Kali Linux 更新源

    vi etc apt source list 添加下列更新源 中科大 deb http mirrors ustc edu cn kali kali rolling main non free contrib deb src http mir
  • 安装所有Kali 工具包

    apt get kali linux all

随机推荐