重读C Primer Plus ,查漏补缺

  重读C Primer Plus,记录遗漏的、未掌握的、不清楚的知识点

文件输入/输出

  1、fgets函数在读取文件内容时会将换行符读入,但gets不会,fputs函数在写入文件时不会追加一个换行符,但puts会,应该对应配合使用。

  2、不同操作系统下,以文本方式打开文件,几乎没有区别,但由于不同操作系统文件结尾的的标识符不同,以二进制方式打开时,可能会将结尾标识符错误输出。

  3、对于大型文件,有两个特殊的函数提供支持:

 int fgetpos(FILE * restrict stream, fpos_t * restrict pos);
int fsetpos(FILE * stream, const fpos_t *pos);

  其中,fpos_t是通过其他类型定义的文件定位类型,在使用上述函数时,fsetpos中的pos必须是通过fgetpos函数获得的。当两个函数执行成功时,会返回0。

  4、其他标准IO函数

 size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb, FILE* restrict fp);
size_t fread(void * restrict ptr, size_t size, size_t nmemb, FILE* restrict fp);
// 是否到达文件结尾
int feof(FILE* fp);
// 是否发生读写错误
int ferror(FILE* fp);
// 将字符回流进缓冲区
int ungetc(int c, FILE* fp)
// 立刻将缓冲区内容写入文件
int fflush(FILE* fp)
// 替换缓冲区
int setvbuf(FILE* restrict fp, char * restrict buf, int mode, size_t size)

  当然,上述的一些函数在目前的VS Studio中会被认为是不安全的函数,已经过时。

  

结构和其他数据格式

  5、C99标准下支持对结构体初始化时的任意字段赋值:

 struct book gift = {.value=25.99, .author="Harry Potter", .title="Yoo"};
// 此时 0.25 会被赋给定义结构体时author后的那个成员,即便那个成员已经被初始化过。
struct book gift = {.value=25.99, .author="Harry Potter", 0.25};

  6、对于结构体数组,数组名不是其首个元素的地址,需要引用首个元素再取地址。

  7、在结构中一般使用字符数组,而不使用字符指针,结构中的字符指针无法很好的初始化地址,这样会有使用上的风险,所以结构中的字符指针最好只指向那些字符串常量或者是指向由malloc分配的内存。

  8、C99标准对结构也支持复合文字,同时复合文字的结构也可以作为函数参数,也可以取地址,也和普通变量有相同的生存周期,声明方式如下:

 (struct book) {"The Idiot", "Fyodor Dostoyevsky", 6.99}

  9、C99支持一种伸缩型数组成员,这个成员必须是结构中最后一个成员,而且不是唯一一个成员,就像声明普通数组一样,但括号内为空,这个成员不会在声明后立即存在,实际上,C99希望使用malloc为这样含有伸缩型成员的数组分配空间。

 struct flex{
int count;
double avreage;
double scores[]; // 伸缩型成员
}
struct flex * pf;
pf = malloc(sizeof(struct flex) + *sizeof(double))
pf->count = ;
pf->scores[] = 2.99;

  10、对于C中的枚举类型,某些属性不能顺延至C++,例如C允许对枚举做++运算,但C++不允许。

 enum spectrum {red, yellow, green, blue};
spectrum color;
for(color = red; color != blue; color++);

  11、在C中,对于同一作用域下的标记和变量名可以使用同一个名字,因为对于标记(枚举、结构,联合),他们使用的名字空间与普通变量不同,但C++中不可以,例:

 struct complex{double x, double y};
int complex; // 在C中不会引起冲突,但C++中则不允许

  12、对于函数指针执行函数时,会出现两种语法,ANSI C把他们视为等价的。

 void ToUpper(char *);
void (*pf) (char*);
char str[] = "hello";
pf = ToUpper;
(*pf)(str); // 语法1
pf(str); // 语法2

  

