c的指针

指针的基本概念,一维数组的指针。

什么是指针

指针也称作指针变量,大小为4个字节(或8个字节)的变量,其内容代表一个内存地址。

sizeof(T*) 4字节(64位计算机上可能是8字节)

T是任何变量类型

指针的定义

类型名 * 指针变量名

如 floatp,p是指针变量名,变量p的类型是*float *

注意:保存地址的是p不是*p

通过表达式 *p可以读写从地址p开始的sizeof(float)个字节,*p等价于存放在地址p处的一个float类型变量。

注:float可以被任何变量类型替代

指针用法

char ch1 = 'a'
char *p = &ch1
char ch2 = *p
p = &ch2
* p = 'd'

注意要使用&取地址运算符(&x的类型是T*),p是地址,*p是p所指的变量

不同类型指针的相互赋值

不同类型的指针,如果不经过强制类型转换,不能直接赋值

int *pn,char *pc,char c =0x65;//0x是十六进制
pn = (int *)&c;
int n = *pn;//n值不确定
*pn = 0x12345678//编译能过但运行可能出错

运行出错的原因

n值不确定

*pn是int类型,读取四个字节,而c只占开始的一个字节

编译能过但运行可能出错

从pn指向的4个字节往里面写东西,但不能确定c后面的3个字节是否能够访问(操作系统不让访问,导致程序崩溃),或者可以访问,但这3个空间可能是其他变量的空间(程序出错)

指针运算

两个同类型的指针变量可以比较大小

地址p1<地址p2 p1<p2的值为真

同类型的指针变量可以相减

两个T*类型的指针p1和p2

p1-p2=(地址p1-地址p2)/sizeof(T)

指针变量加减一个整数的结果是指针

n:整数类型的变量或常量

p+n:T*类型的指针,指向地址:

地址p+n * sizeof(T)

可自增,可自减

T*类型的指针p指向地址n

p++,++p:p指向n + sizeof(T)

指针可以用下标运算符[]运算

p[n]等价于*(p+n)

空指针

地址0不能访问,指向地址0的指针就是空指针

可以用”NULL”关键字对任何类型的指针进行赋值,NULL实际上就是整数0,值为NULL的指针就是空指针

指针可以作为条件表达式使用。如果指针的值为NULL,则相当于为假,值不为NULL,就相当于为真

指针和数组

数组是特殊类型的指针

指针形式的数组运算:

int *p;
int a[200];
p=a;//p指向数组a的起始地址,即p指向a[0]
*p=10;//a[0]=10
*(p+1)=20;//a[1]=20
p[0]=30;//a[0]=30
for(int i = 0;i<10;++i)&#123;
    *(p+i)=i;//对数字的前10个元素进行赋值
&#125;
p = a + 6//p指向a[6]

颠倒一个数组

void reverse(int *p,int size)&#123;
    int i;
    for(i=0;i<size/2;++i)&#123;
        int tmp = p[i];
        p[i]=p[size-1-i];
        p[size-1-i]=tmp;
    &#125;
&#125;

指针和二维数组

二维数组的地址是连续存放的,所以二维本质上是一维。

void reverse(int *p,int size)&#123;
    int ihttps://github.com/hexojs/hexo/files/2246484/log.txt
    for(i=0;i<size/2;++i)&#123;
        int tmp = p[i];
        p[i]=p[size-1-i];
        p[size-1-i]=tmp;
    &#125;
&#125;
int a[3][4]=&#123;&#123;1,2,3,4&#125;,&#123;5,6,7,8&#125;&#125;;
reverse(a[0],5);

颠倒后的数组为

&#123;&#123;5,4,3,2&#125;,&#123;1,6,7,8&#125;&#125;

指向指针的指针

T **p

p是指向指针的指针,p指向的地方存放着一个类型为T*的指针

*p的类型是T*

int **pp;//是指向int*类型指针的指针
int *p;
int n = 1234;
p = &n;//n的类型是int*
pp=&p;//*pp是p,所以*(*pp)是n

指针和字符串

char *p=”asadcd”

char name[20];
scanf("%s",name);

name是char *类型的,name实际上就是地址

C(string.h)字符串操作函数总结

void指针

因sizeof(void)没有定义,所以*p无定义,++p等运算也无定义

void指针的用处

在头文件cstring中声明的内存操作库函数memset用到了void指针

void *memset(void * dest,int ch,int n);

dest是void*,所以可以是任何类型的指针,ch是字符的ASCII码

将从dest开始的n个字节都设置成ch,返回值是dest,ch每次只对一个字节起作用。

char a[200]=""//空串每一个位置都是"\0"
memset(a,'a',10)//将前10个字符设置为’a‘

输出a数组得到aaaaaaaaaa

memset函数的用处

清空(运用sizeof),无穷大(0x3f),初始化最大值(0x7f),详解见memset函数详解

函数指针

基本概念

程序运行期间,每个函数都会占用一段连续的内存空间。函数名就是该函数所占内存区域的起始地址(也称入口地址)我们可以将函数的入口地址赋给一个指针变量,然后通过指针变量就可以调用这个函数。这种指向函数的指针变量称为“函数指针”。

定义形式

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

类型名是函数的返回类型

例如:

int(*pf)(int,char);

表示pf是一个函数指针,他所指向的函数的返回值为int,该函数有两个参数

使用方法

先定义指针;

把函数名赋值给指针变量名;

指针变量名名(实参表);

qsort库函数

mooc视频



转载请注明: One Fly Bird's Nest c的指针

上一篇
隐藏和覆盖的区别和用法 隐藏和覆盖的区别和用法
隐藏和覆盖的区别和用法 以下内容来自隐藏和覆盖的区别和用法 静态类型和动态类型任何一个引用变量都有两个类型:一个叫静态类型,也就是定义该引用变量的类型;另一个叫动态类型,也就是该引用实际指向的对象类型。 比如对于两个类A和类B,有:A a
2018-11-23
下一篇
利用github把本地图片显示到博客上的方法 利用github把本地图片显示到博客上的方法
上方展示的图片就是把本地图片传到github然后展示在博客上的结果 想法来源:与某位兄弟聊天时的灵光一闪+闲的慌+知乎+没钱买域名用图床 准备工作 注册了一个github的账号 git教程,推荐雪峰老师的网站 有git bash
2018-11-21
目录