Uderstanding and using Pointers 读书笔记
如何阅读指针?
从右向左读。
比如 const int *pci;

虚拟内存和虚拟内存地址是什么?
一个应用程序,在虚拟内存地址里也许是连续的,但是在物理内存里也许是分隔开来的。
虚拟内存和物理内存的映射一般是操作系统主导完成。
程序一般返回的内存地址都是虚拟内存地址。
如何手动 实现 null ?
在许多库里面,NULL 被定义为下面这样的宏
#define NULL ((void *)0)
值为 NULL 的指针不能做什么事情?
不能进行解码,一旦进行解码,就会出现程序终止,因为这个指针实际上并没有含有一个有效的地址。
c 程序编译后,有多少种类型的内存?
Static/Global
当程序运行的时候,这两种类型的变量就一直存在,直至程序终止。
这两个变量的区别是,Global 类型的变量可以被全局访问,而 Static 的变量受函数的范围约束。
Automatic
这种类型的变量在函数里面声明,并且只有当函数被调用的时候才会创建。
他的范围受限于函数,他的生命周期也只有在函数运行的那段时间。
Dynamic
这回总类型的变量,他的内存是从堆里面分配来的,这个变量会一直存在,直到他被声明释放,才会消失。
他的范围受限于指针,或者说,是指针指向的那个内存地址。
总结下

大部分系统下,数据类型的大小是多少?
不同系统下,同一种数据类型的大小可能不同。

%p 的意思是什么?
他的意思是将指针给解析出来,所以你直接传递变量给他去不行的,你要传递地址,也就是指针。
const int 和 int const 的区别
变量类型和 const 关键字的位置顺序并没有什么影响。
下面两个声明都是等同的。
但是 const 在 * 的前后会有影响。
const int *pci;
int const *pci;
const int *p 是怎么回事?
const int *p 是能够使用那些指向 const int 或者 int 类型的指针来赋值的,但是不能改变指针指向的数值,也就是指针解码后的数据是不能够改变的。
int *const p 是啥意思?
这个的意思是, p 这个指针,指向了 int 类型的变量,但是 p 本身已经被声明为了 const 类型,他是不能够改变的。
也就是 p 不能再被赋予其他地址了,但是 p 解码后的数据是能够改变的。
const int * const p 是怎么回事?
这意味着你的指针是 const 的,你的指针指向的类型也是 const 的,所以你无法修改指针的值,也无法修改解码指针后的数据。
const int * const * p 是什么意思?
简单来说,就是一个指针,指向了 「const int * const 类型的指针」。
数组长度是在什么时候确定的?
在程序运行的时候,而不是在编译的时候。
然后,一旦数组被编译创建了,就不能够再改变他的大小了。
动态内存分配函数有几种?