位操作

  13、为什么一个字节可以表示的有符号整数的范围是-128~+127?

  看这里:https://www.cnblogs.com/Dylan7/p/12649972.html

  14、计算机中小数是如何表示的?(一部分表示指数,一部分表示小数,有精确度问题)

  15、对位进行操作的第二种方法就是位字段(从没用过,细节可以用到时再研究),位字段好比一个结构体,但其中的成员,代表的是某几位上的值,好处是避免了通过复杂的位运算去控制某些位上的值,声明例如:

 struct box
{
unsigned int opaque : // 整体结构的对齐补齐依据无符号整型
unsigned int fill_color : // 数字代表需要几位来表示这个字段
unsigned int : // 可以跳过一些位
unsigned int show_border : // 但一个字段不能横跨两个无符号整型的边界
}
struct box b;
b.fill_color = ; // 不可以超过字段所占用的位可表示的上限

  

C预处理器和C库

  16、程序翻译的第一步,在预处理前,编译器会对代码做一些翻译,将代码中出现的字符映射到源字符集(用来处理多字节字符和使C外观更加国际化的三元字符扩展),接着查找反斜杠后紧跟换行符的实例,将其转换为一行,然后将文本划分为预处理的语言符号序列以及空白字符及注释序列(将用一个空格代替一个注释),最后进入预处理阶段,寻找每一个预处理指令。

  17、 几个宏定义

 #define F(x) #x      // #将语言符号字符串化
#define F(x) F##x // ##将两个语言符号组成一个语言符号
#define F(x,...) printf("x", __VA_ARGS__) // ...和__VA_ARGS__,可变参数(必须为最后一个参数)

  18、#if 指令后面跟常量整数表达式,可以与 #elif 配合使用,例如:

 #if 1 == SYS
...
#elif 2 == SYS
...
#endif

  同时,还有以下新的实现方式,defined 是一个预处理运算符,如果参数使用#define定义过,defined返回1,否则返回0。

 #if defined(INMPC)
...
#elif defined(VAX)
...
#endif

  19、#line 用于重置__LINE__,__FILE__宏所报告的行数

    #error 指令使预处理器可以发出一条错误信息

 #line 10000
#line 10 cool.c"
#if __STD_VERSION__ != 199901L
#error Not C99
#endif

  20、C99 提供了_Pragma预处理器运算符,可以将字符串转换成常规的编译指示

 _Pragma("c99 on") 等价于
#pragma c99 on

  21、内联函数不会在调试器中显示,例如使用gdb调试时,有些内联函数无法被手动执行,同时内联函数具有内部链接属性,所以在多文件程序中,使用其他文件的内联函数时,要单独声明一次,并且在尝试获 取内联函数的地址时,编译器都会产生非内联函数,也就是说可能产生外部定义的函数。

  23、在main()函数结束时,会隐式地调用exit()函数,同时,可以通过atexit()函数,向exit()注册在程序允许结束时执行的函数,ANSI C保证可以设置至少32个函数,按照先设置后执行的顺序执行,atexit()函数接受一个返回值为void,参数也为void的函数指针作为唯一参数。

  24、memcpy()与memmove()两个函数的区别在于声明上,以及memcpy()会假定两个内存区没有重叠。

 void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
void *memmove(void *s1, void *s2, size_t n);

  25、可变参数的相关内容包含在stdarg.h头文件中,使用起来比较复杂,包括初始化可变参数列表,遍历列表,清理列表,拷贝列表等一系列操作,需要时再研究。

高级数据表示

  26、 这章没什么新奇内容,但它告诉我们,用C可以实现很多复杂的数据结构。

  2020年4月16日,星期五,晚23点09分,首次完整读完这本书,共勉。

  学如逆水行舟,不进则退;心似平原放马,易纵难收。

