《C专家编程》读书笔记

第一章

const float* 表示一个指向float类型常量的指针

第二章

1. 在c语言中const并非真正表示“常量”,在数组定义与case中不可以使用

2. case的一些问题

   1: #include<stdio.h>

   2:  

   3: main(){

   4:     int i = 2;

   5:     switch(i){

   6:     case 1:

   7:     printf("1\n");

   8:     case 2:

   9:     printf("2\n");

  10:     case 3:

  11:     printf("3\n");

  12:     case 4:

  13:     printf("4\n");

  14:     }

  15: }

这段代码打印出来的是:

2

3

4

3. 函数可见性

   1: void sb(){}/*any where*/

   2: extern void zt(){}/*any where best way!! */

   3: static void sbzt(){}/*only in this file*/

4. c语言的一些符号重载

符号 意义
static 在函数内部,表示该变量值在各个调用间一直保持一致
  在函数声明阶段,表示该函数只对本文件可见
extern 用于函数定义,表示全局可见(虽然是默认的,应当养成良好的习惯使用)
  用于变量,表示是在其他文件中定义的变量
void 表示函数不返回值
  声明指针时,表示通用指针类型
  在参数列表中表示没有参数

5. sizeof +类型名的时候必须加括号 + 变量名时不需要(个人以为还是加上为好)

6. 运算优先级问题

.的优先级高于*

[]高于*

函数()高于*

==、!= 高于位运算

==、!= 高于赋值运算

算数运算符高于位运算

,运算符优先级最低

说多了都是泪,记的加上合适的括号!

7. 运算的结合顺序

=赋值号右结合,先计算右侧再复制,|| &&严格从左到有,但是函数参数的计算顺序并不固定

8. gets()并不在意buffer的长度,记的使用fgets()替换它

第三章

1. 变量的声明应该与类型的声明分开

2. 默认情况下,枚举的值从1开始,当某一值被人为赋值后,接下来的值+1

3. c语言生命的优先级规则:

   1) 从名字开始读取,按如下优先级进行

2) 优先级从高到低:

a. 包含名字被括号括起来的部分

b. 后缀操作符:

[] 表示数组

()表示函数

c. 前缀操作符:*表示指针

d. const右侧有有类型说明符,表示const修饰类型说明符

否则,const是左边*号的修饰

4. typedef应当用在

1) 数组、结构、指针以及函数的组合类型;

2) 可以移植的类型;

note:结构标签的命名请使用统一的标记前缀或者后缀;

第五章

1. 对于多为数组,需要提供出去最左边一维之外其他维度的长度

2. 数组名是一个左值,但不是可以修改的左值(左值在编译时可知,表示存储结果的地方,右值到运算时才可知)

3. 指针与数组的区别(char* p,char a[]):

指针:

p先取得指针指向地址的内容,与偏移量相加,再取值;

数组:

a就是一个地址,直接与偏移量相加,取值;

4. char *p = ”abc”;先创建一个字符串常量,然后将p指向他!*p = “sbn”;改变的是p中存储的地址,并非修改了之中的内容

第五章

1. 动态链接&静态链接

动态链接体积小,节省空间,速度略慢

所有动态链接到某个特定函数库的可执行文件在运行时共享该函数库的一个单独的拷贝

静态链接的最大危险在于将来版本的操作系统可能与可执行文件所绑定的函数库不兼容

对于函数库应当始终使用与位置无关代码

第六章

1. 程序在内存中的分布(linux)

由高地支到低地址:

栈      进行函数调用 保存函数参数 保存临时变量 保存返回地址 alloca()函数分配的内存

堆      保存程序中动态分配的内存malloc/new

.bss   未初始化的全局变量

.data  初始化过的全局变量

.text   编译后的主体

2. 栈的结构:

栈顶
main函数局部变量
参数
前一个活动记录(mai函数指向栈顶)
返回地址
函数的局部变量
参数
前一个活动记录(指向mai上一个返回地址)
返回地址

3. 通常情况下从栈内获取内存的速度要快一些

第七章

1. malloc&calloc

类似,但是calloc在返回值诊之前吧分配好的内存全部清0

2. 段错误的几个常见原因

解除引用一个包含非法值的指针

解除引用6一个空指针

在未得到正确的权限是进行访问

用完了堆或者栈空间

第八章

1. 若使用了函数原型,就不会默认对参数进行提升

2. 将函数原型放在头文件中,函数的定义放在.c中

3. 函数指针 int(*a)();

4. 调用函数和通过指针调用函数可以使用同一种语法

第九章

1. 所有座位函数参数的数组名总是可以通过编译器转换为指针

2. 每个指针只能指向一种类型的原因在于:编译器需要知道对指针进行解除引用操作时应该取几个字节,以及每个下标的步长应该取几个字节。

3. 下面的程序

   1: #include<stdio.h>

   2:  

   3: int a[10];

   4:  

   5: void S( int a[] ) {

   6:     printf("%d\n",sizeof(a));

   7: }

   8:  

   9: main() {

  10:     printf("%d\n",sizeof(a));

  11:     S(a);

  12: }

打印的两个结果分别为40和4

4. 只有字符串指针可以初始化指针数组,其他的都不行:

char* a[] = {“aaa”,"bbb”}//可以!!

int* b[] = {{1,2,3},{1,2},{1}}//不可以!!

第十章

1. 指向23个字符的指针数组: char* a[23]

指向一个具有23个字符的数组的指针: char (*a)[23]

2. 向函数传递多维数组时,除了要传递数组名,还要传递每一维的长度(最左一维也许可以省略,但别的不可以!!!)eg: void fk(int a[][2][3][4]){}

3. 多维数组作为参数时,数组会被改写为“数组的指针”

第十一章

c++了没什么好写的

that’s all!

上一篇:JSON扩展类——JsonHelper


下一篇:AMD64和i386的区别