第三章

1.作用域

1.代码作用域 , {}
2.文件作用域,头文件
3.原型作用域,函数传参
4.函数作用域,goto

2.链接属性

  1. external,外部链接,外部源文件也可以访问。

staic修饰完,external变为internal

  1. internal,内部链接,本源文件内有效
  2. none

3.存储类型

1.普通内存
2.运行时堆栈
3.硬件寄存器

1.代码外声明的变量 -> 静态存储。生命周期:程序一直运行就一直存在,而不是每次代码块开始时创建,代码执行完销毁
2.static关键字可以使类型从自动(生命周期是函数体内)变成静态(退出该函数后,尽管该变量还继续存在,但不能使用它)。自动和静态的作用域相同。
3.register,自动变量的声明,存储再硬件寄存器,特点:访问效率高,所以可以吧程序经常访问的指针存储再寄存器中

第六章 指针

内存和地址

通过指针访问指向的地址过程叫间接访问或解引用

左值

int a; int *d = &a;都是左值
*d = 10 - *d; 10-*d是右值 *d是左值

指针未初始化

int *a; *a = 12;
未初始化的非法指针,会造成"段违例"或"内存错误"访问未分配给程序的内存位置

NULL指针

可以表示某个特定指针目前未指向任何东西。一般在解引用之前,首先要确保它是NULL指针

间接访问

*&a = 25; <⇒ a = 25;
&会产生a的地址,*操作符访问其地址

指针常量

(int)100 = 25;
指值100从整形转变未『指向整形的指针』

指针的指针

int **c;
int a = 12;
int *b = &a;
int **c = &b;
*c访问c指向的位置,是变量b
**c访问的是【*c】所指向的地址,也就是变量a
间接访问:
a ==> 12
b ==> &a
*b ==> a, 12
c ==> &b
*c ==> b, &a
**c ==> 12, *b, a

指针运算

int *p;
p + 1 +1会加上p类型字节的大小

总结

  1. 一个值应该只有一种意思
  2. 如果指针指向任何有意义东西,那么设置未NULL

第八章 数组

8.1 一维数组

  • 数组具有确定数量的元素,而指针只是一个标量值
  • 当数组在表达式中使用时,编译器才会为它产生一个指针常量
  • 数组名是一个指针常量(除了在sizeof操作符和单目操作符&场合下)

例子:

int a[10];
int b[10];
int *c;
c = &a[0];
  • c = &a[0]是一个指向数组第一个元素的指针, 等价于c = a;
  • b = a 是非法的,不能使用一个赋值符把一个数组所有元素复制到另外一个数组,必须使用一个循环复制每一个元素
  • a = c,非法的,因为a的值是个常量,不能被修改
下标引用
*(b + 3)
  • b是指向整形的指针
  • 加法运算,指向数组第一个元素向后移3个整数长度的位置
  • 间接引用访问这个新位置,或者取得那里的值(右值),或者把一个新值存储于该处(左值)。
array[subscript] < == > *(array + (subscript))
  • 除优先级外,下标引用和间接访问完全相同

例子:

int array[10];
int *ap = array + 2;
  • ap ==> array + 2 ⇒ &array[2]
  • *ap ==> *(array + 2) ==> array[2]
  • ap[0] ==> *(array + 2) ⇒ array[2]
  • ap + 6 ⇒ &array[8] ==> array + 8
  • *ap + 6 ⇒ array[2] + 6(间接访问的优先级高)
  • *(ap + 6) ⇒ array[8]
  • ap[6] ⇒ array[8]
  • &ap 合法,但无法预测编译器会把ap放在array的什么位置
  • ap[-1] ⇒ array[1]

指针和下标

  • 下标更容易理解
  • 不要为了效率上的细微差别而牺牲可读性
  • 当根据某个固定数目的增量在一个数组中移动时,使用指针变量比使用下标产生效率更高

指针和数组

int a[5];
int *b;
  • 表达式*a是合法的,b是非法的(因为b是一个随机值)
  • b++可以编译成功,a++不行(a的值是个常量)
作为函数参数的数组名
  • 数组名就是一个指向数组第一个元素的指针
  • 传递给函数的是一份该指针的拷贝
  • 所有传递给函数的参数都是通过传值方式进行的,但数组名参数是通过地址传递的,下标引用实际执行的就是间接访问
