C语言程序设计进阶随堂

目录

指针运算

*p++

0地址

指针的类型

指针的类型转换

指针的运用

 动态内存分配

字符串操作

putchar

 getchar


指针与字符串

函数返回多个值,某些值就只能通过指针返回  return只能返回一个值

传入的参数实际上是需要保存带回的结果的变量

求数组元素个数 sizeof(a) / sizeof(a0)

a是数组名

指针应用场景二 函数返回运算的状态,结果通过指针返回

让函数返回特殊的不属于有效范围内的值来表示出错

比如-1 或 0

但是当任何数值都是有效的可能结果时,就得分开返回了

错误:使用未指向任何变量的指针变量    解引用未初始化的指针

所有的本地变量都没有默认的初始值(随机   

这可能不会出什么错,也可能会擦写数据或代码,或者导致程序崩溃

创建一个指针时,系统只分配了存储指针本身的内存,并未分配存储数据的内存。因此,在使用指针之前,必须先用已分配的地址初始化它。

double * pd;

* pd = 2.4;  //不要这样做 

未初始化的指针指向是不确定的

指针的字节是4

函数参数表里的数组实际上是指针 (所以参数表里可以写 int a[];

sizeof(a) == sizeof(int *)

(但是可以用数组的运算符[]进行运算

作为函数原型

 数组变量本身表达地址,数组名前不需要取地址符,但是数组的单元表达的是变量

[]运算符可以对数组做,也可以对指针做

p[0] <==> a[0]           //变址符嘛

*也可以对数组做

数组变量是const的指针,所以不能被赋值

即数组变量之间不能作互相赋值

int a[] <==> int * const a

(以下只适用于C99

 指针是const

指针所指是const 表示不能通过指针去修改所指的值

比如p指向i i可以被赋值,p可以指向别的值,但是不能*p = ...

 标志是const 与 * 的位置关系 (const 在 * 后则指针不可修改

int const*与int * const_冷崖的博客-CSDN博客_const int*和int*const

 传结构

a 完全等价于 &a 么?

从类型来说,不的

它们不是 同类型 的指针

什么叫 同类型 的指针?

比如 char* 与 char* 是相同的 char 类型指针

比如 double* 与 double* 是相同的 double 类型指针

那么,不同类型 的指针,就是指

比如 double* 与 char*

比如 int* 与 float*

 相同值 的指针,可以是 不同类型 的指针么?

char* p11 = a;

double*p12 = a;

int* p13 = a;

可以,编译器不禁止——可能会提醒一下——指针类型不匹配

(不过可以注意到,编译器只提醒p11,p12,不提醒p13)

如果是,替换为 同值 的&a

char* p21 = &a;

double*p22 = &a;

int* p23 = &a;

还是可以,编译器不禁止——可能会提醒一下——指针类型不匹配

(不过可以注意到,编译器提醒了p21,p22,p23)

指针加减法_nifeigea的博客-CSDN博客_指针加减

上面的测试感觉到了什么意味?

是不是说

 a 是 int* —— 即 int 类型指针

而 &a 不是 int* ?——虽然它们 值 相等

假定 a 与 &a 它们是 同类型 指针

那么 同类型 指针有什么特点呢?

比如,它们进行同样的加减法后,值 应该一样, 对吧

因为某类型指针 p 有如下的运算

    p + n == p + n * sizeof(p的类型)

意思就是

如果有 a == &a 且 a 与 &a 是同类型的指针

那么

 a + 1 == &a + 1 应该是成立的

 a + 100 == &a + 100 应该是成立的

好比有

char* ch1 = "ABCDEFG";

char* ch2 = ch1;

int* ch3 = ch1;

那么 ch1 + 1 == ch2 + 1 应该是成立的

因为

    ch1 == cha2

    ch1 + 1 == ch1 + 1 * sizeof(char)

    ch2 + 1 == ch2 + 1 * sizeof(char)

而 ch1 + 1 == ch3 + 1 就不能成立了

因为

    ch1 == ch3

    ch1 + 1 == ch1 + 1 * sizeof(char)

    ch3 + 1 == ch3 + 1 * sizeof(int)

那么

 a + 1 == &a + 1 是否成立?

 a + 100 == &a + 100 是否成立?

……

很可惜,它们都不成立                                                //代码验证

说明 sizeof它们的指针指向的数据类型 是 不同 的值

即 a 与 &a 的 指针类型 是不同的

而且

很容易发现

a + n 是以 n * sizeof(int) 字节在移动指针

&a + n 是以 n * sizeof(int) * 10 字节在移动指针

其实

回到最开始,关于数组a的定义

int a[10];

含义是:

    定义了一个 int [10] 类型的数组

    数组的名字是 a

    该数组未初始化

        int [10]类型的数组意味着

            数组的元素类型是 int,元素的数量是 10 

 a 是 数组 元素 类型 的指针 —— int* —— 它的移动单位是 sizeof(int) == 4 字节

 &a 是 数组类型 的指针 —— int* [10] —— 它的移动单位是 sizeof(int [10]) == 4 * 10字节

可以定义

int* pt1 = a;    https://没有编译警告

还可以定义

int (*pt2) [10] = &a;     //没有编译警告,[]的运算级高于*,所以需要()

此时

a + 1 == pt1 + 1

&a + 1 == pt2 + 1

指针运算

 sizeof(char) == 1

sizeof(int) == 4

 *号是单目运算符,优先级比加减乘除高,需要加括号

没  有  意  义 

因为如果是只移一个字节,则指针从这里开始指不能构成一片连续分配的空间

 十六进制小心计算

两个指针相减得到的结果表示的是有几个单元格

即 两个地址的差 / sizeof(指向的类型)

*p++

取出p所指的数据之后把p移到下一个位置去

*的优先级没有++高

常用于数组类的连续空间操作

在某些CPU上,可以直接被翻译成一条汇编指令

指针乘除无意义

数组中的单元的地址肯定是线性递增的

0地址

Windows、Linux等操作系统(多进程)基本的管理单元叫进程

双击让其运行 就叫一个进程

对于进程,操作系统会给它一个虚拟的运行空间,所有的程序在运行的时候都以为自己有从零开始的一片连续的空间

内存中有0地址(任何一个程序),但是0地址通常是个不能随便碰的地址

所以指针不应该具有0值

因此可以用0地址来表示特殊情况: 1、返回的指针是无效的    2、指针没有被真正初始化(先初始化为0)

NULL是一个预定定义符号,表示0地址

有的编译器不愿意你用0来表示0地址,有点编译器0和NULL代表不同的含义

指针的类型

无论指向什么类型,所有指针的大小都是一样的,因为都是地址。

但是指向不同类型的指针是不能直接互相赋值

这是为了避免用错指针

 int *q = 0; 一个*q要四个字节

指针的类型转换

void* 表示不知道指向什么东西的指针

不确定它要指向什么,也不关心  表达有一块内存地址,往往用于底层程序,直接去访问某个内存地址或其代表的外部设备。

计算时与char*相同(但不相通)

指针也可以转换类型

int *p = &i ; void *q = (void*)p;

注意:并不会改变p所指的变量的类型

指针的运用

  • 需要传入较大的数据时用作参数
  • 传入数组后对数组做操作
  • 函数返回不止一个结果
  • 需要用函数来修改不止一个变量

 动态内存分配

C99可以用变量做数组定义的大小

int *a = (int*)malloc(n*sizeof(int));

malloc() 在 stdlib.h 头文件中

malloc要的参数不是单元,而是空间,以字节为单位

注意malloc返回的是void*  记得类型转换

未初始化的指针只是不能解引用,还是可以赋值的

int *a = (int*) malloc(number*sizeof(int));

如果申请失败则返回0,或者叫NULL

while((p=malloc(100*1024*1024))
//用p得到的值作while的条件

 p得到的地址如果不是0,则循环继续

free()只能还申请来的空间的首地址

报错:"pointer being freed was not allocated"

free(NULL);  //√
free(0);   //√
free(1);   //×

常见问题:

  • 申请了没free ——>  长时间运行内存逐渐下降
  • free过了再free   程序会崩溃
  • 地址变过了,直接去free(只能还首地址

malloc得到的空间是连续的吗?

 

 

 内存不是无限的,所以malloc最终会失败,返回NULL指针,NULL的值为0,所以最后是写入地址0退出

字符串操作

putchar

int putchar(int c);

向标准输出写一个字符;

返回写了几个字符,EOF(-1)表示写失败

EOF(-1)是定义的一个宏,值为-1

 getchar

int getchar(void)

从标准输入读入一个字符

返回类型是int是为了返回EOF(-1)

Windows Ctrl-Z

Unix Ctrl-D

 

 没有输出EOF,说明只是强制让程序结束

 得到了EOF的输出

 在输入回车之前,这些字都还没有被送到程序,都还停留在shell处,直到你按下回车

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值