《C与指针》个人笔记

容易忘记的点

  1. 函数不显式地声明返回值的类型就默认返回整型。
  2. 使用typedef而不是#define来创建新的类型名,后者无法正确处理指针类型。
  3. int const a;和const int a没有区别;int const *p一个指向整型常量的指针;int *const p一个指向整型的常量指针
  4. 如果内层代码块有一个标识符的名字与外层代码块的一个标识符同名,内层的那个标识符就将隐藏外层的标识符,即外层的那个标识符无法在内层代码块中通过名字来访问。
  5. switch()其括号内的结果必须是整型值。P57。(此处整型值包括char型)。
  6. sizeof (int);sizeof x;sizeof的操作数可以是个表达式(常常是单个变量),也可以是两边加上括号的类型名。是个数组名时返回数组长度。均以字节为单位。判断表达式的长度并不需要对表达式进行求值,如sizeof(a=b+1)并没有向a赋任何值。
  7. 不能简单通过检查一个值的位来判断它的类型;值的类型并非值本身所固有的一特性,而是取决于它的使用方式。如以浮点值3.14存储,用整型读取其值可能为1078523331(基于处理器的不同)。
  8. 对于一些机器,对NULL指针进行间接访问会访问内存位置零。在对指针进行解引用操作之前,必须确保它并非NULL指针。
  9. 越界指针和指向未知值的指针是常见的错误根源。
  10. 标准允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针(再往后就不合法了)进行比较(但不应该对这个指针进行间接访问操作),但不允许与指向数组第1个元素之前的那个内存位置的指针进行比较。
  11. 一个没有参数的函数原型应该写成:int *func(void);关键字void提示没有任何参数。原因:int *fun();它既可以看作是一个旧式风格的声明(只给出func函数的返回类型),也可以看作是一个没有参数的函数新的新风格原型。这个声明必须被解释为旧式风格的声明,目的是保持与ANSI标准之前的程序的兼容性。
  12. 在声明数组参数时不指定它的长度是合法的,因为函数并不为数组元素分配内存。间接访问操作将访问调用程序中的数组元素。
  13. ADT(abstract data type)和黑盒设计:模块具有功能说明和接口说明,除了那些定义好的接口外,用户不能以任何方式访问模块;限制对模块的访问是通过static关键字的合理使用实现的。P124 。
  14. P134 关于可变参数列表,一个类型va_list和三个宏va_start、va_arg和va_end
    void average(int number, ... )
    {
    va_list value;//定义一个变量
    va_start(value, number);//初始化
    a = va_arg(value, int);//取第一个值
    b = va_arg(value, int);//取第二个值
    va_end(value);//结束
    }
  15. 如果一个递归内部所执行的最后一条语句就是调用自身时,则被称为尾部递归。尾部递归可以很容易地改写为循环的形式,而且通常效率更高。
  16. 除了优先级之外,下标引用和间接访问完全相同。array[0]等同*(array+0)。array[-1]使用偏移量-1可得到它的前一个元素。
  17. comst修饰指向字符指针的形参的3个好处:可读性;编译器可捕捉到任何试图修改该数据的意外错误;这类声明允许向函数传递const参数
  18. 在许多机器上,register变量所产生的代码将比静态内存中的变量和堆栈中的变量所产生的代码执行速度更快;许多当前的编译器比程序员更加懂得怎样合理分配寄存器。
  19. 只有存储于全局区(静态区)的数组才会被自动初始化为0;为一个数组提供部分初始值,后面的元素则初始化为0。
  20. char msg1=”hello”;char *msg2=”hello;前者初始化一个字符数组的元素,后者是一个字符串常量。
  21. int matrix[3][10], (*p)[10]=matrix;//p是一个指向拥有10个整型元素的数组的指针,p与一个整数相加时,该整数值根据10个整型值的长度进行调整;int *pi=&matrix[0][0]等同于int *pi=matrix[0];//指向matrix的第1个整型元素。
  22. 单目操作符&返回一个指向数组的指针,而不是一个指向数组第1个元素的指针的指针。
  23. 标准保留了所有以str开关的函数名,用于标准库将来的扩展。
  24. strlen返回一个类型为size_t的值。这个类型是在头文件stddef.h中定义的,它是一个无符号整数类型。在表达式中使用无符号数可能导致不可预料的结果。比如这两个看上去相等的表达式:if(strlen(x)>=strlen(y))…和if(strlen(x)-strlen(y)>=0)…第2条语句的结果将永远为真,无符号数绝不可能是负的。如果把strlen的返回值强制转换为int,就可以消除这个问题。
  25. 查找标记strtok函数保存它所处理的函数的局部状态信息,所以不能用它同时解析两个字符串。
  26. memcmp对两段内存的内容按照无符号逐字节进行比较,所以如果memcmp函数用于比较不是单字节的数据如整数或浮点数时就可能给出不可预料的结果。
  27. strncpy中,长度指定了多少个字符将被写入到目标字符数组中,如果源字符串比指定长度更长,结果字符串将不会以一个NUL字节结尾。
  28. 相同类型的结构变量相互之间可以赋值。P195。这两个声明被编译器当作截然不同的类型,即使它们的成员列表完全相同,故z=&x是非法的。P196。即不同的结构声明即使它们的成员列表相同也被认为是不同的类型。P214
  29. 点操作符的优先级高于间接访问操作符。->操作符的优先级高于&操作符的优先级。->操作符的左操作数必须是一个指向结构的指针。
  30. 编译器为一个结构变量的成员分配内存时要满足它们的边界对齐要求;根据边界对齐要求降序排列结构成员可以最大限度地减少结构存储中浪费的内存空间;系统禁止编译器在一个结构的起始位置跳过几个字节来满足边界对齐要求,因此所有结构的起始存储位置必须是结构中边界要求最严格的数据类型所要求的位置。
  31. offsetof(type,member)宏返回一个size_t值,表明这个member开始存储的位置距离结构开始存储的位置偏移几个字节。P206 eg:offsetof(struct ALIGN,b)。
  32. 位段成员必须声明为int、signed int、unsigned int类型。位段在不同的系统中可能有不同的结果,降低了可移植性,原因:1.int位段被当作有符号数还是无符号数。2.位段中位的最大数目。许多编译器把位段成员的长度限制在一个整型值的长度之内。3.位段中的成员在内存中是从左向右分配的还是从右向左分配的。4.当一个声明指定了两个位段,第2个位段比较大,无法容纳于第1个位段剩余的位时,编译器有可能把第2个位段放在内存的下一个字,也可能直接放在第1个位段后面,从而在两个内存位置的边界上形成重叠。
  33. 联合的长度就是它最长成员的长度。联合变量可以被初始化,但这个初始值必须是联合第1个成员的类型,而且它必须位于一对花括号里面。
  34. 符号NULL定义于stdio.h,实际上是字面值常量0,起着视觉提醒器的作用,提醒我们进行测试的值是一个指针而不是整数。
  35. pi=malloc(25*sizeof(int));即使是在整数长度不同的机器上,它也能获得正确的结果。
  36. 常见的动态内存错误:包括对NULL指针进行解引用操作、对分配的内存进行操作时越过边界、释放并非动态分配的内存、试图释放一块动态分配的内存的一部分以及一块动态内存被释放之后被继续使用、忘记检查所请求的内存是否成功分配、内存泄漏。
  37. qsort(array,n_values,sizeof(int),compart_integers)排序函数
  38. 非法表达式:int f()[];函数只能返回标量值,不能返回数组;int f;数组元素必须具有相同的长度,但不同的函数显然可能具有不同的长度;合法表达式:int (*f[])(); f是一个元素为函数指针类型的指针的数组。
  39. P265 int main(int argc,char **argv);argc表示命令行参数的数目,argv指向数组的第1个元素,第1个参数是程序的名称。
  40. 预定义符号:FILE LINE DATE TIME STDC、# ##连接,必须产生一个合法的标识符,否则其结果是未定义的。P279
  41. 第15章、第16章
  42. 如果函数体内没有任何语句,那么该函数就称为存根。
  43. 树、二叉树、二叉搜索树
  44. 不同的编译器可能具有不同的堆栈帧约定或者在函数的调用和返回上使用不兼容的协议,因此,在通常情况下,你不能使用不同的编译器编译同一个程序的不同片段。P402
  45. 学习机器的运行时环境既有益处又存在危险。说它有用是因为获得的知识允许你做一些其他方法无法完成的事情,说它危险是因为程序中如果存在任何依赖于这方面知识的东西,可能会损害程序的可移植性。
  46. scanf里面不要加\n

没看懂

  1. 隐式类型转换: a=(~a^b<<1)>>1,由于存在求补和左移操作,所以8位的精度是不够的。标准要求进行完整的整型求值,所以对于这类表达式的结果,不会存在歧义性。 P80
  2. 如果x+y溢出,则(有些机器)if(x+y+1>0)的结果将取决于先计算x+y还是y+1,因为这两种情况下溢出的地点不同。P84
  3. “flattening the array”压扁数组,它实际上是非法的,因此从某行移到下一行后就无法回到包含第1行那个子数组?P155
  4. 一个指向整型指针的指针和指向整型数组的指针并不是一回事。P160;P105-P107
  5. P167 问题1 &ints+4答案应该错了
  6. 结构体:不完整的声明。看不懂也不知道有哪些地方需要这种相互之间存在依赖的结构。P199
  7. P233 while(scanf(*%d*,&i)==)) arry[i]+=1;一头雾水
  8. P272 13.9问题1 e.h.j.k.l.m;一脸懵逼,答案是不是错了一两个
  9. 同优先级的情况下符号的结合性。
  10. 第15章输入输出函数:有一些是认识的,有一些却很陌生;第16章标准函数库:一大堆函数;这两章不想整理了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值