the C programming language 阅读笔记2
1. 指针
1.1 自增符的使用
++*p;//p指向的内容加一
(*p)++; //p指向的内容加一
*p++;//p本身自增
*++p; //p本身自增
因为诸如*和++这样的一元运算符在表达式求值时按从右到左的顺序和运算分量结合。
1.2 指针运算比数组下标运算快
1.3 数组名
一个数组名即该数组第0个元素的位置,所以赋值语句pa = &a[0]等价于pa = a
1.4 数组下标求值
在求数组元素a[i]的值时,C语言实际上先将其转换成*(a + i)的形式再求值
而对于指针pa而言,pa[i] 等价于 *(pa + i)
1.5 数组名与指向数组首地址的指针的区别
前者非变量,后者为变量
1.6 函数参数传入指针
在函数的定义中,char s[]与char *s是等价的。
当函数参数传入一个较大数组的子数组的指针时,并不会对函数本身造成影响
1.7 指针使用负下标
如果确信某个元素存在,则使用p[ -1]、p[ -2 ]这样的表达式在语法上是合法的。
int b[] = {,,,,,,,,,};
int *a = b + ;
则:a[-3] = 1; a[ -2] = 2;
1.8 alloc与afree的栈式管理
先分配的后释放
调用alloc之前:
allocbuf:

调用alloc之后:
allocbuf:

afree(p)是将空闲单元起始指针指向p位置
1.9 比较运算
在知道指针值意义的情况下,可以对其进行比较运算
int b[] = {,,,,,,,,,};
int *p1 = &b[];
int *p2 = &b[];
则p2 – p1 = 4
1.10 指针相关的有效运算
- 相同类型指针间的赋值运算
- 指针值加或减一个整数值的运算
- 指向相同数组中的元素的指针之间的减或比较运算
- 将指针赋0或指针与0之间的比较运算
1.11 strcpy函数
原书上的函数:
void strcpy( char *s, char *t){
while( *s++ = *t++);
}
这里的指针s是临时变量,就算自增也不会改变实参中存储的地址,改变的只是形参指向的地址里的内容,所以用实参可以正确找到首地址,从而正确完成了strcpy函数的功能。
非常感谢@garbageMan的提醒。
1.12 函数参数为二维数组
f( int daytab[2][13])
= f(int daytab[][13])
=f(int (*daytab)[13])
传入一个指针,指针每个元素的内容是一个数组
1.13指向数组的指针和指针数组
int (*daytab)[13] -->指针指向的内容是int[13]的数组
int *daytab[13]à13个指针指向int
指针的实质是根据定义的类型和其中存储的地址来解析内存里的数据
print (Int *s){
s[1] = 5;//即为*(s+1) = 5;
};
*(s+1) = 5;
根据指针所存的地址及所定义的类型,改变其中的数据
int (*daytab)[13]
所定义的类型为int[13]的数组
所以,对该指针解引用得到的是一段13个int长的内存区域的首地址
即:
int a[4][4]; int (*b)[4] = a;