声明数组参数
int strlen(char *string);
int strlen(char string[]);
  • 数组形参可以于任何长度的数组匹配 —— 它实际传递的只是指向数组第一个元素的指针
  • 另一方面,这种实现方法使函数无法知道数组的长度,如果函数需要知道数组的长度,他必须作为一个显示的参数传递给函数
自动计算数组长度

int vector[] = {1,2,3,4,5}

  • 如果未声明数组长度,编译器会自动设置长度。
字符数组初始化
// 字符数组的元素
char message[] = {'h', 'e', 'l', 'l', 'o'};
// 一个真正的字符串常量
char message[] = "hello";

8.2 多维数组

int c[2][4];
int d[3][6][10];
  • 数组d可以看成3排,6行10列的整形三维数组
指向数组的指针
//合法,vp指针指向 整形的指针
int vector[10], *vp = vector;// 非法m, m是指向整形数组的指针
int m[3][10], *mp = matrix;
// 正确应该这样
int (*p)[10];
作为参数传递的多维数组
void func1(int (*mat)[10]);
void func2(int mat[][10]);
  • 第一维的长度并不需要,因为计算下标值时用不到它,但需要知道第二个及以后各维长度

总结

  • 可读性几乎总大于程序运行的效率
  • 函数的指针形参都应该声明为const
  • 有些环境,register关键字提高程序的运行时效率
  • 多维数组用花括号,提高程序可读性

第九章 字符串、字符和字节

不受限的字符串函数

复制字符串
char *strcpy(char *dst, char const *src);
  • 注意:src长度如果大于dst长度会出core(abort)
连接字符串
char *strcat(char *dst, char const *src);
字符串比较
int strcmp(char const *s1, char const *s2);

长度受限的字符串函数

char *strncpy(char *dst, char const *src, size_t len);
char *strncat(char *dst, char const *src, size_t len);
char strncmp(char const *s1, char const *s2, size_t len);

字符串查找基础

查找一个字符
char *strchr(char const *str, int ch);
chra *strrchr(char const *str, int ch);
查找任意几个字符
char *strpbrk(char const *str, char const *group);
查找一个子串
char *strstr(char const *s1, char const *s2);
查找一个字符串的前缀
size_t strspn(char const *str, char const *group);
size_t strcspn(chat const *str, char const *group);
内存操作
void *memcpy(void *dst, void const *src, size_t length);
void *memmove(void *dst, void const *src, size_t length);
void *memcmp(void const *a, void const *b, size_t length);
void *memchr(void const *a, int ch, size_t length);
void *memset(void *a, int ch, size_t length);

总结

  • 应该在使用有符号数的表达式中使用strlen函数
  • 在表达式中混用有符号和无符号数
  • 使用strcpy函数把一个长字符串复制到一个较短的数组中,导致数组溢出
  • 使用strcat函数把一个字符串添加到一个数组中,导致数组溢出
  • 把strcmp函数的返回值当做bool判断
  • 把strcmp函数的返回值与1和-1进行比较
  • 使用并非以NUL字节结尾的字符序列
  • 使用strncpy函数和strxxx族函数混用
  • 忘记strtok函数将会修改它所处理的字符串
  • strtok函数是不可再入的

第十章 结构和联合

直接访问

点操作符(.)

间接访问

箭头操作符(->)

结构体的子引用

1.错误用法,会永无止境递归下去

struct test1 {int a;stuct test1 b;int c;
};

2.正确用法,现在的b是一个指针而不是一个结构

struct test2 {int a;stuct test2 *b;int c;
};

3.错误示例,类型名知道声明的末尾才定义

typedef struct  {int a;stuct test3 *b;int c;
} test3;
不完整的声明

需求:声明一些相互之前存在依赖的结构,其中一个结构包含了另外一个结构的一个或多个成员

struct B;
struct A {struct B *partner;
};struct B {struct A *partner;
};

结构指针和成员

typedef struct {int a;short b[2]
} EX2;
typedef struct EX {int a;char b[3];EX2 c;struct EX *d;
} EX;EX x = {10, "HI", {1, {-1, 23},}, 0}
EX *px = &x;

访问结构成员

// ->优先级大于&,所以不需要使用括号
pi = &px->x;

px->b[1];

px->c.a

px->d->c.b[1]

