C语言进阶课程笔记之指针

指针

指针就是保存地址的变量,想一下,无论什么类型的指针,因为地址的所占用的空间是一样的,所以指针所占用的字节应该是一样的。后面不妨给出验证。我们常用的写法无外乎向下面这样

int i;
int* p = &i;
int* p,q;
int *p,q;

指针变量

普通变量的值是实际的值
指针变量的值是具有实际值的变量的地址

Paste_Image.png

我们这里不妨就验证一下指针所占的空间到底是不是一样的。

#include<stdio.h>
int main(){
    char* p = NULL;
    int* q = NULL;
    int i = 5;
    char c = 6;
    q =&i;
    p =&c;
    printf("p's size is %d\n",sizeof(p));
    printf("q's size is %d\n",sizeof(q));
    return 0;
}
  

我们在cpp.sh上编译运行的结果是

Paste_Image.png

而在我的电脑上运行的结果是

Paste_Image.png

对呀,同样的代码,为什么有不同的结果呢?因为我们的运行环境不一样,在我电脑中指针只占用4的字节,而在cpp.sh服务器上每个指针占用8的字节。但是我们要强调的重点是我们char类型的指针和int类型的指针占用 的字节数在同一机器架构下是一样的,也就验证了我们刚刚所言。

作为参数的指针

void f(int* p);//在调用的时候得到某个变量的地址
int i=0;
f(&i);//在函数里面可以通过这个指针访问外面的变量i

访问对应地址中的元素

*是弹幕运算符,用来访问指针所指地址上的变量
可以作为右值也可以作为左值
int k = *p;
*p = k+1;

指针的应用场景

场景一

交换两个变量的值
我们都写过交换两个变量的swap函数,但是当我们从形参传进来两个值的时候,我们能在函数内交换,但是一旦离开了函数,原本的变量根本没有变化,因而我们要传入地址进来

void swap(int *pa, int *pb){
  int temp =*pa;
  *pa = *pb;
  *pb = temp;
}

这样我们就能交换两个变量的值了

场景二

函数要同时返回多个值
一般情况我我们通过函数的return语句返回值的时候只能返回一个,但是如果我们要同时返回多个值该怎么办呢?这时候我们通过参数传入地址,然后通过指针把要返回的值带回到函数外。举个例子:我们写个函数求数组中的最大最下值。

#include<stdio.h>
void maxmin(int a[], int len, int *max, int *min){
    *max = a[0];
    *min = a[0];
    for (int i = 0; i < len; i++){
        if (*max < a[i])
            *max = a[i];
        if (*min>a[i])
            *min = a[i];
    }
}
int main(){
    int num[] = { 1, 10, 5, 8, 9, 6, 7, 25, 6, 3, 4 };
    int max;
    int min;
    maxmin(num,sizeof(num)/sizeof(int), &max, &min);
    printf("max = %d\n", max);
    printf("min = %d\n", min);
    return 0;
}
Paste_Image.png

在maxmin函数中,我们返回值类型是void,也就是不通过return返回值,但是我们确实得到了max和min,如何做到的?那就是我们穿进去两个地址,在函数内部把地址上的内容改了,所以函数结束以后,我们能得到我们想要的。我们在进一步探索一下,maxmin函数的参数列表中除了我们要传入的数组int a[], 两个指针变量int *max和int *min,还多了一个长度int len 为什么我们不在函数内部做sizeof(a)/sizeof(int) 来得到数组的长度呢?
我们来看一个例子

Paste_Image.png

为什么我们的数组才占了4个字节呢?显然,此时a并不表示数组了,那么我们传进来的到底是什么呢?4个字节刚好是一个指针所占用的字节数,没错此时的a就是一个指针。那么我们能否像操作指针一样操作a呢?我们来试一下:

Paste_Image.png

没错我们可以像操作指针一样操作a,所以a其实就是一个指针,所以我们在函数内部是不能通过sizeof(a)/sizeof(int)来求得数组的个数的,那么我们只能再传进来一个参数len。

指针最常见的错误

定义了指针变量,还没有指向任何变量就开始使用指针
当你定义了一个指针变量的时候,由于没有指向任何变量,所以它里面的内容是杂乱无章的,可能是个可以访问的地址,也可能是不可访问的地址,无论哪种都不是我们想要的。

Paste_Image.png

vs提示我们是使用了未初始化的变量,所以连编译都过不去

Paste_Image.png

我们在cpp.sh上运行了一下,通过了,能正常运行,但这不总是那么幸运,万一我们的p内的地址是0,这个特殊的地址,我们的程序就会崩掉。

Paste_Image.png

我们把p的值改为了0,程序一直得不到结果,在vs下呢

Paste_Image.png

一样的结果,因为我们的0地址是无法访问的。
一般我们用NULL来表示0地址。

指针与const

在使用指针的时候我们经常会看到const,一脸懵逼,你能正确分辨下面的几种写法么?
int i;
int *const p1=&i;
const int *p2=&i;
int const *p3=&i;
三种写法有两种意思,const在*之前,表示指针是const,也就是说指针只能指向这个变量,不能改变,所以一般声明和初始化一起。const在*之后表示不能通过该指针来改变变量的值,并不是说变量不可改变,或者指针不可改变,而是通过该指针改变该变量的值是不允许的。

强制类型转换

void* 这种类型的指针,表示某个地址,但是不明确指出所存储是数据类型。一般用在比较底层的操作中,例如动态分配内存的时候,我们只要告诉系统,请求分配多少字节的内存,并不需要告诉它用来存什么数据 ,所以malloc返回值类型为void*
必要的时候我们可以通过强制类型转换来改变指针的类型
void* p = malloc(128);
int * q = (int*) p;

malloc动态分配内存

有时候我们不知道数组的大小,要传入一个变量n到数组中,在C99之前是不允许的,这时候就要动态分配内存了
具体做法

Paste_Image.png

记住不仅仅如此,我们借了内存,还要还回去,不然,有借无还,最终内存会用光的。我们用free函数还回内存

Paste_Image.png

指针的运算

指针是地址,地址是可以运算的,有加减运算,比较运算,
那么指针加一是否是地址加一呢?
不是的,指针加一,表示指向下一个单元,如果是int*类型的指针,指针加一,则地址加4,如果是char*类型的指针,指针加一,则地址加一。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; ...
    朱森阅读 3,387评论 3 44
  • 1.语言中变量的实质 要理解C指针,我认为一定要理解C中“变量”的存储实质, 所以我就从“变量”这个东西开始讲起吧...
    金巴多阅读 1,672评论 0 9
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy阅读 9,446评论 1 51
  • 在三体世界派出的水滴不费吹灰之力地毁灭了人类的庞大舰队后,水滴终于要去执行它被交付的秘密任务。 在三体世界强大的数...
    凯恩Kane阅读 375评论 2 0
  • 01、 你有没有遇到过熊孩子? 不是调皮好动那类的,而是没礼貌、没教养、坑爹那类的。还记得那个在地铁上直接从别人手...
    镜中燃灯阅读 935评论 5 4