b[2][2] = *(*(b+2)+2) = (*(s+2))[2] != *(s+2)[2]
分析:
*b解引用得到:int[4]
*b的值为这段int[4]的首地址
**b为这段int[4]首地址指向的内容即为b[0][0]的值
1.14 指针数组的初始化
即用指针来初始化数组
1.15 指向函数的指针
1.15.1 一个实例:
支持-n进行数字排序的排序函数
#include <stdio.h>
#include <string.h>
#define MAXLINES 5000 /* max #lines to be sorted */
char *lineptr[MAXLINES]; /* pointers to text lines */
int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);
void qsort(void *lineptr[], int left, int right,
int (*comp)(void *, void *));
int numcmp(char *, char *);
/* sort input lines */
main(int argc, char *argv[])
{
int nlines; /* number of input lines read */
int numeric = ; /* 1 if numeric sort */
if (argc > && strcmp(argv[], "n")== )
numeric = ;
if ((nlines = readlines(lineptr, MAXLINES)) >= ) {
qsort((void**) lineptr, , nlines1,
(int (*)(void*,void*))(numeric ? numcmp : strcmp));
writelines(lineptr, nlines);
return ;
} else {
printf("input too big to sort\n");
return ;
}
}
/* qsort: sort v[left]...v[right] into increasing order */
void qsort(void *v[], int left, int right,
int (*comp)(void *, void *))
{
int i, last;
void swap(void *v[], int, int);
if (left >= right) /* do nothing if array contains */
return; /* fewer than two elements */
swap(v, left, (left + right)/);
last = left;
for (i = left+; i <= right; i++)
if ((*comp)(v[i], v[left]) < )
swap(v, ++last, i);
swap(v, left, last);
qsort(v, left, last1,comp);
qsort(v, last+, right, comp);
}
1.15.2 指向函数的指针&返回为指针的函数
指向函数的指针:
int (*comp)(void *, void *);
返回为指针的函数:
int *comp(void *, void *);
C在编译时,每个函数都有一个入口地址,该入口地址就是函数指针所指向的地址
有了指向函数的指针变量后,可用该指针变量调用函数
1.15.3 函数指针的定义
1.void (*f)(int x);
调用(*f)(x);
2.typedef int (*fun_ptr)(int,int);
fun_ptr max_func = max;
c = max_func(a,b);
1.15.4 函数指针数组
1.标准定义:
int (*op[2])(int,int);
2.强制类型转换
定义为普通的int型指针数组
在要使用时,强制类型转换为相应的函数指针类型
int *a;
int add(int a, int b);
a = add;
r = ((int (*)(int,int))(a))(numa,numb);
1.16复杂指针的理解
基本形式:
- char **argv; //二维指针
- int (*daytab)[13];//指向一个int[13]数组的指针
- int *daytab[13];//指针数组
- void (*comp)();//函数指针
- void *comp();//返回值为指针的函数
- void (*op[2])();//函数指针数组
char (*(*x())[])()
*x()如上式5,表示返回值为指针的函数
剩余部分表述的就是所返回的指针的类型:
返回的指针类型如上式6,返回值char的函数指针数组
所以,
x是一个函数,该函数的返回值是一个指向类型为char的函数指针数组的指针
char (*(*x[3])())[5]
(*x[3])()如上式6为函数指针数组
其他的部分描述函数指针数组的返回值
所以,x是一个返回值为char[5]的长度为3的函数指针数组
2.内存布局
2.1数组的内存布局
int a[10];