作为函数参数的结构

通常情况下传递指针比较高效

typedef struct  {char p[];int quantity;float unit_price;float total;
}Transation;
void test(register Transation *trans) {trans->total = trans->quantity *trans->unit_price;
}
// 调用
test(&current_trans);
联合

联合的所有
54w1 1 成员引用的是内存中的相同位置,如果想在不同时刻把不同的东西存储再同一个位置,就用联合

union {float f;int i;
} fi;

第十一章 动态内存分配

malloc和free

malloc函数从内存池中提取一块合适的内存,返回一个指向这块内存的指针,但是不会初始化。分配失败返回NULL指针
calloc会初始化
free函数会把内存归还给内存池

void *malloc(size_t size);
void free(void *pointer);

calloc和realloc

void *calloc(size_t num_elements, size_t elements_size);
void  realloc(void *ptr, size_t new_size);
  • calloc参数包括所需元素的数量和每个元素的字节数,根据这些值,他能计算出总共所需分配的内存
  • realloc函数 可以、扩大或缩小已经分配的内存块大小。如果扩大,在后面增加新的内存块。如果缩小,就把内存尾部的内存拿掉,剩余部分内存的原先内存保留。

常见的动态内存错误

  1. NULL指针的解引用
  2. 对分配内存进行操作时越界
  3. 释放并非动态分配的内存
  4. 试图释放一块动态分配内存的一部分
  5. 内存被释放后继续使用

第十三章 高级指针话题

指向指针的指针

int i;
int *p
int **ppi;1. printf("%d\n", ppi);  // 自动变量没有被初始化,打印一个随机值。如果是静态变量结果是0
2. printf("%d\n", &ppi);  // 把ppi的地址,以10进制的形式打印
3. *ppi = 5;  // 结果不能预测,因为ppi没有被初始化,所有也不应该执行间接访问ppi = &pi;  // 把ppi初始化为指向p的变量
*ppi = &i; // 把pi初始化为指向变量ii = 'a';
*pi = 'a';
**ppi = 'a'

为什么要对指针间接访问:在某些函数,变量名在函数的作用域内部是未知的,函数拥有的只是一个指向需要修改的内存位置的指针,所以要通过对指针间接访问来修改变量

高级声明

int f;  //整形变量
int *f; //  指向整形的指针int f(); // f是个函数,返回值是一个整数
int *f();   //  f是个函数,返回值是一个指向整形的指针int (*f)(); // f是一个函数指针,指向的函数返回一个整型值
int *(*f)(); // f是一个函数指针,指向的函数返回一个整形指针int *f[];  // f是一个数组,他的元素类型指向整形的指针
int f()[];  //f是一个函数,返回标量值,不能返回数组

函数指针,回调函数

Node *search_list(Node *node, int const value) {while (node != NULL) {if (node->value == value) break;node = node->link;}return node;
}

这个函数只适用值的整数链表,如果在一个字符串链表查询就需要另外编写函数。
解决方案就是函数指针,把一个指向这个函数的指针作为参数传递给查找函数,然后查找函数调用这个函数来执行值的比较。
回调函数:用户把一个函数指针作为参数传递给其他函数,后者将『回调』用户函数

