《C和指针》摘抄整理型笔记

发布 2021-05-12 17:42:28 阅读 2565

/*读书笔记类型多种多样,有摘抄型的,有感想型的,有批注型的,有摘要型的……

现在正在研读《c和指针》,其中有很多我认为必要的知识点,摘抄并简单整理了一下,记录在这里。

1. 数值是以引用(reference)形式进行传递,也就是传址调用;标量和常量按值(value)传递。所有传递给函数的参数都是按值传递的,但是,数组名作为参数时就会产生按引用传递的效果。

*个人观点:数组其实是指针应用的一个特例,所以编译器没有必要去检查数组下标是否越界,当然,这也提高了编译的效率。*/

2. 不良的风格和不良的文档是软件生产和维护代价高昂的两个重要原因。在函数定义中,返回类型出现在独立一行中,而函数名则出现在下一行起始处,这样在寻找函数定义时,你可以在一行的开头处找到函数的名字。

*作者的经验,可以参考,但未必符合每个人的习惯*/

3. 数组使用方面的一个良好经验法则:如果下标值是从那些已知是正确的值计算得来,那么就无需检查它的值,如果一个用作下标的值是根据某种方法从用户输入的数据产生而来的,那么在使用它之前必须进行检测,确保它们位于有效范围之内。

4. 容易“被愚弄”的地方:

1)声明指针:

例如:int* b, c, d;

人们很自然地以为这条语句把所有三个变量都声明为指向整型的指针,但事实上星号是表达式*b的一部分,只对这个标识符有用。b是一个指针,其余两个变量c、d只是普通的整型。要声明三个指针,正确的语句是:

int *b, *c, *d;

2)声明指针并赋值:

例如: char *message = hello world”;

这条语句是指message声明为一个指向字符的指针,并用字符串常量中的第一个字符的地址对该指针进行初始化。这样的声明很容易引起误解,看上去好像初始值是赋给了表达式*message,事实上它是赋给了message本身。上面的声明相当于:

char *message;

message = hello world”;

5. 创建新的类型名,宜使用typedef而不用#define,因为后者无法正确处理指针类型,如:

#define d_ptr_to_char char *

d_ptr_to_char a, b;

正确地声明了a,但b却被声明为一个字符。如果使用typedef就会避免这个问题。

6. 常量与指针在一块使用的情况:

int const *pc; /是一个指向整型常量的指针,可修改指针的值,但不能修改它所指向的值。

int *const cp; /是一个指向整型的常量指什,此时,指针是常量,它的值无法修改,但可以修改它所指向的整型的值。

int const *const ccp; /无论指针本身还是它所指向的值,都是常量均不允许修改。

7. 对于auto变量,除了声明为const的变量外,在声明变量的同时进行初始化和声明后赋值只有风格之差,并无效率之别。

8. 当static用于函数定义时,或用于**块之外的变量声明时,static关键字用于修改标识符的链接属性,从external改为internal,但标识符的存储类型和作用域不受影响,用这种方式声明的函数或变量只能在声明它们的源文件中访问。

当用于**内部的变量声明时,static关键字用于修改变量的存储类型,从自动变量修改为静态变量,但变量的链接属性和作用域不受影响。用这种方式声明的变量在程序执行前创建,并在程序的整个执行期间一直存在,而不是每次在**块开始执行时创建,在**执行完毕后销毁。

9. for语句和while语句执行过程的区别在于出现continue语句时。在for语句中,continue语句跳过循环体的剩余部分,直接回到调整部分;在while语句中,调整部分是循环体的一部分,所以continue语句将会把它也跳过。

for循环有一个风格上的优势,它把所有用于控制循环的表达式收集在一起,放在同一处,便于寻找。

10. 跳出多层嵌套循环的方法:

1)使用goto语句,因为break语句只影响包围它的最内层循环体;

2)当希望退出所有循环时设置一个状态标志,但这个标志在每个循环中都必须进行测试;

3)把所有循环放在一个单独的函数中,当要从最内层循环跳出时,使用return语句离开这个函数。

读书笔记类型多种多样,有摘抄型的,有感想型的,有批注型的,有摘要型的……

现在正在研读《c和指针》,其中有很多我认为必要的知识点,摘抄并简单整理了一下,记录在这里。

11. 位操作技巧:

value |=1 <

value &=1 <

12. 知识点1:

if(a>5)

b = 3;

elseb = 20;

可以写成: b = a > 5 ? 3 : 20;

知识点2:sizeof(a)返回的a的长度是字节数。

*这里记录的两个知识点是最最基础的c语言点,之所以记录在这里,是因为自己的基础知识不牢固,在某次面试时被这些基础知识所虐。记录于此,起个警示作用吧*/

13. 变量的值就是分配给该变量的内存位置所存储的数值,即使是指针变量也不例外。

14. 所谓左值与右值——左值是那些能够出现在赋值符号左边的东西,右值是那些可以出现在赋值符号右边的东西。

15. 把整型值25存放在地址100的位置中:

(int *)100 = 25;

首先将100强制转换成“指向整型的指针”类型,再进行间接访问。

16. 实际上,绝大多数编译器都不会检查指针表达式的结果是否位于合法边界之内。因此,程序员应该负起责任,确保这一点。