malloc 的形参有需要注意的?
函数原型
void* malloc(size_t);
关于他的形参,有几点需要注意的。
如果你给这个形参传入了负数,那么有的系统会直接报错,有的系统则会返回一个 NULL 值。
如果你给形参赋值 0 ,那么他也许会返回 NULL 值,或者他会返回一个指针指向一个 0 bytes 的内存区域。
如果,你给形参赋值 NULL,则系统会警告,然后返回一个指向 0 bytes 的内存区域的指针。
使用 malloc 的最佳实践是什么?
由于 malloc 也许会返回 NULL ,所以需要在使用 malloc 返回的指针之前,检查一下他返回的值是不是 NULL
int *pi = (int*) malloc(sizeof(int));
if(pi != NULL)
{
// Pointer should be good
}else {
// Bad pointer
}
怎么使用 malloc ?
在编译器的角度来看,= 符号有两种状态,一种是初始化,一种则是赋值,这是不同的两种状态。
错误
static int *pi = malloc(sizeof(int));
正确
static int *pi;
pi = malloc(sizeof(int));
清理内存是怎么做到的?
只要将内存全部设置成二进制的 0 就行了。
calloc 函数的原型是怎样?
calloc 函数会同时分配和清理内存,他的函数原型是这样的。
void *calloc(size_t numElements, size_t elementSize);
什么时候用 calloc ?
当你的内存需要清空的时候,使用 calloc
当某个指向一块内存区域的指针被释放后,这个指针指向什么?
他被释放后,实际上还是指向原本指向的地方,只不过不再能被调用。
dangling pointer 是什么?有什么危害?
你释放了一个指针,然而这个指针没有被赋值为 null ,那么这个指针就是 dangling pointer ,因为他还是指向着之前指向的那块内存区域。
dangling pointer 的危害是:
1、你不能预测这个内存区域是否还会被进行访问。
2、如果这个内存区域不能被访问,而你访问了,则会发声 segment fault
3、隐藏的安全风险
automatic variables 的其他名字是什么?
他也叫做 local variables
被分配到 stack 上。
真正释放指针的最佳实践是什么?
在释放指针后,将指针赋值为 NULL
使用 void 类型有什么需要注意的?
使用 void 类型的形参,可以接受任何类型的变量。
但是如果你没有显示将这个变量强制转换成了 void 类型,那么这个编译器是会提示你警告的。
你只要将这个变量强制转换成了 void 类型就行了。
函数指针和返回指针的函数,别搞混了
函数指针,是指向函数的指针。
而返回指针的函数,只是返回指针。
如何将函数指针简化?
typedef int (*funcptr)(int);
...
funcptr fptr2;
fptr2 = square;
printf("%d squared is %d\n",n, fptr2(n));
上面的 typedef 语句,让 funcptr 这个函数变成了一种类型。
返回一个指针,这个指针指向 int 类型
不要随便对函数指针进行强制类型转换
这种活动一般来说都不能保证每次都能成功。
指针和数组名的区别是什么?
指针可以赋值其他地址,而数组名不行。
如何为函数设定没有固定长度的数组?
使用数组标记法
就是通过一个函数的形参 arr[] 来达到目的的。
void displayArray(int arr[], int size)
{
for (int i = 0; i < size; i++)
{
printf("%d\n", arr[i]);
}
}
int vector[5] = {1, 2, 3, 4, 5};
displayArray(vector, 5);
指针标记法
void displayArray(int* arr, int size)
{
for (int i = 0; i < size; i++)
{
printf("%d\n", arr[i]);
}
}
如何为函数传递二维数组?
你可以使用下面的两种方法来传递二维数组
void display2DArray(int arr[][5], int rows){}
或者是
void display2DArray(int (*arr)[5], int rows){}
需要注意的是,如果写成这样子就没有用了,他表示 arr 数组含有五个元素,每个元素都是指向 int 类型的指针。
void display2DArray(int *arr[5], int rows){}
同理,如果是这样子写就是传递一个三维数组了
void display3DArray(int (*arr)[2][4], int rows)
分配动态数组的方法是什么?
int rows = 2;
int columns = 5;
int **matrix = (int **) malloc(rows * sizeof(int *));
for (int i = 0; i < rows; i++) {
matrix[i] = (int *) malloc(columns * sizeof(int));
}
如何构造参差不齐的数组?
int (*(arr2[])) = {
(int[]) {0, 1, 2, 3},
(int[]) {4, 5},
(int[]) {6, 7, 8}};
构造长的一样的数组
int (*(arr1[])) = {
(int[]) {0, 1, 2},
(int[]) {3, 4, 5},
(int[]) {6, 7, 8}};
为什么不提倡使用参差不齐的数组?
因为你没法记住某个元素的长度究竟是多少,一不小心你就数组越界了。
string 的定义是什么?
string 是一段符号并且以 ASCII 码 NUL 符号结尾的东西。
NUL 意味着 \0
string 一般存储在数组里,在内存里一般分配到堆。
然而,并不是所有的字符数组都是 string,因为他不一定是以 NUL 结尾的。
string 的长度是怎么算的?
一般计算 String 长度的时候,都会忘记 NUL 这个字符,所以如果是分配给某个 string 的长度,一定要记得分配上 NUL 字符的长度。
NUL 和 NULL 有什么区别?
NULL 和 NUL 是不一样的。
NULL 是个特殊的指针,被定义为 ((void*)0)
而 NUL 则是一个 char 类型的字符,并且被定义为 \0
他们两个是不可能互相转换的。
字符变量的长度是多少?
printf("%d\n",sizeof(char));
printf("%d\n",sizeof('A'));
当执行的时候,第一个输出是 1,第二个输出是 4,第二种类型是 character literal,他是 int 类型,这是语言的设计问题。
string 是否可变?
在大部分编译器看来,string 都是常量,但是对于 GCC 编译器来说,却是有办法改变 string 的值。
char *tabHeader = "Sound";
*tabHeader = 'L';
printf("%s\n",tabHeader); // Displays "Lound"
所以最安全的是这样子声明
const char *tabHeader = "Sound";
错误的初始化数组方法
char header2[];
header2 = "Media Player";
左边是数组名是指针,右边是 string,怎么可以这样子赋值
怎么让字符指针初始化为字符串?
char *header = (char*) malloc(strlen("Media Player")+1);
strcpy(header,"Media Player");
使用 malloc 来确定字符串长度的时候,需要注意什么?
一定要记得算上 NUL 这个字符。
不要使用 sizeof 来测量 string 的长度是多少,因为 sizeof 会返回 array 或者 pointer 的大小,而不是 string 的长度。
你应该使用 len 函数来测量。
指针指向结构体的话,解析结构体内元素的方法是什么?
Person *ptrPerson; // Person 是结构体
ptrPerson = (Person*)malloc(sizeof(Person));
ptrPerson->firstName = (char*)malloc(strlen("Emily")+1);
strcpy(ptrPerson->firstName,"Emily");
ptrPerson->age = 23;
另一种解析方法
Person *ptrPerson;
ptrPerson = (Person*)malloc(sizeof(Person));
(*ptrPerson).firstName = (char*)malloc(strlen("Emily")+1);
strcpy((*ptrPerson).firstName,"Emily");
(*ptrPerson).age = 23;
不好的指针申明方式有哪些?
int* ptr1, ptr2;
这个的声明方式, ptr1 才是指针,而 ptr2 是 int 类型的变量。
所以正确的声明方式是
int *ptr1, *ptr2;
错误的内存管理方法
不应该两次 free 一个指针,因为那样子会出错。
DMA 是什么?
Direct Memory Access (DMA)
这是一种 low-level 操作,他用于在内存和其他设备之间传输数据。
这个功能并不是 ANSI C 的功能之一,他是操作系统提供的。
指针别名是怎么回事?
当两个指针指向同一个地址的时候,第二个指针就叫做第一个指针的别名。
如何防止指针别名?
使用 restrict 关键字,在声明这个指针的时候,就使用 restrict 关键字。
他表示这个指针指向的内存是独一无二的,只有他这个指针才能指向,其他指针不能指向这个内存区域。
经常使用 restrict 关键字,有利于提高程序的性能。
Uderstanding and using Pointers 读书笔记的更多相关文章
- 《Essential C++》读书笔记 之 面向过程编程风格
<Essential C++>读书笔记 之 面向过程编程风格 2014-06-18 2.2 调用(invoking)一个函数 2.2.1 Pass by Reference语义 在函数sw ...
- 《More Effective C++》读书笔记(零)Basic 基础条款
这是篇读书笔记,只记录自己的理解和总结,一般情况不对其举例子具体说明,因为那正是书本身做的事情,我的笔记作为梳理和复习之用,划重点.我推荐学C++的人都好好读一遍Effective C++ 系列,真是 ...
- 读书笔记汇总 - SQL必知必会(第4版)
本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...
- 读书笔记--SQL必知必会18--视图
读书笔记--SQL必知必会18--视图 18.1 视图 视图是虚拟的表,只包含使用时动态检索数据的查询. 也就是说作为视图,它不包含任何列和数据,包含的是一个查询. 18.1.1 为什么使用视图 重用 ...
- 《C#本质论》读书笔记(18)多线程处理
.NET Framework 4.0 看(本质论第3版) .NET Framework 4.5 看(本质论第4版) .NET 4.0为多线程引入了两组新API:TPL(Task Parallel Li ...
- C#温故知新:《C#图解教程》读书笔记系列
一.此书到底何方神圣? 本书是广受赞誉C#图解教程的最新版本.作者在本书中创造了一种全新的可视化叙述方式,以图文并茂的形式.朴实简洁的文字,并辅之以大量表格和代码示例,全面.直观地阐述了C#语言的各种 ...
- C#刨根究底:《你必须知道的.NET》读书笔记系列
一.此书到底何方神圣? <你必须知道的.NET>来自于微软MVP—王涛(网名:AnyTao,博客园大牛之一,其博客地址为:http://anytao.cnblogs.com/)的最新技术心 ...
- Web高级征程:《大型网站技术架构》读书笔记系列
一.此书到底何方神圣? <大型网站技术架构:核心原理与案例分析>通过梳理大型网站技术发展历程,剖析大型网站技术架构模式,深入讲述大型互联网架构设计的核心原理,并通过一组典型网站技术架构设计 ...
- LOMA280保险原理读书笔记
LOMA是国际金融保险管理学院(Life Office Management Association)的英文简称.国际金融保险管理学院是一个保险和金融服务机构的国际组织,它的创建目的是为了促进信息交流 ...
随机推荐
- 数据结构与算法 --- js描述队列
js描述队列 队列的特性是只能在队尾插入元素,在队首删除元素,先进先出: 队列被用在很多地方,比如提交操作系统执行的一系列进程,打印任务池,模拟现实中的排队: //队列类 function Queue ...
- Express+MySQL实现登录注册的demo
MySQL5.7.20 demo准备 安装MySQL,安装完毕之后添加系统环境变量在cmd中启动服务:net start mysql57,如果是安装MySQL8.0则服务名默认时mysql80,测试安 ...
- kali-2019.4中文乱码问题的解决
1.安装完kali-2019.4版出现乱码问题 2.更新源,用vi编辑器,在/etc/apt/resources.list中添加清华源 #清华大学 [更新源]deb https://mirrors.t ...
- springboot-mybatis配置问题
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)问题
- StringBuffer StringBuilder String 区别
String 字符串常量 不可变 使用字符串拼接时是不同的2个空间 StringBuffer 字符串变量 可变 线程安全 字符串拼接直接在字符串后追加 StringBui ...
- C++不同类中的特征标相同的同名函数
转载请注明出处,版权归作者所有 lyzaily@126.com yanzhong.lee 作者按: 从这篇文章中,我们主要会认识到一下几点: ...
- C++ STL——优先队列的结构体表示方法
优先队列是队列的一种,但是自身具有一定的排序功能,所以不具有队列“先进先出”的性质 刚刚接触优先队列,看过网上的用法后感觉还是太过于朦胧,所以打算自己写一个稍微细节一点的. 头文件 #include& ...
- HTTP&HTTPS协议详解之HTTP篇
一.HTTP简介 01.什么是HTTP HTTP(HyperText Transfer Protocol ,超文本传输协议),是一个基于请求与响应的,无状态的,应用层的协议,常基于TCP/IP协议传输 ...
- 某cms审计思路,以及ci框架如何找寻注入点
某cms审计思路,以及ci框架如何找寻注入点 ABOUT 之前闲着没事的时候审的某cms,之前看一群大表哥刷过一次这个cms,想着看看还能不能赶得上分一杯羹,还是审计出来些东西,来说一说一个前台注入吧 ...
- [redis读书笔记] 第一部分 数据结构与对象 对象类型
- 从前面redis的基本数据结构来看,可以看出,redis都是在基本结构(string)的基础上,封装了一层统计的结构(SDS),这样让对基本结构的访问能够更快更准确,提高可控制度. - redis ...