指针和函数

标签:c++


一、基本概念

定义:

也称作“指针变量”,大小为4个字节,内容代表一个内存地址

指针的定义及使用:

  • 定义:

    1. int *p;//指向的变量类型为整型
    2. char *pc;
  • 赋值:

    1. int *p = (int *) 4000;//强制类型转换,让p = 4000
    2. char ch1 = A’;
    3. char *pc = &ch1;
    4. *pc = B’;
    5. char ch2 = *pc;
    6. pc = &ch2;

    注:指针定义后就要赋值,防止变成野指针

二、指针的相互赋值

不同类型的指针相互赋值要强制类型转换

  1. int *pn;
  2. char *pc;
  3. char c = 0x65;//e
  4. pn = pc;//编译出错,类型不匹配
  5. pn = &c;//编译出错
  6. pn = (int *) &c;//可以,但是&c只代表一个字节,pn代表四个字节,此时pn会占用&c后面的三个字节,导致错误
  7. 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

可以做条件表达式使用

五、指针作为函数参数

  • 传递指针的方式依然是指传递,注意函数是在对指针操作还是对指针所指的内容操作,即函数只能改变指针指向地址中的内容,不能改变指针本身

    1. #include<iostream>
    2. using namespace std;
    3. void Swap(int *p1, int *p2)
    4. {
    5. int temp = *p1;
    6. *p1 = *p2;
    7. *p2 = temp;
    8. }
    9. int main()
    10. {
    11. int m = 4, n = 3;
    12. Swap(&m, &n);
    13. cout<<m<<','<<n;
    14. }
    15. 结果:3,4
  • 使用指针作为函数参数时,应先判断指针是否为空,避免野指针对函数造成影响

  • 返回一个指针时,也要注意返回非空指针

六、指针和数组

数组的名字即为一个指针,作为函数形参时,T *pT p[ ]完全等价

七、常量指针和指针常量

常量指针

const T* p

特点:不能通过常量指针修改指向的内容,即内容可以修改,但是要用其他方法

指针常量

T *const p = p0

特点:定义之后指针p就不能指向其他位置,但是可以通过指针对其指向内容修改

八、字符串和指针

普通字符串和指针的关系

字符串常量的类型就是char *,字符数组的类型也是char *

  1. char name[20];
  2. char *pName = name;

string对象和char *指针的关系

  • 可以用char *类型指针对string对象赋值

  • string对象有成员函数:const char *c_str(),返回的是字符串指针

  • 如果s是一个string对象,对其执行 const char *p = s.c_str(),当s的内容改变时,p可能会失效,因为s的位置可能发生改变

    1. #include<iostream>
    2. #include<cstring>
    3. #include<string>
    4. using namespace std;
    5. int main()
    6. {
    7. string s;
    8. char str1[20] = "the flower of war";
    9. char str2[20] = "hhh";
    10. char *p = str1;
    11. s = p;
    12. cout<<"s:"<<s<<endl;
    13. strcat(str2, s.c_str());
    14. cout<<"str2:"<<str2<<endl;
    15. return 0;
    16. }

常用字符串操作库函数

cstring中声明:

char *strcat(char *dest, const char *src),返回dest

char *strchr(const char *src, int c),寻找csrc中第一次出现的位置,找到则返回位置指针,否则返回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复制到destn个字节中

void *memcpy(void *dest, void *src, int n),将src的开始n个字节复制到dest

示例

  1. #include<iostream>
  2. using namespace std;
  3. void *myMemcpy(void *dest, const void *src, int n)
  4. {
  5. char *pDest = (char *)dest;//必须先将形参进行强制类型转换
  6. char *pSrc = (char *)src;
  7. for(int i = 0; i < n; ++i)
  8. *(pDest + i) = *(pSrc + i);
  9. return dest;
  10. }
  11. int main()
  12. {
  13. char szName[10] = "abcdsedf";
  14. char destName[10];
  15. myMemcpy(destName, szName,5);
  16. cout<<szName<<endl;
  17. for(int i = 0; i < 5; ++i)
  18. cout<<destName[i];
  19. }

十、 函数指针

定义:

类型名 (*指针变量名)(参数类型1,参数类型2,……)

赋值及调用:

  • 可以用一个原型匹配的函数的名字给一个函数指针赋值

  • 调用格式:函数指针名(实参表)

    1. #include<iostream>
    2. using namespace std;
    3. void PrintMin(int a, int b)
    4. {
    5. if(a < b)
    6. cout<<a;
    7. else
    8. cout<<b;
    9. }
    10. int main()
    11. {
    12. int x = 4, y = 1;
    13. void (*pf)(int ,int) = PrintMin;
    14. pf(x, y);
    15. return 0;
    16. }

应用

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,其他的依次类推
  1. #include<iostream>
  2. #include <cstdlib>
  3. using namespace std;
  4. //比较函数可以根据自己的需求写,其作用相当但不限于
  5. //使用sort()时的运算符重载
  6. int myCompare(const void *elem1, const void *elem2)
  7. {
  8. unsigned int *p1, *p2;
  9. p1 = (unsigned int *)elem1;
  10. p2 = (unsigned int *)elem2;
  11. return (*p1 % 10) - (*p2 % 10);
  12. }
  13. const int NUM = 5;
  14. int main()
  15. {
  16. unsigned int a[NUM] = {8,123,11,10,4};
  17. qsort(a, NUM, sizeof(unsigned int), myCompare);
  18. for(int i = 0; i < NUM; ++i)
  19. cout<<a[i]<<endl;
  20. return 0;
  21. }

