校招即将开始,突然翻到了4年前的C语言读书笔记,放在此处做个存档吧,只是整理了当时的重点部分。
第三章 C语言基础
1.所有标识符必须以字母或下划线开头,而不能以数字或者符号开头;
2.标识符不能是关键字;
3.数据类型中基本类型包括:整型,字符型,实型(浮点型),枚举类型;结构类型包括:数组类型,结构体类型,共用体类型;
4.整形数据都是以二进制的方式存放在计算机内存中,其数值是以补码的形式进行表示的。正数的补码与其原码的形式相同,负数的补码是将该数绝对值的二进制形式按位取反再加1;
5.在字符常量中国存储的是字符的ASCII码值;
6.ASCII码:A(65) a(97) Z(90) z(122) 0(48);
7.long范围0~4294967295; unsigned long 范围 -2147483648~2147483647; 占4个字节;
8.在编写程序时,定义所有变量的步骤应该在变量的赋值之前,否则会产生错误;
9.在为单精度类型赋值时,需要在数值后面加f,表示该数字的类型是单精度类型,否则默认为双精度类型;单精度类型使用的关键字是float,他在内存中占4个字节;
10. 双精度类型使用的关键字是double,他在内存中占8个字节;
11.字符型变量在内存中占1个字节,取值范围是-128~127;
12.储存形式主要分为两大类:静态存储和动态存储。主要有自动(auto)、静态(static)、寄存器(register)和外部(extern)4种。
自动的作用是修饰一个局部变量为自动的,每次执行到定义该变量时,都会产生一个新的变量,并且对这个变量进行初始化。
寄存器的目的在于提高程序的运行速度。
static静态变量,作用域为声明变量的函数体内。static变量始终保持他的值。
extern变量称为外部存储变量。extern声明了程序种将要用到但尚未定义的外部变量。
13.const是只读变量,修饰的变量必须初始化。
14.用户态切换到内核态的3种方式:a.系统调用 b.异常 c.外围设备的中断
第四章 运算符与表达式
1.如果把较长的数值类型变量的值赋给比较短的数值类型变量,那么数据级就会降低级别表示,当数据大小超过比较短的数值类型的可表示范围时,就会发生数据截断,就如同溢出的水。需要强制类型转换。
2.取模运算符用于计算两个整数相除得到的余数,取模运算符的两侧均为整数。
3.常量和表达式不可以进行自增或自减运算。
4. “!=” 的优先级比 “=” 高。
5.判断是否为偶数 a%2==0偶数,a%2 !=0奇数
6.^异或运算符,相同为0不同为1。
7.逗号表达式
形式: 表达式1,表达式2,……,表达式n
逗号表达式的求解过程:先求解表达式1,再求解表达式2,一直求解到表达式n。整个逗号表达式n的值。逗号表达式称为顺序求值运算符。
Value = 2+5,1+2,5+7的值为7,而非12。由于赋值运算符的优先级比逗号运算符的优先级高,因此先执行赋值的运算。
如果要执行逗号运算,则可以适用括号运算符。
Value = (2+5,1+2,5+7)值为12.
第五章 常用的数据输入/输出函数
1.putchar()函数只能输出一个字符,如果要输出字符串就需要多次调用putchar()函数。
getchar()函数输入一个字符。
2.对字符串操作分别为puts()和gets()函数。puts()函数输出一个字符串后会自动进行换行。
3.scanf()在输入时以非空白字符开始,以第一个空白字符结束,字符串以空终止符“\0”作为最后一个字符。
第六章 选择结构程序设计
1.判断是否为闰年 if( (year%4==0)&&(year%100!=0) || (year%400==0) ) //是闰年
2.else总是与最近的if匹配。
3.条件运算符 表达式1?表达式2:表达式3
首先对表达式1的值进行检验,如果值为真,则返回表达式2的结果值,如果值为假,则返回表达式3的结果值。
4.switch语句检验的条件必须是一个整型表达式,这意味着其中也可以包含运算符和函数调用,而case语句检验的值必须是整型常量,也即可以是常量表达式或者常量运算。
5.多路开关模式的switch语句
#include <stdio.h>
int main()
{
int month;
printf("please enter a month:\n");
scanf_s("%d",&month);
switch(month)
{
case 3:
case 8:
case 10:
printf("%d is spring\n",month);
break;
case 1:
case 7:
case 2:
printf("%d is summer\n",month);
break;
case 5:
case 4:
case 11:
printf("%d is autumn\n",month);
break;
case 6:
case 9:
case 12:
printf("%d is winter\n",month);
break;
default:
puts("error!!\n");
break;
}
return 0;
}
第七章 循环控制
1.for语句的执行顺序
2.输出金字塔形
#include <stdio.h>
int main()
{
int i; //有几行
int j; //有几个空格
int k; //有几个*
for (i=1;i<=5;i++) //1-5行
{
for(j = 1;j <= 5-i;j++) //每行*前面有5-i个空格
{
printf(" ");
}
for (k = 1;k <= 2*i-1;k++) //每行有2i-1个空格
{
printf("*");
}
printf("\n");
}
getchar();
return 0;
}
3.有时会遇到这样的情况,不顾表达式检验的结果而强行终止循环,这时可以使用break语句。break语句的作用是终止并跳出循环。如果遇到循环嵌套的情况,break语句将只会使程序流跳出包含它的最内层的循环结构。
#include <stdio.h>
int main()
{
int iCount;
for(iCount=0;iCount<10;iCount++)
{
if (iCount==5)
{
printf("Find a true friend\n");
break;
}
printf("Friend %d\n",iCount);
}
return 0;
}
4.在某些情况下,程序需要返回到循环头部继续执行,而不是跳出循环,此时可以使用continue语句。
第八章 数组
1.使用格式符“%s”将字符串进行输出,需要注意以下几种情况:
(1)输出字符不包括结束字符“\0”
(2)如果数组长度大于字符串实际长度,则也只能输出到“\0”为止
(3)如果一个字符数组中包含多个“\0”结束字符,则在遇到第一个“\0”时就结束。
2. 堆和栈的举例:
使用栈就像我们去饭馆里吃饭,只管点菜(发出申请),付钱和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但自由度较小。
使用堆就像是自己动手做喜欢吃的菜,比较麻烦,但是比较符合自己的口味,而且自由度大。
3.strcpy
该函数的功能是把源字符数组中的字符串复制到目的字符数组中。字符串结束标志“\0”也一同复制
- 目的字符数组应该有足够的长度,否则不能全部装入所复制的字符串。
- “目的字符数组名”必须写成数组名形式;而“源字符数组名”可以是字符数组名,也可以是一个字符常量,这时相当于把一个字符串赋予一个字符数组。
- 不能用赋值语句将一个字符串常量(初始化字符数组除外)或字符数组直接赋给一个字符数组。
4.strupr(字符串)将字符串中的小写字母转换成大写字母;strlwr(字符串)将字符串中的大写字母转换成小写字母。
第九章 函数
1.return语句后面需要有返回值,该返回值可以用小括号括起来,也可以省略括号,例如return 0和return (0)是相同的。
2.在运行程序时,有时需要将必要的参数传递给主函数。主函数main的形式参数如下:
main(int argc, char *argv[])
两个特殊的内部形式参数argc和argv是用来接收命令行实际参数的,这是只有主函数main具有的参数。
argc参数保存命令行的参数个数,是整形变量。这个参数的值至少是1,是因为至少程序名就是第一个实际参数。
argv参数是一个指向字符数组的指针,这个数组中的每一个元素都指向命令行实际参数。所有命令行实际参数都是字符串,任何数字都必须由程序转变成为适当的格式。
第十一章 结构体与链表
1.结构体一般形式:
struct 结构体名
{
成员列表
};
结构体名表示该结构的类型名
2.引用结构变量成员的一般形式为:结构变量名.成员名
在引用结构的成员时,可以在结构的变量名的后面加上成员运算符“.”和成员的名字。
3.结构体中char name[20],要用strcpy()赋值;
结构体中char * name,要用a.name = “ ”赋值。
(字符数组的赋值要用strcpy函数,不能直接用赋值操作赋值)
4.(1) pStruct->iGrade++,表示指向的结构体变量中成员iGrade的值,使用后该值加1;
(2) ++pStruct->iGrade,表示指向的结构体变量中成员iGrade的值加1,计算后再使用。
第十三章 位运算
- 位是计算机存储数据的最小单位。
- 1个字节8bit。
- 运算所需变量为两个的运算符叫做双目运算符·或者要求运算对象的个数是2的运算符称为双目运算符。eg. a+b
单目运算符是运算所需变量为一个的运算符,又叫一元运算符。eg. !a。 - 异或:相同为0,不同为1。
- 异或操作的一个主要用途是使特定位翻转(P319)。
- 左移一位相当于该数乘以2,右移一位相当于该数除以2。
- 在进行右移时对于符号数需要注意符号位问题,当为正数时,最高位补0;而为负数时,最高位是补0还是补1取决于编译系统的规定,移入0的称为“逻辑右移”,移入1的称为“算术右移”。
- 实现循环左移:
z >> (32-n);
y = x << n;
y = y | z;
- 实现循环右移:
z << (32-n);
y = x>>n;
y = y | z;
- 位段类型是一种特殊的结构类型,其所有成员的长度均是以二进制位为单位定义的,结构中的成员被称为位段。
一个位段必须被说明是int, unsigned或signed中的一种。
一个位段必须存储在一个存储单元(通常为一字节)中,不能跨两个存储单元。如果本单元不够容纳某位段,则从下一个单元开始存储该位段。
可以用%d,%x,%u和%o等格式字符,以整数形式输出位段。
在数值表达式中引用位段时,系统自动将位段转换为整型数。
第十四章 预处理
- 如果在字符串中含有宏名,则不进行替换。
- 宏名的有效范围为定义命令之后到此源文件结束。
- 可以用#undef命令终止宏定义的作用域。 格式: #undef 宏替换名
- 宏定义用于预处理命令,它不同于定义的变量,只作字符替换,不分配内存空间。
- 用宏替换代替实在的函数的一个好处是宏替换增加了代码的速度,因为不存在函数调用。但由于重复编码从而增加了程序长度。
- 对于带参数的宏定义需要强调:宏定义时参数要加括号,如不加括号,则有时结果果时正确的,有时结果却是错误的。
- 头文件用双引号或尖括号括起来,两者之间的区别是,用尖括号时,系统到存放C库函数头文件所在的目录中寻找要包含的文件,这为标准方式;用双引号时,系统先在用户当前目录中寻找要包含的文件,若找不到,再到存放C库函数头文件所在的目录中寻找要包含的文件。
- 用户自己编写的文件通常是在当前目录中,如果文件不在当前目录中,双引号可给出文件路径。
- 条件编译
一般情况下,源程序中所有行都参加编译,但是有时希望只对其中一部分内容在满足一定条件时才进行编译,这时就需要使用一些条件编译命令。
(1)#if命令
如果#if命令后的参数表达式为真,则编译#if到#endif之间的程序段,否则跳过这段程序。#endif用来表示#if段的结束。
#if 常数表达式
语句段
#endif
(2)#elif命令
相当于elseif
10.#ifdef及#ifndef命令,分别表示“如果有定义”及“如果无定义”
#ifdef 宏替换名 #ifdef 宏替换名
语句段 语句段1
#endif #else
语句段2
#endif
含义:如果宏替换名已被定义过,则对“语句段”进行编译;如果未定义#ifdef后面的宏替换名。则不对语句段进行编译;
如果宏替换名已被定义过,则对“语句段1”进行编译;如果未定义#ifdef后面的宏替换名,则对“语句段2”进行编译。
#include <stdio.h>
#define STR "Believe Yourself\n"
int main()
{
#ifdef STR
printf(STR);
#else
printf("**Don't give up**\n");
#endif // STR
printf("\n");
#ifndef ABC
printf("Don't give up\n");
#else
printf(STR);
#endif
return 0;
}
11.#pragma命令的作用是设定编译器的状态,或者指示编译完成一些特定的动作。
#pragma 参数
参数可以分为以下几种:
message参数能够在编译信息输出窗口中输出相应的信息。
code_seg参数设置程序中函数代码存放的代码段。
once参数保证头文件被编译一次。
第十五章 文件
- 如果使用fopen()函数打开文件成功,则返回一个有确定指向的FILE类型指针;若打开失败,则返回NULL。通常打开失败的原因有以下几方面:
指定的盘符或路径不存在;
文件名中含有无效字符;
以r模式打开一个不存在的文件。
2.当正常完成关闭文件操作时,fclose()函数返回值为0,否则返回EOF。