【读书笔记】c和指针相关推荐

  1. C++读书笔记之this指针的用法

    C++ this指针的用法 this指针的含义及其用法: 1.  this指针是一个隐含于每一个成员函数中的特殊指针.     它指向正在被该成员函数操作的那个对象. 2.  当对一个对象调用成员函数 ...

  2. c语言指针读书笔记,《C与指针》读书笔记一

    我平时不太看书.倒不是我没有读书的习惯.而是如今的社会知识传播的方式太多.书已经不是唯一知识的载体.至于"书是人类知识的阶梯"这句名言的时代已经过去了.每天各种微信公众号推介的文章 ...

  3. 【读书笔记】【程序员的自我修养 -- 链接、装载与库(三)】函数调用与栈(this指针、返回值传递临时对象构建栈、运行库与多线程、_main函数、系统调用与中断向量表、Win32、可变参数、大小端

    文章目录 前言 介绍 内存 内存布局 栈与调用惯例 堆与内存管理 运行库 入口函数和程序初始化 C/C++运行库 运行库与多线程 C++全局构造与析构 fread 实现 系统调用与API 系统调用介绍 ...

  4. Android智能指针——读书笔记

    目录结构 目录结构 参考资料 概述 背景知识 GC经典问题 轻量级指针 实现原理分析 构造函数 析构函数 应用实例分析 强指针和弱指针 强指针的实现原理分析 增加对象的弱引用计数 增加对象的强引用计数 ...

  5. c语言指针读书笔记,《C与指针》读书笔记九

    原标题:<C与指针>读书笔记九 指针之所以在C语言中占据很大分量,是因为指针有很大的灵活性.指针以结构体结合确实为程序的编写提供了一把锋利无比的宝剑.在有些资料上介绍结构体是多种数据集合, ...

  6. 《征服C指针》读书笔记

    <征服C指针>读书笔记 评价 对于学习过C语言和C++的,<征服C指针>推荐一读,能明白一些指针深层次的一些知识点,对于一些知识有一种顿悟的感觉.如果C语言不熟或者是初学者就没 ...

  7. 读书笔记:编写高质量代码--web前端开发修炼之道(二:5章)

    读书笔记:编写高质量代码--web前端开发修炼之道 这本书看得断断续续,不连贯,笔记也是有些马虎了,想了解这本书内容的童鞋可以借鉴我的这篇笔记,希望对大家有帮助. 笔记有点长,所以分为一,二两个部分: ...

  8. 《JavaScript面向对象精要》读书笔记

    JavaScript(ES5)的面向对象精要 标签: JavaScript 面向对象 读书笔记 2016年1月16日-17日两天看完了<JavaScript面向对象精要>(参加异步社区的活 ...

  9. C++ Primer 第三版 读书笔记

    1.如果一个变量是在全局定义的,系统会保证给它提供初始化值0.如果变量是局部定义的,或是通过new表达式动态分配的,则系统不会向它提供初始值0 2.一般定义指针最好写成:" string * ...

  10. 《编程之美》读书笔记19: 3.9 重建二叉树

    <编程之美>读书笔记19: 3.9 重建二叉树 对根节点a以及先序遍历次序P和中序遍历次序I,查找a在I中的位置,将I分为两部分,左边部分的元素都在a的左子树上,右边的元素都在a的右子树上 ...

最新文章

  1. Gridview改变单元格颜色
  2. Android系统JNI的实现方式
  3. LeetCode 258. Add Digits
  4. 水凝胶 静电纺丝_离子液体/水和静电纺丝条件对聚偏氟乙烯纳米纤维晶体结构的影响...
  5. 雨林木风SP3YN9.9 装机版09年09月更新(终结版)
  6. xpwifi热点设置android,笔记本xp系统wifi热点设置教程(图文)
  7. 前端的3D(css3版本)--淘宝造物节3D创景的制作
  8. oracle教程课件,Oracle入门教程(PPT课件)
  9. 窗函数(window function)
  10. 车载定位与轨迹服务系统
  11. 2015华为暑期实习面试全过程
  12. 百信计算机管理员登录账号密码,192.168.1.1登陆入口管理员密码是多少?
  13. Github上Stars最多的53个深度学习项目
  14. 嵌入式学习——串口通信小试
  15. CVPR 2020 | 跟郎朗媳妇有得一拼的AI,只看弹琴动作,完美复现原声
  16. 安防视频推流组件EasyRTSPServer对接海康NVR视频正常音频不能正常播放问题解析
  17. 踩坑 Mac Xcode 与 conio.h windows.h 库(如何解决错误代码:‘conio.h‘ file not found ‘windows.h‘ file not found)
  18. weui 加载提示_WEUI滚动加载
  19. SQL交叉表查询 如何实现
  20. Fortran编程——文件输入输出

热门文章

  1. 复赛了?“移动云杯”复赛模式开启!
  2. 大牛证券公司点评主板指数目前属于蓝筹
  3. redis 启动命令 (windos)
  4. Win10系统 默认以管理员权限运行所有程序
  5. 苹果微信浏览器html缓存图片吗,h5清理微信浏览器网页缓存
  6. 如何在 Mac 和虚拟机上安装 macOS Big Sur、Monterey 和 Ventura
  7. 西夏文可用电脑录入了【ZZ】
  8. hydra的基本使用
  9. 全国各地土特产一览表(以后好问朋友要礼物了)
  10. laraveladmin省市区三级联动