C Primer Plus(三)的更多相关文章

  1. 如何学习C++? C++ Primer第三版中文版

    C++只是一门工具,要在实际项目中才能感受到它的伟大.是慢慢积累的(任何知识都是,冰冻三尺非一日之寒),它的思想是慢慢领悟的. 知道它的语法不代表你会用,你会用不代表你就会建造起高水平的作品,这是一个 ...

  2. C++Primer 第三章

    //1.位于头文件中的代码一般不应该使用using声明.这是因为头文件的内容会拷贝到所有引用它的文件中,可能会产生始料未及的命名空间冲突. // 三种使用命名空间中的名字的方法 using names ...

  3. C++ Primer 第三章 标准库类型vector+迭代器iterator 运算

    1.vector: 标准库类型vector表示对象的集合,其中所有对象的类型都相同,集合中的每个对象都有一个与之对应的索引,索引用于访问对象.因为vector“容纳着”其他对象,所以它也常被称作容器( ...

  4. C++primer第三章标准库类型

    除第二章介绍的基本数据类型外,C++ 还定义了一个内容丰富的抽象数据类型标准库. 本章将介绍标准库中的 vector.string 和 bitset 类型. string 类型支持长度可变的字符串 v ...

  5. C++ Primer 第三章 标准库类型string运算

    1. 标准库类型 string string表示可变长的字符序列,使用string必须首先包含string头文件.如何初始化类的对象是由类本身决定的. int n; string s1;//默认初始化 ...

  6. C++ primer第三章作业

    3.1节 练习3.1: 使用恰当的using声明重做1.4.1节(第11页)和2.6.2节(第67页)的练习 #ifdef 1 #include <iostream> using std: ...

  7. c++primer 第三章编程练习答案

    3.7.1 #include<iostream> int main() { using namespace std; ; int height,inch,foot; cout <&l ...

  8. c++ primer 第三章 标准库类型

    1. string 标准库 1.1初始化 string s1; 默认构造函数s1为空 string s2(s1); 将s2初始化为s1的一个副本 string s3("value" ...

  9. <<C++ Primer>> 第三章 字符串, 向量和数组 术语表

    术语表 第 3 章 字符串, 向量和数组 begin: 是 string 和 vector 的成员,返回指向第一个元素的迭代器.也是一个标准库函数,输入一个数字,返回指向该数字首元素的指针.    缓 ...

  10. C++ Primer 笔记 第三章

    C++ Primer 第三章 标准库类型 3.1using声明 例: using namespace atd; using std::cin; 3.2string类型 初始化方式 string s1 ...

随机推荐

  1. 解析webpack插件html-webpack-plugin

    前言: 本文将分为基本概念.基础使用.模块的运用(问题解决)来进行阐述. 一.基本概念 我们为什么会需要HtmlWebpackPlugin插件? 在真实发布项目时,发布的是dist文件夹中的内容,但是 ...

  2. PAT-1134 Vertex Cover (图的建立 + set容器)

    A vertex cover of a graph is a set of vertices such that each edge of the graph is incident to at le ...

  3. 4、Servlet中的Cookie 用于存储 web 页面的用户信息。

    Servlet Cookie 处理 Cookie 是存储在客户端计算机上的文本文件,并保留了各种跟踪信息.Java Servlet 显然支持 HTTP Cookie. 识别返回用户包括三个步骤: 服务 ...

  4. 剑指Offer之跳台阶

    题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). 解法1:递归解法 public int JumpFloor(int t ...

  5. Leetcode 416分割等和子集

    416. 分割等和子集 已知是个背包问题,由于可以等分为两部分,所以必定是个偶数. 一开始想到的是回溯法 bool helper(vector<int>&nums, int i, ...

  6. Linux系统部署JavaWeb项目(超详细tomcat,nginx,mysql)

    转载自:Linux系统部署JavaWeb项目(超详细tomcat,nginx,mysql) 我的系统是阿里云的,香港的系统,本人选择的是系统镜像:CentOS 7.3 64位. 具体步骤: 配置Jav ...

  7. ASP.NET Core Blazor Webassembly 之 数据绑定

    上一次我们学习了Blazor组件相关的知识(Asp.net Core Blazor Webassembly - 组件).这次继续学习Blazor的数据绑定相关的知识.当代前端框架都离不开数据绑定技术. ...

  8. 小谢第8问:ui框架的css样式如何更改

    目前有三种方法, 1.使用scss,增加样式覆盖,但是此种方法要求css的className需要与框架内的元素相一致,因此修改时候需要特别注意,一个父级的不同就可能修改失败 2.deep穿透,这种方法 ...

  9. Chisel3 - 使用chisel-iotesters进行验证

    https://mp.weixin.qq.com/s/KqyklKrPLtPm38sftMYlHA   1. 使用Maven获取库   Chisel相关的库基本上都可以使用Maven获取到(https ...

  10. Java实现 LeetCode 20 有效的括号

    20. 有效的括号 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合. 左括号必须以正确的顺序闭合. ...