【C++】指针和函数
指针和函数
标签:c++
一、基本概念
定义:
也称作“指针变量”,大小为4个字节,内容代表一个内存地址
指针的定义及使用:
定义:
int *p;//指向的变量类型为整型
char *pc;
赋值:
int *p = (int *) 4000;//强制类型转换,让p = 4000
char ch1 = ‘A’;
char *pc = &ch1;
*pc = ‘B’;
char ch2 = *pc;
pc = &ch2;
注:指针定义后就要赋值,防止变成野指针
二、指针的相互赋值
不同类型的指针相互赋值要强制类型转换
int *pn;
char *pc;
char c = 0x65;//e
pn = pc;//编译出错,类型不匹配
pn = &c;//编译出错
pn = (int *) &c;//可以,但是&c只代表一个字节,pn代表四个字节,此时pn会占用&c后面的三个字节,导致错误
int n = *pn;//n中的内容不是0x65
因此,不要用不同类型的指针相互赋值
三、指针的运算
比较大小:
两个同类型的指针p1
, p2
,如果地址p1
<地址p2
,则p1
<p2
,其余同理
相减:
p1 – p2 = (地址1-地址2)/sizeof(T)
T为指针的类型
加减整数类型变量或者常量:
p + n
等价于:地址p + n * sizeof( T )
p - n
等价于:地址p - n * sizeof( T )
自增自减:
同3
下标运算符[ ]:
p[ n ]
等价于 *( p + n )
四、空指针
空指针NULL,即为地址0
可以做条件表达式使用
五、指针作为函数参数
传递指针的方式依然是指传递,注意函数是在对指针操作还是对指针所指的内容操作,即函数只能改变指针指向地址中的内容,不能改变指针本身
#include<iostream>
using namespace std;
void Swap(int *p1, int *p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main()
{
int m = 4, n = 3;
Swap(&m, &n);
cout<<m<<','<<n;
}
结果:3,4
使用指针作为函数参数时,应先判断指针是否为空,避免野指针对函数造成影响
返回一个指针时,也要注意返回非空指针
六、指针和数组
数组的名字即为一个指针,作为函数形参时,T *p
和T p[ ]
完全等价
七、常量指针和指针常量
常量指针
const T* p
特点:不能通过常量指针修改指向的内容,即内容可以修改,但是要用其他方法
指针常量
T *const p = p0
特点:定义之后指针p
就不能指向其他位置,但是可以通过指针对其指向内容修改
八、字符串和指针
普通字符串和指针的关系
字符串常量的类型就是char *
,字符数组的类型也是char *
char name[20];
char *pName = name;
string
对象和char *
指针的关系
可以用
char *
类型指针对string
对象赋值string
对象有成员函数:const char *c_str()
,返回的是字符串指针如果
s
是一个string
对象,对其执行const char *p = s.c_str()
,当s的内容改变时,p可能会失效,因为s的位置可能发生改变#include<iostream>
#include<cstring>
#include<string>
using namespace std;
int main()
{
string s;
char str1[20] = "the flower of war";
char str2[20] = "hhh";
char *p = str1;
s = p;
cout<<"s:"<<s<<endl;
strcat(str2, s.c_str());
cout<<"str2:"<<str2<<endl;
return 0;
}
常用字符串操作库函数
cstring
中声明:
char *strcat(char *dest, const char *src)
,返回dest
char *strchr(const char *src, int c)
,寻找c
在src
中第一次出现的位置,找到则返回位置指针,否则返回NULL
int strcmp(const char *s1, const char *s2)
,比较大小
char *strcpy(char *dest, const char *src)
,复制
int strlen(const char *src)
,求长度
char *strlwr(char *str)
,字母转小写
char *strupr(char *str)
,字母转大写
char *strncat(char *dest, const char *src, int n)
,连接前n
个字符到dest
类似有:strncpy
, strncmp
cstdlib
中声明:
atoi
:字符串转整数
atof
:字符串转浮点数
itoa
:整数转字符串,char *itoa(int value, char *string, int radix)
九、 void指针和内存操作库函数
定义及特点:
指针的类型为void *
- 可以用任何类型的指针对其初始化
- 主要用于内存复制
sizeof()
及各种指针运算不适用于空指针
库函数
在cstring
中声明
void *memset(void *dest, int ch, int n)
,将ch
复制到dest
前n
个字节中
void *memcpy(void *dest, void *src, int n)
,将src
的开始n
个字节复制到dest
中
示例
#include<iostream>
using namespace std;
void *myMemcpy(void *dest, const void *src, int n)
{
char *pDest = (char *)dest;//必须先将形参进行强制类型转换
char *pSrc = (char *)src;
for(int i = 0; i < n; ++i)
*(pDest + i) = *(pSrc + i);
return dest;
}
int main()
{
char szName[10] = "abcdsedf";
char destName[10];
myMemcpy(destName, szName,5);
cout<<szName<<endl;
for(int i = 0; i < 5; ++i)
cout<<destName[i];
}
十、 函数指针
定义:
类型名 (*指针变量名)(参数类型1,参数类型2,……)
赋值及调用:
可以用一个原型匹配的函数的名字给一个函数指针赋值
调用格式:函数指针名(实参表)
#include<iostream>
using namespace std;
void PrintMin(int a, int b)
{
if(a < b)
cout<<a;
else
cout<<b;
}
int main()
{
int x = 4, y = 1;
void (*pf)(int ,int) = PrintMin;
pf(x, y);
return 0;
}
应用
qsort()
函数
原型:void qsort(void *base, int nelem, unsigned int width, int (*pfCompare)(const void *, const void *))
其中比较函数的原型:int
函数名(const void *elem1, const void *elem2)
注意:
- 返回值必须是
int
- 两个参数的类型必须都是
const void *
- 假设是对
int
排序的话,如果是升序,那么就是如果a比b大返回一个正值,小则负值,相等返回0,其他的依次类推
#include<iostream>
#include <cstdlib>
using namespace std;
//比较函数可以根据自己的需求写,其作用相当但不限于
//使用sort()时的运算符重载
int myCompare(const void *elem1, const void *elem2)
{
unsigned int *p1, *p2;
p1 = (unsigned int *)elem1;
p2 = (unsigned int *)elem2;
return (*p1 % 10) - (*p2 % 10);
}
const int NUM = 5;
int main()
{
unsigned int a[NUM] = {8,123,11,10,4};
qsort(a, NUM, sizeof(unsigned int), myCompare);
for(int i = 0; i < NUM; ++i)
cout<<a[i]<<endl;
return 0;
}
十一、 指针域动态内存分配
使用方法:
指针类型 *p = new 指针类型(int *p = new int)
指针类型 *p = new 指针类型[空间大小](int *p = new int[N])
,分配到N*sizeof(T)
的空间
注意
- 分配空间失败时,系统会抛出异常
- 动态分配的内存使用结束后要释放,方法为:
delete 指针
,delete [ ] 指针
- 释放一个指针后,不会使指针的值变为
NULL
十二、 二阶指针
指向指针的指针,大小永远为4字节,对应多维数组
十三、指针数组
定义:
T *a[N]
数组中每个元素的类型是T *
,a
的类型是T **
示例:
#include<iostream>
using namespace std;
int main()
{
char **p = NULL;
char *countries[] = {"China","USA","Japan","France"};
p = countries;
for(int i = 0; i < 4; ++i)
cout<<*(p + i)<<endl;
cout<<*((*p) + 1);
}
【C++】指针和函数的更多相关文章
- 12-返回指针的函数&&指向函数的指针
前言 接下来我只讲指针的最常见用法,比如这一章的内容----返回指针的函数 与 指向函数的指针 一.返回指针的函数 指针也是C语言中的一种数据类型,因此一个函数的返回值肯定可以是指针类型的. 返回 ...
- 我的c++学习(12)指针作为函数参数
◆ 引用调用与指针传值调用C++中函数的参数的基本使用方法是传值.为了弥补单纯传值的不足,以引用作为函数的参数,从逻辑上讲引用是别名,在函数中对参数的操作,就是对实参的操作,而在物理上是传实参的地址. ...
- C#委托与C语言函数指针及函数指针数组
C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用 ...
- 【C语言】14-返回指针的函数与指向函数的指针
前言 前面我们花了接近3个章节学习指针,应该都感受到指针的强大了吧.指针可以根据地址直接操作内存中的数据,使用得当的话,不仅能使代码量变少,还能优化内存管理.提升程序性能.关于指针的内容还非常多,比如 ...
- C/C++ 一段代码区分数组指针|指针数组|函数指针|函数指针数组
#include<stdio.h> #include<stdlib.h> #include<windows.h> /* 举列子说明什么是函数指针 */ //以一个加 ...
- 【学习笔记】【C语言】返回指针的函数
函数如果带*的返回的就是指针 char *test(){ } #include <stdio.h> char *test(); /* 返回指针的函数 */ int main() { cha ...
- C++ 二维数组(双重指针作为函数参数)
本文的学习内容参考:http://blog.csdn.net/yunyun1886358/article/details/5659851 http://blog.csdn.net/xudongdong ...
- Delphi 函数指针(函数可以当参数)
首先学习: 指向非对象(一般的)函数/过程的函数指针 Pascal 中的过程类型与C语言中的函数指针相似,为了统一说法,以下称函数指针.函数指针的声明只需要参数列表:如果是函数,再加个返回值.例如声明 ...
- C语言中的声明解析规则——数组,指针与函数
摘要:C语言的申明存在的最大问题是:你无法以一种人们所习惯的自然方式和从左向右阅读一个声明,在引入voliatile和const关键字以后,情况更加糟糕了.由于这些关键字只能出现在声明中,是的声明形式 ...
- C语言的本质(12)——指针与函数
往往,我们一提到指针函数和函数指针的时候,就有很多人弄不懂.下面详细为大家介绍C语言中指针函数和函数指针. 1.指针函数 当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需 ...
随机推荐
- CF706A Beru-taxi 题解
Content 有一个人在点 \((a,b)\) 等出租车.已知他周围共有 \(n\) 辆出租车,其中第 \(i\) 辆车在点 \((x_i,y_i)\) 上,速度为 \(v_i\).这个人想打能让他 ...
- Spring Security Filter 学习笔记
过滤器可以简单理解成用于拦截请求,并执行相应逻辑的代码. 在Spring Security架构中实现过滤器 在SpringSecurity中,可以通过实现 javax.servlet 包中的 Filt ...
- 【剑指Offer】调整数组顺序使奇数位于偶数前面 解题报告(Python)
[牛客网]调整数组顺序使奇数位于偶数前面 解题报告 标签(空格分隔): 牛客网 题目地址:https://www.nowcoder.com/questionTerminal/beb5aa231adc4 ...
- 1120 机器人走方格 V3
1120 机器人走方格 V3 基准时间限制:1 秒 空间限制:131072 KB N * N的方格,从左上到右下画一条线.一个机器人从左上走到右下,只能向右或向下走.并要求只能在这条线的上面或下面走, ...
- 【嵌入式AI】全志 XR806 say hello world
欢迎关注我的公众号 [极智视界],回复001获取Google编程规范 O_o >_< o_O O_o ~_~ o_O 大家好,我是极智视界,本文介绍了全志 ...
- eclipse的安装及最大子数组求和
我安装的是eclipse.由于eclipse是一个基于Java的课扩展开发平台,所以在安装eclipse之前要先安装Java的开发工具JDK(Java Devolopment Dit),且安装JDK需 ...
- Mysql数据库服务端的安装
一般提到Mysql数据库的安装在工作当中是说的安装数据库管理软件的服务端,服务端的安装可以安装在Windows环境,也可以安装在Linux环境. Windows环境安装:目前安装比较流行的是5.7,增 ...
- [opencv]approxDP多边形逼近获取四边形轮廓信息
#include "opencv2/opencv.hpp" #include <iostream> #include <math.h> #include & ...
- Eclipse 常用快捷键大全
15 个 Eclipse 常用开发快捷键使用技巧 1.alt+? 或 alt+/:自动补全代码或者提示代码 2.ctrl+o:快速outline视图 3.ctrl+shift+r:打开资源列表 4.c ...
- MySQL数据操作与查询笔记 • 【第7章 连接查询】
全部章节 >>>> 本章目录 7.1 内连接查询 7.1.1 交叉连接(笛卡尔积) 7.1.2 内连接查询概要 7.1.3 内连接案例 7.1.4 自然连接 7.2 多表连 ...