类似,编译器将不会阻止你取一个标量变量的地址并对它执行指针运算,即使它无法**运算结果所产生的指针指向哪个变量。越界指针和指向未知值的指针是两个常见的错误根源。当你使用指针运算时,必须非常小心,确信运算的结果将指向有意义的东西。

17. 声明一个指针变量并不会自动分配任何内存。在对指针执行间接访问前,指针必须进行初始化;或者使它指向现有的内存,或者给它分配动态内存。

对未初始化的指针变量执行间接访问操作是非法的,而且这种错误常常难以检测。其结果常常是一个不相关的值被修改。这种错误是很难被调试发现的。

18. 使用函数原型最方便(且最安全)的方式是把原型置于一个单独的文件,当其他源文件需要这个函数的原型时,就使用#include指令包含这个文件。

读书笔记类型多种多样,有摘抄型的,有感想型的,有批注型的,有摘要型的……

现在正在研读《c和指针》,其中有很多我认为必要的知识点,摘抄并简单整理了一下,记录在这里。

19. 在c中,在几乎所有使用数组名的表达式中,数组名的值是一个指针常量,也就是数组第一个元素的地址。请不要根据这个事实得出数组和指针相同的结论。

只有当数组名在表达式中使用时,编译器才会为它产生一个指针常量。

20. 只有两种场合下,数组名并不用指针常量来表示——就是当数组名作为sizeof操作符或单目操作符&的操作数时。

21. 你不能使用赋值符号把一个数组的所有元素复制到另一个数组,必须使用一个循环,每次复制一个元素。

22. 定义一个数组,比如 int array[10];

表达式2[array],是合法的!编译器会把它转换成对等的间接访问表达式*(2 + array)。2[array]与*(2 + array)、array[2]是无差别的。

但在实际使用中,绝不应该写2[array],因为它会大大影响程序的可读性。

23. 数组下标表达式a[2]和指针表达式*(a + 2)可以互换。在可读性方面,下标有一定的优势,尤其是多维数组中,但下标绝不会比指针更有效率。而指针有时会比下标更有效率。

24. 指针比下标更有效率,前提是它们被正确地使用。不要为了效率上的细微差别而牺牲可读性,这点非常重要。

25. 函数原型中的一维数组形参无需写明它的元素数目,因为函数并不为数组参数分配内存空间。形参只是一个指针,它指向的是已经在其他地方分配好内存的空间。

这也解释了为什么数组形参可以与任何长度的数组匹配——它实际传递的只是指向数组第一个元素的指针。另一方面,这种实现方法使函数无法知道数组的长度,如果需要知道数组的长度,它必须作为一个显式的参数传递给函数。

26. sizeof的用途,它用于对数组中的元素进行自动计数。如,定义了array[ ]sizeof(array)的结果是整个数组所占用的字节数,而sizeof(array[0])的结果则是数组每个元素所占用的字节数。

两个值相除,结果就是数组元素的个数。

27. 头文件包含了使用字符串函数所需的原型和声明。尽管并非必需,但在程序中包含这个头文件确实是个好主意,因为有了它所包含的原型,编译器可以更好地为你的程序执行错误检查。

28. 标准库函数有时是用汇编语言实现的,目的就是为了充分利用某些机器所提供的特殊字符串操作指令,从而追求最大限度的速度,即使在没有这类指令的机器上,你最好还是把更多的时间花在程序其他部分的算法改进上。寻找一种更好的算法比改良一种差劲的算法更有效率,复用已经存在的软件比重新开发一个更有效率。

读书笔记类型多种多样,有摘抄型的,有感想型的,有批注型的,有摘要型的……

现在正在研读《c和指针》,其中有很多我认为必要的知识点,摘抄并简单整理了一下,记录在这里。

29. memxxx函数提供了类似字符串函数的功能,但它们可以处理包括nul字节在内的任意字节。这些函数都接受一个长度参数。

memcpy从源函数向目标函数复制长度参数指定的字节数。

memmove函数执行与memcpy相同的功能,但它能正确处理源参数与目标参数出现重叠的情况。

memcmp函数比较两序列的字节。

memchr函数在一个字节序列中查找一个特定的值。

C笔记整理

c 一点知识。语言基础。一 c 程序的基本组成。1.命名空间 using 命名空间名 例 using systemtext 2.类 类修饰符 class 类名 基类或接口 class program static void main string args object a定义object类型的引用...

c语言笔记整理

1.源程序 c 预处理 目标程序 obj 连接 可执行语言 exe 其中源程序是程序设计语言,其余的为机器语言。枚举类型数据。3.在字符串本身中含有双引号的用法 4.单目运算符的优先级高于双目运算符。5.三种结构 顺序结构,选择结构,循环结构。6.输出表中,要输出的数据可以是没有的。7.变量编名,字...

c语言整理笔记

以 为划分依据,分为全局变量与局部变量。例外 函数参数也是局部变量。作用域的最大单位是文件 编译的最小单位是文件 作用域的最小单位是 全局变量的作用域的文件,局部变量的作用域是 变量的作用域,始于定义处,结束预作用域结束。相同的作用域内不可以有重名的变量。当局部变量发生重名的时候,局部会覆盖全局的变...