指针基础简述

6.1内存和地址

单个字节包含了存储一个字符所需要的位数,每个字节包含8位。
存储无符号值的范围:0 ~ 28-1(255)
存储有符号值的范围:-27(-128) ~ 27-1(127)

由四个字节存储的字,每个字包含4*8=32位
存储无符号值的范围:0 ~ 232-1(4294967295)
存储有符号值的范围:-231(-2147483648) ~ 231-1(2147483648)

高级语言通过名字而非地址来访问内存的位置;硬件仍然通过地址访问内存位置。

6.2 值、类型、指针变量与间接访问

不能简单地通过检查一个值的位来判断它的类型。
变量被声明为指针并不会改变这些表达式的求值方式,一个变量的值就是分配给这个变量的内存位置所存储的数值。
通过一个指针访问它所指向的地址的过程称为间接访问解引用指针(*)
间接访问操作只能作用于指针类型表达式。

因为对一个NULL指针使用解引用操作是非法的。因此在对指针进行解引用之前,首先确保它并非NULL指针。
为测试一个指针变量是否为NULL,可将它与零值进行比较。

间接访问操作符所需要的操作数是右值,但此操作符所产生的结果是左值。
指针变量可因其是变量而作为左值使用。对指针变量进行间接访问表示我们应该访问指针所指向的位置。

int a;
int *d=&a;//定义指针变量d并指向a*d=10-*d;
//右侧对d所指向位置所存储的值(a的值)进行操作再将其赋给左侧d所指向的位置
d=10-*d;
//非法,表示把一个整型数量(10-d*)存储于一个指针变量(d)中。*&a=25;//把值25赋值给变量a。&操作符产生变量a的地址(指针常量)
//*操作符访问其操作数(a的地址)所表示的地址p=&a;//把a的地址赋给指针变量p,指针变量p的值是变量a的地址,p指向a
*p=1;//将整数1赋给指针变量p当前所指向的变量,即a=1;

&—— 取地址运算符。&a是变量a的地址。
*—— 指针运算符(间接访问运算符),*p代表指针变量p指向的对象。

若偶尔需通过地址访问内存中某个的特定位置时(即用整型字面值的形式,左值为指针常量,右值为整型常量),可通过强制类型转换转换成适当的类型。

6.3 指针表达式

前缀自增++操作符优先级高于*,结合性都是从右向左。

表达式*cp++可作为左值和右值存在。(先执行++)
1.++操作符产生cp的一份拷贝
2.然后++操作符增加cp的值
3.最后,在cp的拷贝上执行间接访问操作。
表达式++*cp右值存在,左值非法。(先执行间接访问操作)
1.首先执行间接访问操作
2.cp所指向位置的值增加1
3.表达式的结果是这个增值后的值的一份拷贝
后缀自增(减)的优先级高于前缀自增(减)。
while((string=*strings++)!=NULL)
1.它把strings当前所指向的指针复制到变量string中
2.它增加strings的值,使它指向下一个值
3.它测试string是否为NULL

插播assert知识点:

断言assert是一个宏,该宏在<assert.h>中,,当使用assert时候,给他个参数,即一个判读为真的表达式。预处理器产生测试该断言的代码,如果断言不为真,则发出一个错误信息告诉断言是什么以及它失败一会,程序会终止。
我们一般可以用在判断某件操作是否成功上。
程序一般分为Debug版本和Release版本,Debug版本用于内部调试,Release版本发行给用户使用。
断言assert是仅在Debug版本起作用的宏,它用于检查“不应该”发生的情况。
assert不是一个仓促拼凑起来的宏,为了不在程序的Debug版本和Release版本引起差别,assert不应该产生任何副作用。所以assert不是函数,而是宏。程序员可以把assert看成一个在任何系统状态下都可以安全使用的无害测试手段。
以下是使用断言的几个原则:
1)使用断言捕捉不应该发生的非法情况。不要混淆非法情况与错误情况之间的区别,后者是必然存在的并且是一定要作出处理的。
2)使用断言对函数的参数进行确认。

在对指针执行间接访问前,指针必须进行初始化:使它指向现有的内存或给它分配动态内存。

编程练习

1.

请编写一个程序,它在一个字符串中进行搜索,查找所有在一个给定字符集合中出现的字符。这个函数的原型应该如下:

char *find_char(char const *source,char const *chars);

