当前课程知识点:C++语言程序设计基础 > 第6章 数组、指针与字符串(一) > 指针的定义和运算 > 指针的初始化和赋值
指针的初始化和赋值
语法形式
存储类型 数据类型 *指针名=初始地址;
例:
int *pa = &a;
注意事项
用变量地址作为初值时,该变量必须在指针初始化之前已声明过,且变量类型应与指针类型一致。
可以用一个已有合法值的指针去初始化另一个指针变量。
不要用一个内部非静态变量去初始化 static 指针。
语法形式
指针名=地址
注意:“地址”中存放的数据类型与指针类型必须相符
向指针变量赋的值必须是地址常量或变量,不能是普通整数,例如:
通过地址运算“&”求得已定义的变量和对象的起始地址
动态内存分配成功时返回的地址
例外:整数0可以赋给指针,表示空指针。
允许定义或声明指向 void 类型的指针。该指针可以被赋予任何类型对象的地址。
例: void *general;
以往用0或者NULL去表达空指针的问题:
C/C++的NULL宏是个被有很多潜在BUG的宏。因为有的库把其定义成整数0,有的定义成 (void*)0。在C的时代还好。但是在C++的时代,这就会引发很多问题。
C++11使用nullptr关键字,是表达更准确,类型安全的空指针
//6_5.cpp
#include <iostream>
using namespace std;
int main() {
int i; //定义int型数i
int *ptr = &i; //取i的地址赋给ptr
i = 10; //int型数赋初值
cout << "i = " << i << endl; //输出int型数的值
cout << "*ptr = " << *ptr << endl; //输出int型指针所指地址的内容
return 0;
}
运行结果:
i = 10
*ptr = 10
例6-6 void类型指针的使用
#include <iostream>
using namespace std;
int main() {
//!void voidObject; 错,不能声明void类型的变量
void *pv; //对,可以声明void类型的指针
int i = 5;
pv = &i; //void类型指针指向整型变量
int *pint = static_cast<int *>(pv); //void指针转换为int指针
cout << "*pint = " << *pint << endl;
return 0;
}
不能通过指向常量的指针改变所指对象的值,但指针本身可以改变,可以指向另外的对象。
例
int a;
const int *p1 = &a; //p1是指向常量的指针
int b;
p1 = &b; //正确,p1本身的值可以改变
*p1 = 1; //编译时出错,不能通过p1改变所指的对象
若声明指针常量,则指针本身的值不能被改变。
例
int a;
int * const p2 = &a;
p2 = &b; //错误,p2是指针常量,值不能改变
大家好
欢迎回来继续学习
C++语言程序设计
这一节呢
我们来学习
指针变量的初始化和赋值
我们定义一个变量的时候
总是建议大家
最好给变量做个初始化
不然没有经过初始化的变量
里面可能有垃圾数据
这样盲目地投入运算
可能就会产生一些
不可预见的错误
指针变量也不例外
当我们定义指针变量的时候呢
如果给指针变量做一个初始化
也能够避免指针变量里面
容纳了一些垃圾数据
因此访问内存空间的时候
出一些意外的错误
那么指针变量
该如何初始化呢
还有我们可不可以
用一般的整数
或者什么一个计算的结果
就给指针变量就赋值
去把一个地址放在里面呢
这个是不能的
普通的整数
我们设计的一个什么地址
是不能直接赋值给指针变量的
在指针变量中存放的
只能是我们程序中
合法获得的地址
所以这一节呢
我们来看
如何来给指针变量进行初始化
如何给它赋值
现在我们首先来看
指针变量的初始化
我们来看
这是指针变量初始化的语法形式
在定义这个指针变量的时候呢
我们将初始地址放在这儿
作为指针的初始值
那么这个初始地址
可以是什么样的地址呢
当然不能是
我们直接写出来的整数
它必须是合法获得的地址
比如说看这个例子里面
一个变量a
应该是在此之前
已经定义过的变量
那么我们用地址运算
去取得变量a的地址
把它初始化到指针pa中
这就是一个合法的指针的初始化
大家对指针做初始化的时候
要注意
用变量的地址作为初始值的时候
这个变量
必须在指针初始化之前
就已经声明过
而且变量的类型
与指针它所指向的类型
应该是一致的
注意我们在这儿
看到定义指针的时候
前面它是有一个类型的
我们可以用一个
已经有合法值的指针
去初始化另一个指针变量
那么这也是一种合法的初始化
但是呢
千万不要用一个内部的
非静态变量去初始化静态指针
接下来呢
我们来学习指针变量的赋值运算
看看
我们如何正确地将一个地址
赋值给指针变量
那么
指针变量的赋值的语法形式呢
其实跟其他的
变量赋值的语法形式是一样的
也是用这样的赋值表达式
那需要注意的就是说
赋值运算符右边的这个地址
它里面存放的数据类型
与指针的类型是必须相符的
还有呢
向指针变量赋的值
必须是地址常量
或者是地址变量
不能是普通的整数
那什么样是我们
合法获得的这种地址呢
比如说通过地址运算
求出来的这个
已经定义过的变量
和对象的起始地址
这就是合法的地址
还有
我们在这一章稍后要学到的
用动态内存分配的方式
获得的这个返回地址
它也是合法地址
只要你动态内存分配操作成功了
它就会返回一个合法的地址
这样的地址可以赋值给指针
有一个整数它是例外的
就是整数0
它可以赋值给指针
它并不表示让指针
指向地址为0的空间
而是表示这个指针呢
它是空指针
我们定义
指针所指向类型的时候呢
可以定义一个void类型的指针
表示这个指针
只能用于存放地址
但是没有规定
它所指向的对象类型是什么
所以这个指针
只能存放地址
而不能用它来访问
它所指向的对象
不能用它访问它所指向的内存空间
以往呢
在以前版本的C++标准中
我们都是用0表示空指针
还可以用一个预定义好的null
来表示空指针
那么在C++11标准中呢
有了一个新的
更安全的空指针
那么我们用这样的空指针
可以使得表达更准确
指针运算更加安全
下面我们通过一个完整的实例
来演示指针变量的定义
和使用
这个程序将我们前面
举的局部片断的例子
对指针变量的定义 赋值
使用这些都集成在一个程序中
我们来看
首先
定义一个普通的int变量
然后用它的地址
去初始化一个指针
它们两个都是非静态的局部变量
它的作用域范围
寿命是一样的
所以可以这样去初始化
接下来我们
给10放到变量i里面
给变量i赋个值 10
i里面有了10个数值以后
我们再通过两种情况
尝试输出这个内容
看看比较一下
首先用变量名去输出i的值
我们看到运行结果是10
然后通过指针
先通过指针运算
找到它所指向的对象
也就是i
然后输出
我们看到也是10
所以两者效果就是一样的
下面我们通过一个实例
来演示一下void指针的定义
和使用
在这个例子中呢
我们定义了一个无类型的指针
void指针
注意我们不能定义void变量
变量
你要定义它必须有类型
为什么呢
如果说我们像这个
就是注释掉的这一行
如果我们像注释掉的这一行这样
去定义了无类型的变量
那你想想编译器怎么处理呀
它都不知道
这个变量该要多少存储空间
给它分配多少存储空间
它是两个字节 一个字节
还是四个字节
这些都不知道
因为无 没有类型
那程序没法继续了呀
所以无类型的变量
是不可以定义的
但是为什么可以定义
无类型的指针呢
因为这个变量pv
它自己的类型是确定的
它就是一个指针
只是在此没有定义
它所指的对象的类型
它指向的对象不确定
是无类型的
没有定义
像这样的指针呢
就只能用来存放地址
它可以容纳地址
但是不能通过
这样的指针去访问
它所指向的对象
因为不知道该访问什么
好 接下来我们来看
这个类型转换
又定义一个int变量i
初始化为5
现在呢
我们将i的地址
赋值给无类型的指针pv
可不可以
可以呀
刚才说了
无类型的指针
它就是容纳地址的一个变量
那你把地址放在里面
没有任何问题
那么如果说
我们想用它的内容做转换
将这个无类型的指针
转换成这个int信号
转换成int指针
这是没有问题的
它本来也是指向的int
存放的int地址
转成int指针以后
放到哪儿呢
放到pint这个指针里面去
赋值过去
然后我们就可以任意地
通过指针运算
去访问这个指针所指向的对象了
好 接下来我们来考虑一个问题
如果指针所指向的对象是常量
会怎么样呢
那么接下来我们看
我们怎么定义一个
指向常量的指针
我们如果要一个指针
去指向常量的话呢
就需要在这个指针
它的类型前面
加上const这个关键字
说明这个指针所指向的对象
是一个常量
我们看这个例子里面呢
在指针p1它的类型前面
加了一个const
这样就说明
这个指针p1
是一个指向常量的指针
因此我们就不能通过
这个指针去改变
它所指向对象的值
但是这个本身
这个指针本身可不是常量
这个指针本身是可以被改变的
比如我们看这个例子里面
指针一开始
它初始化为变量a的地址
也就是说
它指向了变量a
但是稍后呢
我们又将变量b的地址
赋值给指针p1
它又改成指向变量b了
那么这个呢是可以的
因为指针p1本身不是常量
但是接下来我们看到
如果我们企图通过指针p1
将1赋值到它所指向的空间
也就是赋值到变量b里面去
编译就出错了
虽然我们看到b本身
它其实不是常量
但是呢
我们将指针定义为了
指向常量的指针
所以结果就是
变量a 变量b
用它们自己的名字都可以改变
它的值
但是通过指针
就不许改变了
因为指针p1
是一个指向常量的指针
所以当我们把一个变量的地址
赋给指针的时候
可以选择你是把全部的访问权限
都授权出去了
让这个指针
可以读取内存空间中的值
也可以改写
还是说呢
你只是部分授权
让这个指针是只读的指针
如果希望一个指针
只能用来读取
某些内存空间中的内容
但是不许覆盖 不许改写
那这种情况下
我们就可以用const来修饰
这个指针所指向对象的类型
这就是指向常量的指针
它相当于一个只读的指针
另外我们定义指针的时候
还可以把指针本身
定义成一个常量
将指针本身定义成一个常量
就是说指针自己的值
是不能改变的
我们看一下
指针本身是常量的情况
大家看
像我们这样声明一个指针p2
仅挨着p2前面
就用了这个const关键字
那说明什么呢
说明p2这个指针
它本身是常量
但是它并不是一个只读的指针
通过p2
我们可以去访问它所指向的对象
去读 去写都可以
但是一旦p2指向了一个变量以后
初始化了以后
它就不能改变了
比如说在这个例子中
一旦p2它指向了a
你看
我们把a的地址用来初始化p2
经过这样的初始化以后
p2自己里面
存放的这个地址是不能改了
它永远就指向a了
我们试图再将b的地址赋值给p2
让它指向变量b
那么编译的时候就会出错
因为什么呢
因为指针p2本身是常量
所以它本身的值不能被改变
-导学
--第1章导学
-计算机系统简介
--计算机系统简介
--计算机系统简介 测试题
-计算机语言和程序设计方法的发展
--计算机语言和程序设计方法的发展 测试题
-面向对象的基本概念
--面向对象的基本概念 测试题
-程序的开发过程
--程序的开发过程
--程序的开发过程 测试题
-信息的表示和储存
--计算机的数字系统
--数据的编码表示
--信息的表示和储存 测试题
-实验指导
-导学
--第二章导学
-C++语言概述
--C++语言概述 测试题
-基本数据类型、常量、变量
--程序举例
--基本数据类型、常量、变量 测试题
-运算与表达式
--运算与表达式 测试题
-实验二:简单程序设计(上)
-数据的输入和输出
--数据的输入和输出
--数据的输入和输出 测试题
-选择结构
--if语句
--switch语句
--选择结构 测试题
-循环结构
--for语句
--循环结构 测试题
-自定义类型
--自定义类型
--自定义类型
-第2章小结
--第二章小结
-实验二:C++简单程序设计(下)
-导学
--导学
-函数定义
--函数定义
--函数定义 测试题
-函数调用
--例3-2
--例3-3
--例3-4
--例3-5
--例3-6
--函数调用 测试题
-嵌套与递归
--例3-9
--例3-10
--嵌套与递归 测试题
-函数的参数传递
--函数的参数传递
--函数的参数传递 测试题
-引用类型
--引用类型 测试题
-含有可变参数的函数
--含有可变参数的函数 测试题
-内联函数
--内联函数 测试题
-constexpr函数
--CONSTEXPR函数课后习题
-带默认参数值的函数
--带默认参数值的函数 测试题
-函数重载
--函数重载 测试题
-C++系统函数
--C++系统函数习题
-第3章小结
--第三章小结
-实验三(上)函数的应用
-实验三(下)函数的应用
-导学
--导学
-面向对象程序的基本特点
--面向对象程序的基本特点 测试题
-类和对象
--类和对象的定义
--类和对象 测试题
-构造函数
--构造函数基本概念
--委托构造函数
--复制构造函数
--构造函数 测试题
-析构函数
--析构函数
--析构函数 测试题
-类的组合
--类的组合
--类的组合程序举例
--前向引用声明
--类的组合 测试题
-UML简介
--UML简介
--UML简介课后习题
-结构体与联合体
--结构体与联合体 测试题
-枚举类
--枚举类
--枚举类 测试题
-第4章小结
--第四章小结
-实验四(上)
--实验四(上)
-实验四(下)
--实验四(下)
-导学
--导学
-标识符的作用域与可见性
--标识符的作用域与可见性 测试题
-对象的生存期
--对象的生存期
--对象的生存期 测试题
-类的静态成员
--类的静态成员 测试题
-类的友元
--类的友元 测试题
-共享数据的保护
--共享数据的保护 测试题
-多文件结构和预编译命令
--多文件结构和预编译命令 测试题
-第5章小结
--小结
-实验五
--实验五
-导学
--导学
-数组的定义与初始化
--数组的定义与使用
--一维数组应用举例
--数组的定义与初始化 测试题
-数组作为函数的参数
--数组作为函数的参数 测试题
-对象数组
--对象数组
--对象数组 测试题
-基于范围的for循环
-指针的定义和运算
--指针的定义和运算 测试题
-综合实例
--综合实例
-实验六(上)
--实验六上
-指针与数组
--指针数组
--指针与数组 测试题
-指针与函数
--指针类型的函数
--指向函数的指针
--指针与函数 测试题
-对象指针
--对象指针
--对象指针 测试题
-动态内存分配
--动态内存分配 测试题
-智能指针
--智能指针
-vector对象
--vector对象
--vector对象 测试题
-对象复制与移动
--移动构造
--对象复制与移动 测试题
-字符串
--C风格字符串
--string类
--字符串 测试题
-第6章小结
--第六章小结
-综合实例
--综合实例
-实验六(下)
--实验六(下)