内存是连续分配的相邻区域
int *p = &a;
p = p + 1;
2.2 大端模式 & 小端模式
大端模式:即指数据的高位,保存在内存的低地址中,而数据的低位,保存在内存的高地址中
例:
65534(0x0000FFFE)
小端模式(一字节存储单位):
0x0000 0x0008 0x0010 0x0018
FE FF 00 00
大端模式:
0x0000 0x0008 0x0010 0x0018
00 00 FF FE
3.结构
3.1 结构变量的定义方法
struct {…} x,y,z;
语法上与int x,y,z;相似
3.2 结构变量的定义方法
typedef struct{…} myType;
3.3 结构变量的初始化
struct point maxpt = {320,200};
3.4 对结构体的合法操作
- 拷贝
- 作为一个单元对其赋值
- 通过&取其地址
- 访问结构成员
3.5 结构数组的初始化
struct key{
char *word;
int count;
} keytab[] = {“auto”,,”break”,};
3.6 字节对齐
参加博文《关于C语言中结构体中的结构体成员导致的字节对齐问题》
4.其他
4.1 逗号表达式
逗号运算符,优先级别最低,它将两式连起来,其求解过程先表达式1,后表达式2,整个表达式是表达式2的值
(3+5,6+8) = 14
(a = 3*5,a*4) = 60
4.2 命令行参数
argc 程序执行时命令行中参数的数目
argv 指向字符串数组的指针
4.3 联合
在单独存储区域中管理不同类型的数据
4.4 位字段
struct {
unsigned int is_keyword : ;
unsigned int is_extern : ;
unsigned int is_static : ;
}flags;
分配空间大小为flags分配字段类型最长的倍数,然后一个字节一个字节地存储。在字节内的存储方式未知,根据不同的编译器决定从右往左还是从左往右。GCC是从右往左。
the C programming language 阅读笔记2的更多相关文章
- the C programming language 阅读笔记1
读了一遍著名的<the C programming language>,果然如听说的一样,讲解基础透彻,案例简单典型,确实自己C语言还有很多细节点不是很清楚. 总结一下阅读的收获(部分原书 ...
- C++ Programming language读书笔记
C语言,结构化程序设计.自顶向下.逐步求精及模块化的程序设计方法;使用三种基本控制结构构造程序,任何程序都可由顺序.选择.循环三种基本控制结构构造. 模块结构:"独立功能,单出.入口&quo ...
- The C++ Programming Language 学习笔记 第7章 函数
1.关于内联函数(inline) 借用一下书中的例子. inline int fac(int n) { ) ? :n*fac(n-); } inline描述符给编译器一个提示,要求 ...
- The C++ Programming Language 学习笔记 第6章 表达式和语句
1.关于strcpy函数. 书中说c风格的字符串尽量少用,strcpy这样的函数应该也要少用.这里讲这个函数主要是要通过本章课后练习第十题来讲一下前面提及的要点.巩固一下前几章的知识.写了一段,本来感 ...
- The C++ Programming Language 学习笔记 第5章 指针、数组和结构
1.关于输出指向字符的指针的值. 现在定义,char c='a',char* pc=&c.在C中,输出该值只需要printf("%p\n",pc);而在C++中,如果cou ...
- The C++ Programming Language 学习笔记 第四章 类型和声明
1.关于main 函数中的 return 0 C99标准中,main 函数的返回值类型必须是 int ,这样返回值才能传递给程序的激活者(如操作系统).如果 main 函数的最后没有写 return ...
- 《Multiplayer Game Programming》阅读笔记
在图书馆发现一本<网络多人游戏架构与编程>-- Joshua Glazer, Sanjay Madhav 著.书挺新的,17年出版的,内容很有趣,翻一翻可以学到不少在<计算机网络&g ...
- Programming Ruby 阅读笔记
在Ruby中,通过调用构造函数(constructor)来创建对象 song1=Song.new("Ruby") Ruby对单引号串处理的很少,除了极少的一些例外,键入到字符串字面 ...
- 《The Swift Programming Language》的笔记-第24页
The Swift Programming Language读书笔记学习笔记 第24页 本页主要内容有两个:打印输出和怎样在swift凝视代码 1 怎样打印变量和常量的值? 使用println函数,细 ...
随机推荐
- T-sql编程
T-Sql中的变量都是@符号开头的 以一个@符号开头,叫做“用户声明的变量” 以两个@@开头的叫做"全局变量","系统变量",是由系统来维护的.无需我们维护 - ...
- 从一个小例子认识SQL游标
1 什么是游标: 关系数据库中的操作会对整个行集起作用. 例如,由 SELECT 语句返回的行集包括满足该语句的 WHERE 子句中条件的所有行. 这种由语句返回的完整行集称为结果集. 应用程序 ...
- [IOS]图标尺寸
最新参考网址:https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/Ico ...
- (转)OpenGL中位图的操作(glReadPixels,glDrawPixels和glCopyPixels应用举例)
(一)BMP文件格式简单介绍 BMP文件是一种像素文件,它保存了一幅图象中所有的像素.这种文件格式可以保存单色位图.16色或256色索引模式像素图.24位真彩色图象,每种模式种单一像素的大小分别为1/ ...
- Char型和string型字符串比较整理
1.赋值 char赋值: char ch1[] = "give me"; char ch2[] = "a cup"; strcpy(ch1,ch2); cout ...
- Ecside基于数据库的过滤、分页、排序
首先ecside展现列表.排序.过滤(该三种操作以下简称为 RSF )的实现原理完全和原版EC一样, 如果您对原版EC的retrieveRowsCallback.sortRowsCallback.fi ...
- css动画,css过度,js动画
1jQuery动画 语法a$(selector).animate(styles,options) 语法b$(selector).animate(styles,speed,easing,callback ...
- accordion
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- PHP不显示报错了怎么办~
php.ini里设置吧, 找到 display_errors, 设置成on, error_reporting = E_ALL
- Android 微信分享信息
随着微信越来越火,越来越多的应用要求有分享到微信的功能.虽然有很多平台都帮集成有分享功能,比如友盟.但是个人觉得友盟集成的东西太多了,自己封装得太过分了,很多资源文件也要带进去,所以感觉不是怎么好,所 ...