它的基本想法是查找source字符串中匹配chars字符串中任何字符的第1个字符,函数然后返回一个指向source中第1个匹配所找到的位置的指针。如果source中的所有字符均不匹配chars中的任何字符,函数就返回一个NULL指针。如果任何一个参数为NULL,或任何一个参数所指向的字符串为空,函数也返回一个NULL指针。
举个例子,假定source指向ABCDEF。如果chars指向XYZ、JURY或QQQQ,函数就返回一个NULL指针。如果chars指向XRCQEF,函数就返回一个指向source中C字符的指针。参数所指向的字符串是绝不会被修改的。
碰巧,C函数库中存在一个名为strpbrk的函数,它的功能几乎和这个你要编写的函数一模一样。但这个程序的目的是让你自己练习操纵指针,所以:
a.你不应该使用任何用于操纵字符串的库函数(如strcpy,strcmp,index等)。
b.函数中的任何地方都不应该使用下标引用。

分析: 这个函数是一个以指向两个字符型常量的指针变量作为形参且返回值为指针的函数。这个题目中的“函数返回一个指向source中第一个匹配所找到位置的指针”,这一句话也值得好好思考一下。题目中提到的strpbrk,是在源字符串(s1)中找出最先含有搜索字符串(s2)中任一字符的位置并返回,若找不到则返回空指针。头文件为#include <string.h>。

程序如下:

//方法一
#include <stdio.h>char *find_char(char const *source,char const *chars);
//这里是指针变量作为函数参数,即将一个变量的地址传送到另一个函数中
//用字符指针变量作形参和实参且函数返回指针值
int main()
{char const  *s="ABCDEF"; char const  *c="XRCQEF";char *t;printf("source=%s\nchars=%s\n",s,c);t=find_char(s,c);printf("Matched return value:%s",t);return 0;
}char *find_char(char const *source,char const *chars)
{char *p;//设p为指向source中第一个匹配所找到位置的指针 if(source != NULL && chars != NULL){for(;*source != '\0';source++){for(p = chars; *p != '\0';p++)if(*p == *source)return p;}}return NULL;
}//方法二
#include<stdio.h>char *find_char(char const *source,char const *chars);
int main(){char m[]="ABCDEF";char n[]="XRCQEF";char *t;char const *s=m; //使指针变量s指向m数组首元素char const *c=n; //使指针变量c指向n数组首元素printf("source=%s\nchars=%s\n",s,c);t=find_char(s,c);printf("Matched return value:%s",t);return 0;
} char *find_char(char const *source,char const *chars)
{char *ps = source;char *pc = NULL;if(source == NULL || chars == NULL)return NULL;while(*ps != '\0'){pc = chars;while(*pc != '\0'){if(*pc == *ps)return pc;pc++;}ps++;}return NULL;
}//方法三
char *find_char(char const *source,char const *chars)
{int size = 0;if(source != NULL && chars != NULL){for(;*chars++ != '\0';size++);for(;*source != '\0';source++){for(chars-=size; *chars != '\0';chars++)if(*chars == *source)return chars;}}return NULL;
}

运行结果:

注: 在运行时,纠结过返回的指针所指的究竟是source中还是chars中的字符串首地址,最后反复读题,根据题上所言的“指向source中的指针”可见,返回的指针不在source中,而应该是指向source中的,所以最后返回的指针所指的应该是chars中的字符串首地址。

虽然美名其曰是重新温习,但实际清楚的知道自己是来填坑的。之前有多浪,现在需要填的坑就有多深,尤其是在进行指针这一板块的内容时,深切体会到了大一的时候C语言老师语重心长提醒我们关于指针的知识点一定要重复多遍才能真正掌握的良苦用心。
关于指针的知识点,个人感觉,谭浩强的《C程序设计》中的讲解更为详细些,细节方面适合我这种小白阅读;而在《C和指针》中,只简单看完相关知识点,不参考其他的书籍,则在直接编程练习的过程中,做到一帆风顺是不容易的。
综上,这一章节的编程练习题,两本书混合食用效果更佳~

现在看着日历仿若是在看病危通知书
暑假自己定的计划终究也为证明人类的本质作了贡献
还有两天……(Death smiles)
好多人都说生活的迷人之处在于阴差阳错
可我不,我偏就是想要如愿以偿