十一、 指针域动态内存分配

使用方法:

指针类型 *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 **

示例:

  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. char **p = NULL;
  6. char *countries[] = {"China","USA","Japan","France"};
  7. p = countries;
  8. for(int i = 0; i < 4; ++i)
  9. cout<<*(p + i)<<endl;
  10. cout<<*((*p) + 1);
  11. }

【C++】指针和函数的更多相关文章

  1. 12-返回指针的函数&&指向函数的指针

    前言 接下来我只讲指针的最常见用法,比如这一章的内容----返回指针的函数 与 指向函数的指针   一.返回指针的函数 指针也是C语言中的一种数据类型,因此一个函数的返回值肯定可以是指针类型的. 返回 ...

  2. 我的c++学习(12)指针作为函数参数

    ◆ 引用调用与指针传值调用C++中函数的参数的基本使用方法是传值.为了弥补单纯传值的不足,以引用作为函数的参数,从逻辑上讲引用是别名,在函数中对参数的操作,就是对实参的操作,而在物理上是传实参的地址. ...

  3. C#委托与C语言函数指针及函数指针数组

    C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用 ...

  4. 【C语言】14-返回指针的函数与指向函数的指针

    前言 前面我们花了接近3个章节学习指针,应该都感受到指针的强大了吧.指针可以根据地址直接操作内存中的数据,使用得当的话,不仅能使代码量变少,还能优化内存管理.提升程序性能.关于指针的内容还非常多,比如 ...

  5. C/C++ 一段代码区分数组指针|指针数组|函数指针|函数指针数组

    #include<stdio.h> #include<stdlib.h> #include<windows.h> /* 举列子说明什么是函数指针 */ //以一个加 ...

  6. 【学习笔记】【C语言】返回指针的函数

    函数如果带*的返回的就是指针 char *test(){ } #include <stdio.h> char *test(); /* 返回指针的函数 */ int main() { cha ...

  7. C++ 二维数组(双重指针作为函数参数)

    本文的学习内容参考:http://blog.csdn.net/yunyun1886358/article/details/5659851 http://blog.csdn.net/xudongdong ...

  8. Delphi 函数指针(函数可以当参数)

    首先学习: 指向非对象(一般的)函数/过程的函数指针 Pascal 中的过程类型与C语言中的函数指针相似,为了统一说法,以下称函数指针.函数指针的声明只需要参数列表:如果是函数,再加个返回值.例如声明 ...

  9. C语言中的声明解析规则——数组,指针与函数

    摘要:C语言的申明存在的最大问题是:你无法以一种人们所习惯的自然方式和从左向右阅读一个声明,在引入voliatile和const关键字以后,情况更加糟糕了.由于这些关键字只能出现在声明中,是的声明形式 ...

  10. C语言的本质(12)——指针与函数

    往往,我们一提到指针函数和函数指针的时候,就有很多人弄不懂.下面详细为大家介绍C语言中指针函数和函数指针. 1.指针函数 当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需 ...

随机推荐

  1. idea删除同一个模块后新建模块显示被占用

    当我们某个模块因为什么原因需要删除重建的时候 ,输入完模块名称并不能创建出来,这是因为模块已经被注册 解决办法: 1.右键点击项目名称---选择Load/Unload Modules 2.将已经删除的 ...

  2. socket网络编程基础模块

    更多功能 sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) 参数一:地址簇 socket.AF_INET IPv4(默认) socket. ...

  3. Django modules模块

    http://www.cnblogs.com/wupeiqi/articles/5246483.html

  4. 使用vi编辑时,上下左右键显示为字符的问题

    1.此问题是因为ubuntu系统自带的 vi 不完整导致,解决方法:安装完整的vi,执行命令: # sudo apt-get install vim-gtk

  5. Spring核心原理之 IoC容器中那些鲜为人知的细节(3)

    本文节选自<Spring 5核心原理> Spring IoC容器还有一些高级特性,如使用lazy-init属性对Bean预初始化.使用FactoryBean产生或者修饰Bean对象的生成. ...

  6. c++设计模式概述之命令

    代码写的不够规范,目的是为了缩短文章篇幅,实际中请不要这样做.  1.概述 命令模式是一种数据驱动的模式.将请求封装到命令的对象中,再传给调用对象,调用对象再处理该命令. [将一个请求封装为一个对象] ...

  7. 【LeetCode】1101. The Earliest Moment When Everyone Become Friends 解题报告 (C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 并查集 日期 题目地址:https://leetcod ...

  8. 【LeetCode】21. Merge Two Sorted Lists 合并两个有序链表

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:合并,有序链表,递归,迭代,题解,leetcode, 力 ...

  9. 第四十八个知识点:TPM的目的和使用方法

    第四十八个知识点:TPM的目的和使用方法 在检查TPM目的之前,值得去尝试理解TPM设计出来的目的是为了克服什么样的问题.真正的问题是信任.信任什么?首先内存和软件运行在电脑上.这些东西能直接的通过操 ...

  10. [数学]高数部分-Part I 极限与连续

    Part I 极限与连续 回到总目录 Part I 极限与连续 一.极限 泰勒公式 基本微分公式 常用等价无穷小 函数极限定义 数列极限数列极限 极限的性质 极限的唯一性 极限的局部有限性 极限的局部 ...