Expert C Programming(C专家编程) 读书笔记
目录
- 几个比较奇葩的指针赋值
- int (* fun())()
- int (* foo())[]
- int (*foo[])()
- const 关键词的意义是什么?
- char const (*next )() 怎么读?
- char (c[10])(int **p) 怎么读?
- typedef 不应该怎么用?
- definition 和 declaration 有什么不同?
- 数组和指针之间的区别是什么?
- ABI 是什么?动态链接的目的是什么?
- 静态库和动态库怎么创建?
- 编译器是怎么赋值的?
- 如何生成链接动态库的文件?
- 哪些关键字是最好别定义成变量名的?
- 关于链接的一些小事
- magic numbers 是什么?
- segment 是什么概念?在 x86 和 UNIX 下有什么区别?
- 如何查看 segment 的大小?
- 存储介质的访问速度排序
- swap out 是什么? swap area 又是什么?
- 堆的实现原理是什么?
- 使用 malloc 函数的注意事项?内存泄露是怎么回事?
- 如何预防内存泄露?
- 如何查看内存泄露?
- 内存的一些知识
- 指针和数组的规则总结
- 数组在内存里面是怎么分布的?
- 数组的真实形态
- c 定义动态数组的方法
- system call 和 library call 有什么不同?
- file descriptor 和 file pointer 区别
几个比较奇葩的指针赋值
int (* fun())()
表示 fun() 这个函数,返回一个指针,这个指针指向一个返回 int 类型的函数。
int (* foo())[]
表示 foo() 这个函数,返回一个指针,这个指针指向 int 类型的数组
int (*foo[])()
foo[] 这个数组里面都是指针,这些指针指向一个返回 int 类型的函数
const 关键词的意义是什么?
他意味着,用他声明的变量只读,因为他就表示 constant ,就是常量。
char * const (next )() 怎么读?
next 这个指针,指向一个函数,这个函数返回一个只读的指针,这个指针指向 char 类型。
char (c[10])(int **p) 怎么读?
下面这句话代表了,C是一个含有十个元素的数组,其中每个元素都是一个指针,这些指针分别指向一个形参是 int**p 的函数,这个函数返回一个指针,这个指针指向 char
typedef 不应该怎么用?
千万千万不要将 typedef 这么用,这样子用意义不明确。
typedef int *ptr, (*fun)(), arr[5];
/* ptr is the type “pointer to int”
* fun is the type “pointer to a function returning int”
* arr is the type “array of 5 ints”
*/
以及
unsigned const long typedef int volatile *kumquat;
definition 和 declaration 有什么不同?
Definition 只能出现一次。
declaration 能出现很多次。
数组和指针之间的区别是什么?
pointer | arrays |
---|---|
保存数据的地址 | 保存数据 |
数据是被间接访问的 | 数据是被直接访问的 |
内存空间用 malloc() 分配和 free() 解除 | 内存空间隐式分配和解除 |
ABI 是什么?动态链接的目的是什么?
ABI 是我们使用动态链接的目的。
全称叫做 Application binary interface
ABI 保证了一些库是肯定会出现在编译环境上的,比如说libc (C runtimes), libsys (other system runtimes), libX (X windowing), libnsl (networking services)
其他的库可以静态链接,也可以动态链接。
静态库和动态库怎么创建?
任何人都可以创建静态库。
你将代码进行编译(不要编译 main 函数),然后使用正确的文件编译出 .o 文件,名字前缀为 ar 的是静态库,为 ld 的是动态库。
编译器是怎么赋值的?
被分配在等号左边的符号叫做 l-value 被分配在右边的符号叫做 r-value
编译器分配地址给每个左边的符号,分配数值给右边的符号,左边符号的地址在编译时期就已经是知道的了,与之相反,右边符号的数值要等到运行的时候才知道。
如果右边符号的数值在编译时期就要知道,那么编译器会通过左边符号的地址来进行寻址,找到具体的数值之后,会将他放到寄存器里面。
如何生成链接动态库的文件?
动态库都靠一个链接工具,名为 ld 命令。
一般动态库文件的后缀都是 .so 意思是 share object
哪些关键字是最好别定义成变量名的?
关键词不是不可以被定义成变量名,只是因为这样子做会让你的程序很难理解,并且调试的时候会很不顺畅。
下面这些是 C 里面的保留字
关于链接的一些小事
动态链接库,一般叫做 .so 而静态链接库,一般叫做 .a
你告诉编译器链接某个库是使用缩写的,比如 libthread.so 可以使用 -lthread
magic numbers 是什么?
可执行文件在 Unix 里面也是有标签那样的东西的,我们称这些东西为 magic numbers
程序可以通过 magic numbers 来推断出某个比特的集结体是什么东西,比如说可以通过下面的 magic number 来推断出他代表的是 superblock
#define FS_MAGIC 0x011954
segment 是什么概念?在 x86 和 UNIX 下有什么区别?
在 Unix 下面,segment 代表了一堆相关联的 section 联结在一起的东西。
在 x86 下面,内存模型不是全部一个整体的,而是被分成很多个 segment ,每一个 segment 大小是 64 Kbyte
如何查看 segment 的大小?
直接对某个文件运行 size 就行了。
比如 size a.out
存储介质的访问速度排序
swap out 是什么? swap area 又是什么?
堆的实现原理是什么?
堆的结尾用一个叫做 break 的指针指向着,当 heap manager 觉得需要更多的内存的时候,就将这个指针向后移动,通过使用 brk() 和 sbrk(),这两个指令你是无法通过显示指定的。
但是如果你使用 malloc 分配了足够的内存,brk() 会自动为你调用的。
使用 malloc 函数的注意事项?内存泄露是怎么回事?
C 没有垃圾回收,所以你必须很小心的使用 malloc() 和 free()
因为 malloc 函数是分配 heap 的内存给你,如果你没有及时清除,有可能会造成内存泄露。
如何预防内存泄露?
一个简单的预防内存泄露的方法,就是使用 alloca() 函数,这个函数会从 stack 里分配内存,而 stack 里的内存,都是用完就回收的。
但是在 stack 里面的东西,就最好不要放长期需要用到的变量,而且你不能在不支持 stack 的硬件上实现这个函数。
如何查看内存泄露?
其实就是观察内存的变化。
有两种方法,一种是观察 swap 空间的大小。
/usr/sbin/swap -s total
通过隔一段时间就输入一次上面的命令,来观察 swap 空间是否变小,来判断是否内存泄露了。
你还可以使用 netstat 或者 vmstat 这些监控工具来查看。
如果你看到被使用的内存在不停的增加,那么就占用内存增长的最多的那个进程,就很有可能是内存泄露的来源。
内存的一些知识
1、
每一个 byte 都有他自己的 virtual address ,也就是虚拟地址。
2、
bytes 只能在内存里面被引用
3、
只有 VM manager 才知道一个 byte 是在内存里面,还是在硬盘里面?
4、
唯一的引用你的 byte 的方法,是给他一个虚拟地址。然而你的 byte 必须要存在内存里面才能被引用,如果你的程序要使用到的 byte 不存在内存里面,那么 VM manager 会去硬盘里面寻找,找到的话,他会将硬盘里包含这个 byte 的 page 给引进 memory 里面,如果他发现,memory 已经没有空间给他了,那么他会在 memory 里面找最老最没用的那个 page ,并且将这个 page 给抛出去,然后将那个 page 给引进来这个位置。
而你根本就不知道这个过程所发生的事情。
5、
你不能够引用别人的 virtual address ,因为 VM manager 知道这个 byte 是属于那个程序的,就算这两个程序的某一个 byte 使用了相同的 virtual address ,你也没法引用别人程序的 virtual address
指针和数组的规则总结
1、
访问 a[i] 的时候,经常被编译器编译成一个指针,那个代码等同于 *(a+i)
2、
Pointer 永远不会被重新翻译成数组,你可以定义一个指针,然后在这个指针后面使用 [i] 的方式,来给指针赋值,这样子做等同于使用数组。
数组在内存里面是怎么分布的?
数组的真实形态
pea[i][j]
会被编译器翻译成
*(*(pea+i)+j)
c 定义动态数组的方法
最核心的思想就是使用 malloc 函数,然后你会得到一个指向一些内存空间的指针,你将这个指针当成数组来用就行了。
#include <stdlib.h>
#include <stdio.h>
. . .
int size;
char *dynamic;
char input[10];
printf(“Please enter size of array: “);
size = atoi(fgets(input,7,stdin));
dynamic = (char *) malloc(size);
. . .
dynamic[0] = ‘a’;
dynamic[size-1] = ‘z’;
system call 和 library call 有什么不同?
file descriptor 和 file pointer 区别
file descriptor 在 Unix 里面是用来描述文件信息的。
file pointer 是保存了一个文件的指针。
Expert C Programming(C专家编程) 读书笔记的更多相关文章
- c专家编程读书笔记
无论在什么时候,如果遇到malloc(strlen(str));,几乎可以直接断定他是错误的,而malloc(strlen(str)+1):才是正确的: 一个L的NUL哟关于结束一个ACSII字符串: ...
- 类型解释器——C专家编程读书笔记
对于声明,应该按下面的步骤来进行解释: 1) 声明从它的名字开始读取,然后按照优先级顺序依次读取 2) 优先级顺序 a) 括号括起来的部分 b) 后缀操作符,()表示函数,[]表示数组 c) 前缀操作 ...
- Node.js高级编程读书笔记Outline
Motivation 世俗一把,看看前端的JavaScript究竟能做什么. 顺便检验一下自己的学习能力. Audience 想看偏后台的Java程序员关于前端JavaScript的认识的职业前端工程 ...
- 《android开发进阶从小工到专家》读书笔记--HTTP网络请求
No1: 客户端与服务器的交互流程: 1)客户端执行网络请求,从URL中解析出服务器的主机名 2)将服务器的主机名转换成服务器的IP地址 3)将端口号从URL中解析出来 4)建立一条从客户端与Web服 ...
- python高级编程读书笔记(一)
python高级编程读书笔记(一) python 高级编程读书笔记,记录一下基础和高级用法 python2和python3兼容处理 使用sys模块使程序python2和python3兼容 import ...
- C++Windows核心编程读书笔记
转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...
- CSAPP 并发编程读书笔记
CSAPP 并发编程笔记 并发和并行 并发:Concurrency,只要时间上重叠就算并发,可以是单处理器交替处理 并行:Parallel,属于并发的一种特殊情况(真子集),多核/多 CPU 同时处理 ...
- unix环境高级编程-读书笔记与习题解答-第一篇
从这周开始逐渐的进入学习状态,每天晚上都会坚持写c程序,并且伴随对这本书的深入,希望能写出更高质量的读书笔记和程序. 本书的第一章,介绍了一些关于unix的基础知识,在这里我不想去讨论linux到底是 ...
- UNIX网络编程--读书笔记
会集中这段时间写UNIX网络编程这本书的读书笔记,准备读三本,这一系类的文章会不断更新,一直会持续一个月多,每篇的前半部分是书中讲述的内容,每篇文章的后半部分是自己的心得体会,文章中的红色内容是很重要 ...
- MacTalk·人生元编程 - 读书笔记
简介 <MacTalk·人生元编程>是一本随笔文集,主要内容来自作者的微信公众平台"MacTalk By 池建强".本书撰写于2013年,书中时间线却不止于此.作者以一 ...
随机推荐
- ES6笔记分享 part 1
ECMAScript ES6 从一脸懵逼到灵活运用 var let const var let const 的比较 声明与赋值 var声明的变量是可以重新赋值的,也可以重复声明 let和const声明 ...
- Shell常用命令之sort
sort命令 sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出.sort命令既可以从特定的文件,也可以从stdin中获取输入. 语法 sort (选项) (参数) 选项 - ...
- 使用nutz框架,找不到入口函数,访问Url报404
案例 今天在跟着nutz框架教程去配置demo时,发现访问URL找不到入口函数,出现了Search mapping for path=/user/count : NOT Action match 异常 ...
- Python 中的三元运算(软件测试中运用)
前言 在java中,有类似于 (condition) ? a :b 这样的语法,表示如果condition 为真,返回a,反之返回b.我们称之为三元运算. 那Python中,有没有这样的语法呢,非常遗 ...
- LeetCode.509——斐波那契数
问题描述: 斐波那契数,通常用 F(n) 表示,形成的序列称为斐波那契数列.该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和.也就是: F(0) = 0, F(1) = 1 F(N) ...
- Open Images V4 下载自己需要的类别
OpenImages V4数据集描述1)这个v4数据集主要有两种用途:对象检测及分类,意思是说可以用这个数据集训练出对象检测模型,用于识别图像中的对象类别及位置边框.视觉关系检测,比如你用这个v4数据 ...
- codeforces 540D Bad Luck Island (概率DP)
题意:会出石头.剪刀.布的人分别有r,s,p个,他们相互碰到的概率相同,输的人死掉,问最终活下去的人是三种类型的概率 设状态dp(i,j,k)为还有i个石头,j个剪刀,k个布时的概率,dp(r,s,p ...
- java12类的无参方法
package com.jh.test01; public class AutoLion { // 属性: 颜色 黄色 String color = "黄色"; // 函数:跑,叫 ...
- SpringBoot之ApplicationRunner接口和@Order注解
我们在开发中可能会有这样的情景.需要在容器启动的时候执行一些内容.比如读取配置文件,数据库连接之类的.SpringBoot给我们提供了ApplicationRunner接口来帮助我们实现这种需求.该接 ...
- win10系统安装VMware虚拟机软件以及linux系统
一.安装VMware 1.在VMware官网下载VMware Workstation Pro 15.5.1 下载地址:https://my.vmware.com/cn/web/vmware/detai ...