C++ Primer 学习笔记与思考_7 void和void*指针的用法

(一)void的含义

void的字面意思是“无类型”,void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变量,让我们试着来定义:

void a;

这行语句编译时会出错,提示“illegal use of type ‘void‘”。不过,即使void a的编译不会出错,它也没有任何实际意义。

void真正发挥的作用在于:

(1) 对函数返回的限定;

(2) 对函数参数的限定。

int f(void); equal to   int f();
void f();

(二)void*指针

C++提供了一种特殊的指针类型void*,它可以保存任何类型对象的地址,void*表明该指针与一地址值相关,但是不清楚在此地址上的对象的类型。Void*指针只支持几种有限的操作:

1.与另一个指针进行比较

2.向函数传递void*指针或从函数中返回void*指针

3.给另一个void*指针赋值

4.不允许使用void*指针操纵它指向的对象

由于其他指针都包含有地址信息,所以将其他指针的值赋给空类型指针是合法的;反之,将空类型指针赋给其他指针则不被允许,除非进行显式转换。

因此,void*的作用大致如下:

1. 传参:通用类型

可以作为函数模板,链表等参数的通用参数。在使用时,只需要强制类型转换就可以。

在WinSocket编程中,_beginthread()函数的参数就是使用void*的一个实例。

2.强制类型转换

有时候由于重载等的干扰,导致需要转换成void *,来进行取地址。

例如,(void *)obj.member,就可以取到member的地址;直接&(obj.member)取到的实际上是obj的开始地址。

3.指向0的地址

(void *)0,指向全是0的地址,相当于NULL。

非void类型显式转换为void类型表达式,用于避免一些代码静态检查工具的警告。

#include<iostream>
#include<string>
using namespace std;
int main()
{

	double obj=3.14;
	int a=7;
	double *pd=&obj;
	void *pv=&obj;  //ok
	pv=&a;  //ok
    (*pv)++; // error,不得操纵对象
	int *ptr=&a;
	void *p=ptr; //ok
	ptr=p;  //error,不能将空类型指针赋给其他指针
	ptr=(int*)p; //ok,显式转换
	return 0;
} 

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 01:31:32

C++ Primer 学习笔记与思考_7 void和void*指针的用法的相关文章

C++ Primer 学习笔记与思考_7 void和void*指针的使用方法

(一)void的含义 void的字面意思是"无类型",void差点儿仅仅有"凝视"和限制程序的作用,由于从来没有人会定义一个void变量,让我们试着来定义: void a; 这行语句编译时会出错.提示"illegal use of type 'void'".只是.即使void a的编译不会出错.它也没有不论什么实际意义. void真正发挥的作用在于: (1) 对函数返回的限定: (2) 对函数參数的限定. int f(void); equal t

C++ Primer学习笔记与思考_1----变量和基本类型

C++ Primer学习笔记与思考_1----变量和基本类型 类型有什么作用? 类型告诉我们数据代表什么意思以及可以对数据执行哪些操作. 一:基本内置类型 C++标准规定了每个算术类型的最小存储空间,但是它并不阻止编译器使用更大的存储空间.对于int,几乎所有的编译器使用的存储空间都比所要求的大. 字符类型有两种char和wchar_t,其中wchar_t用于扩展字符集,比如汉字和日文,这些字符集中的一些字符不能用单个的char表示.  c++ primer第32页      和其他类型不同,c

C++ Primer 学习笔记_103_特殊工具与技术 --类成员指针

特殊工具与技术 --类成员指针 成员指针可以做到:获得特定成员的指针,然后从一个对象或别的对象获得该成员.成员指针应该包含类的类型以及成员的类型. 一.声明成员指针 测试类: class Screen { public: typedef std::string::size_type index; char get() const; char get(index ht,index wd) const; private: std::string contents; index cursor; ind

C++ Primer 学习笔记与思考_10 类型转换易错处大总结

(一)隐式转换 先来看一组样例: int ival=0; ival=3.451+3; 首先做加法操作,操作数分别为int和double类型,c++并没有直接把两个数加在一起,而是提供了一组转换规则,以便在执行算术操作之前,将两个操作数转换为同一种数据类型.在这里是自动执行的,所以他们被成为隐式转换. 因为 C++定义了算术类型之间的内置转换以尽可能防止精度损失,所以这里3转换为double型相加得6.451.但是下一步赋值的时候,右操作数进行截断处理,对此精度会有损失,编译器也会给出警告. 2.

C++ Primer 学习笔记与思考_9 表达式中过的那些容易忽略的地方

(一)移位操作符用于IO 输入输出标准库分别重载了位操作符>>和<<用于输入和输出.并且像其他的二元操作符一样,移位操作符也是左结合的,这也正好说明了我们为什么可以把多个输入输出操作连接为单个语句: cout<<"hi"<<"there "<<endl; 将其执行为: ( (cout<<"hi")<<"there" )<<endl;

C++ Primer 学习笔记与思考_4 ---getline&amp;&amp;size_type&amp;&amp;const_iterator混搭

(一)getline的用法 我们在使用string读入字符串的时候,其输入操作符: * 读取并忽略开头所有空白字符(如空格,换行符,制表符) * 读取字符直至再次遇到空白字符,读取终止. 所以如果我们输入"hello world",string将只输出hello. 为了解决这个问题,我们引入getline函数,它接受两个参数:一个输入流对象和一个string对象,但是getline会读取换行符,保存到string中时却忽略换行符,所以string中是空串. 我们通常用getchar()

C++ Primer 学习笔记与思考_3 ---头文件那些事儿(extern)

(一)extern在头文件里的使用方法 由于头文件包括在多个源文件里.而且变量的定义仅仅能出现一次,所以在头文件里. 仅仅能够声明不能够出现定义. 我们能够在头文件里用extern声明全局变量,这样在包括此头文件的cpp 中可直接使用 声明过的这个全局变量(例如以下面程序中的变量a). 可是有三个例外: 1.头文件里能够定义类 2.值在编译时就已经知道的const对象 3.能够定义inline函数 extern int ival; // yes extern int ival=1; //erro

C++ Primer 学习笔记与思考_5 bitset你用的正确吗?

bitset类型比整型值上的低级位操作更容易使用,简化了位集的处理.在定义bitset时,要明确bitset含有的位数,在尖括号内给出它的长度值. 注意位集合的编号从0开始,低位存低阶位. 最重要的一个问题:bitset的下标是从右边开始的!!!!很多人的博客都写错了,希望引起大家注意. 1.使用unsigned long值初始化bitset对象 若bitset类型长度大于unsigned long值的二进制位数,则其余的高阶位将置为0:若bitset类型长度小于unsigned long值的二

C++ Primer 学习笔记与思考_5 数组和动态数组易错点解读

1. 数组的定义 数组定义中的类型名可以是内置数据类型或者类类型:除了引用之外,数组元素的类型还可以是任意的复合类型.另外,非const变量以及要到运行阶段才知道其值的const变量都不能用于定义数组的维数. #include <iostream> #include <string> #include <cstring> #include <bitset> using namespace std; int main() { const int MAXN1 =