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 指针相关的有效运算

  1. 相同类型指针间的赋值运算
  2. 指针值加或减一个整数值的运算
  3. 指向相同数组中的元素的指针之间的减或比较运算
  4. 将指针赋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复杂指针的理解

  基本形式:

  1. char **argv; //二维指针
  2. int (*daytab)[13];//指向一个int[13]数组的指针
  3. int *daytab[13];//指针数组
  4. void (*comp)();//函数指针
  5. void *comp();//返回值为指针的函数
  6. 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 对结构体的合法操作  

  1. 拷贝
  2. 作为一个单元对其赋值
  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的更多相关文章

  1. the C programming language 阅读笔记1

    读了一遍著名的<the C programming language>,果然如听说的一样,讲解基础透彻,案例简单典型,确实自己C语言还有很多细节点不是很清楚. 总结一下阅读的收获(部分原书 ...

  2. C++ Programming language读书笔记

    C语言,结构化程序设计.自顶向下.逐步求精及模块化的程序设计方法;使用三种基本控制结构构造程序,任何程序都可由顺序.选择.循环三种基本控制结构构造. 模块结构:"独立功能,单出.入口&quo ...

  3. The C++ Programming Language 学习笔记 第7章 函数

    1.关于内联函数(inline)      借用一下书中的例子. inline int fac(int n) { ) ? :n*fac(n-); }      inline描述符给编译器一个提示,要求 ...

  4. The C++ Programming Language 学习笔记 第6章 表达式和语句

    1.关于strcpy函数. 书中说c风格的字符串尽量少用,strcpy这样的函数应该也要少用.这里讲这个函数主要是要通过本章课后练习第十题来讲一下前面提及的要点.巩固一下前几章的知识.写了一段,本来感 ...

  5. The C++ Programming Language 学习笔记 第5章 指针、数组和结构

    1.关于输出指向字符的指针的值. 现在定义,char c='a',char* pc=&c.在C中,输出该值只需要printf("%p\n",pc);而在C++中,如果cou ...

  6. The C++ Programming Language 学习笔记 第四章 类型和声明

    1.关于main 函数中的 return 0 C99标准中,main 函数的返回值类型必须是 int ,这样返回值才能传递给程序的激活者(如操作系统).如果 main 函数的最后没有写 return ...

  7. 《Multiplayer Game Programming》阅读笔记

    在图书馆发现一本<网络多人游戏架构与编程>-- Joshua Glazer, Sanjay Madhav 著.书挺新的,17年出版的,内容很有趣,翻一翻可以学到不少在<计算机网络&g ...

  8. Programming Ruby 阅读笔记

    在Ruby中,通过调用构造函数(constructor)来创建对象 song1=Song.new("Ruby") Ruby对单引号串处理的很少,除了极少的一些例外,键入到字符串字面 ...

  9. 《The Swift Programming Language》的笔记-第24页

    The Swift Programming Language读书笔记学习笔记 第24页 本页主要内容有两个:打印输出和怎样在swift凝视代码 1 怎样打印变量和常量的值? 使用println函数,细 ...

随机推荐

  1. 在一个RAC集群中最多支持多少节点

    How many nodes can one have in an HP-UX/Solaris/AIX/Windows/Linux cluster? Technically and since Ora ...

  2. 使用Open Live Writer 的代码高亮插件体验

    由于windows live writer 2012 已经停止服务,转而推出开源项目Open Live Writer .虽然Open Live Writer 也没怎么更新,官网更是一个插件都没有放出来 ...

  3. HDU 1020 Encoding POJ 3438 Look and Say

    Encoding Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  4. Servlet 浅谈(三)

    关于Session 关于http协议后面会有一系列文章专门介绍.这里就大概了解一下:首先需要知道一点:HTTP是无状态的. 什么是无状态呢? 客户与服务器建立连接.发出请求.得到响应.关闭连接.整个流 ...

  5. JavaScript学习笔记(三)this关键字

    this是Javascript的关键字,代表在函数运行时,自动生成一个内部对象,只能在函数内部使用.例如: function test() { this.x = 1; } 随着函数的使用场合不同,th ...

  6. CentOS DNS resolv重启无效的解决方法

    分类: LINUX 直接修改/etc/resolv.conf不行.必须要在/etc/sysconfig/network-scripts/ifcfg-eth0里面最后 加上dns的设置.要不然,重启后, ...

  7. Spring中常用的hql查询方法(getHibernateTemplate())

    一.find(String queryString); 示例:getHibernateTemplate().find("from bean.User"); 返回所有User对象 二 ...

  8. 限制TextBox输入,只能输入整数

    public class TextBoxInt : TextBox { public TextBoxInt() { KeyDown += TextBoxInt_KeyDown; TextChanged ...

  9. 博士论文》》》 Journal,magazine,transaction,proceeding

    Journal期刊:刊登关于某特殊主题的文章的期刊 magazine杂志:综合性内容的期刊 transactions(学会等的)议事录,会报,会刊 proceedings记录, 会议录; 年[学]报; ...

  10. SPI模式下MCU对SD卡的控制及操作命令

    一.前言 SD 卡有两个可选的通讯协议:SD 模式和 SPI模式 SD 模式是SD 卡标准的读写方式,但是在选用SD 模式时,往往需要选择带有SD 卡控制器接口的 MCU,或者必须加入额外的SD卡控制 ...