C与指针——指针(一)相关推荐

  1. 指针||指针和数组||指针和函数||指针、数组、函数 案例描述:封装一个函数,利用冒泡排序,实现对整型数组的升序排序

    指针 指针的基本概念 指针的作用: 可以通过指针间接访问内存 内存编号是从0开始记录的,一般用十六进制数字表示 可以利用指针变量保存地址 指针变量的定义和使用 指针变量定义语法: 数据类型 * 变量名 ...

  2. 指针数组 数组指针 函数指针 指针函数

    目录 数组指针 指针数组 函数指针 指针函数 数组指针 数组指针的本质: 它是一个指针,指向的是一个数组 数组指针定义: int (*p)[n]; ()优先级高,首先说明p是一个指针,指向一个整型的一 ...

  3. C_C++指针指针应用详解

    前言:复杂类型说明 要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理解一个复杂类型,要理解复杂类型其实很简单,一个类型里会出现很多运算符,他们也像普通的表达式一样,有优先级,其 ...

  4. 「C语言」指针数组 数组指针 指针函数 函数指针

    相信很多人和我一样,有着这样的恐惧,那就是这四个玩意怎么也分不清,这都是啥啥啥啥呢?今天我们来具体分析一下.其实要具体了解这四个概念,只需要了解符号优先级,并关注最后两字,你就成功了一半. 符号优先级 ...

  5. 【C基础】指针/指针运算/二级指针/函数指针

    指针定义: 指针是一种数据类型,使用它可以用来定义指针变量,指针变量中存储的其实是整数,这种整数代表了内存的编号. 指针的使用: 1.函数之间相独立,但有些时候需要共享变量.传参是值传递全局变量容易命 ...

  6. C ++ 指针 | 指针的详细概念和使用_1

    目录 指针 指针取值 指针 指针是存储其他变量地址的变量,内存地址可以用C ++访问. int a = 54; 54 是变量的值,换句话说,它是存储在称为 "a" 的变量保留的位置 ...

  7. 面试准备每日五题:C++(六)——CC++、staticconstextern、sizeof strlen、指针引用、数组指针指针数组函数指针

    文章目录 一.C和C++的区别是什么? 二.关键字static.const.extern作用 三.sizeof和strlen的区别 四.指针和引用的区别 五 .指针数组.数组指针.函数指针 一.C和C ...

  8. c/c++教程 - 1.9 指针 空指针 野指针 const修饰指针 指针常量 常量指针 指针和数组 指针和函数

    十一.指针 (1)指针的定义和使用 指针的作用:可以通过指针间接访问内存. 参考视频:https://www.bilibili.com/video/BV1et411b73Z?from=search&a ...

  9. C++面试题-指针-指针数组与数组指针

    C++面试题-指针-指针数组与数组指针 问:int (*p)[n]与int *p[n]的区别? 答: int (*p)[n]是数组指针,指向某n个元素所组成的整块的数组,返回值是整型指针类型的. in ...

  10. C++面试题-指针-指针与指针的引用

    C++面试题-指针-指针与指针的引用 下面代码编译运行之后是否正常运行? void swap(char *&a, char *&b) {    char temp; temp = *a ...

最新文章

  1. 用计算机画函数图像教案,信息技术应用 用计算机画函数图象教案1
  2. 用FDISK进行硬盘分区
  3. module ‘brotli‘ has no attribute ‘error
  4. C++中变量使用前必须初始化,否则报错~
  5. 使用DbVisualizer连接和管理金仓数据库
  6. Echarts的简单使用
  7. sysbench测试mysql性能(TPS、QPS、IOPS)(重要)
  8. php设计模式的六大原则(六):迪米特法则
  9. TraceView(profile) and Systrace
  10. 计算机考试没考好的检讨书,考试没考好检讨书4篇
  11. UE4中FString转UTF8及UTF8转FString
  12. mdadm管理raid
  13. spring boot高性能实现二维码扫码登录(下)——订阅与发布机制版
  14. 手把手教做无盘服务器,手把手教你做锐起无盘(完整).doc
  15. ActiveReport报表模板库新增21张报表模板,加入报表导出功能!
  16. 深圳市商务局2022年度中央资金(跨境电子商务企业市场开拓扶持事项)申报指南
  17. 高精度绝对角度传感器应用高速度角度监测
  18. Visio 安装暴雷记录
  19. 漫画:国内都有哪些程序员大牛?
  20. UFT12无限期试用

热门文章

  1. 基于Java JAAS表单的身份验证
  2. 哥斯拉Godzilla shell管理工具
  3. 读《About Face 4 交互设计精髓》22
  4. Python 微信自动化工具开发系列03_自动向微信好友发送信息和文件(2022年10月可用)
  5. 修改Eclipse字体以及背景颜色
  6. 绘制电气电路中的电阻——Visio制图总结【电控类】(二)
  7. JDBC——Java连接关系型数据库
  8. java常见面试考点(九):SSM面试题
  9. matlab爱心函数代码画图
  10. [Ubuntu]安装微信/QQ/TIM的简便方法