基础
程序结构是三种: 顺序结构, 选择结构(分支结构), 循环结构.
读程序都要从 main()入口, 然后从最上面顺序往下读(碰到循环做循环, 碰到选择做选择), 有且只有一个 main 函数.
计算机的数据在电脑中保存是以二进制的形式. 数据存放的位置就是他的地址.
bit 是位, 指为 0 或 1.byte 是指字节, 一个字节 = 八个位.
常考
编译预处理不是 C 语言的一部分, 不占运行时间, 不要加分号.
C 语言编译的程序称为源程序, 它以 ASCII 数值存放在文本文件中.
define PI 3.1415926; 这个写法是错误的, 一定不能出现分号.
每个 C 语言程序中 main 函数是有且只有一个.
在函数中不可以再定义函数.
算法: 可以没有输入, 但是一定要有输出.
break 可用于循环结构和 switch 语句.
逗号运算符的级别最低, 赋值的级别倒数第二.
int *p 中 *p 和 p 的差别: 简单说 * p 是数值, p 是地址!
*p: 可以当做变量来用;* 的作用是取后面地址 p 里面的数值.
p: 是当作地址来用. 可以用在 scanf 函数中: scanf("%d",p);
*p++ 和 (*p)++ 的之间的差别:(笔试重点)
*p++: 是地址会变化.
口诀: 取当前值, 然后再移动地址!
(*p)++: 是数值会要变化.
口诀: 取当前值, 然后再使数值增加 1.
例题: int *p,a[]={1,3,5,7,9};
p=a;
请问 * p++ 和(*p)++ 的数值分别为多少?
*p++: 这个本身的数值为 1. 由于是地址会增加一, 所以指针指向数值 3 了.
(*p)++: 这个本身的数值为 1. 由于 ++ 表示数值会增加, 指针不移动, 但数值 1 由于自加了一次变成了 2.
二级指针:
*p: 一级指针: 存放变量的地址.
**q: 二级指针: 存放一级指针的地址.
常考题目: int x=7;int*p=&x,**q=p;
问你:*p 为多少?*q 为多少?**q 为多少?
*p=7,*q=p,**q=7
再问:**q=&x 的写法可以吗? 不可以, 二级指针只能存放一级指针的地址.
程序进行编译时, 并不为形式参数分配存储穿间. 只有在被调用时, 形式参数才临时地占有存储空间. 形式参数用关键字 auto 作存储类别的声明时, 关键字 "auto" 可以省略, auto 不写则隐含确定为 "自动存储类别", 它属于动态存储方式.
函数的存储类型是函数定义时函数名前面的数据类型前面的存储类型, 缺省时应该是: extern, 表示该函数属外部函数(即 可以被本 C 文件外的其他 C 源程序文件中的函数调用)
extern:
对整个工程可见, 其他文件可以使用 extern 外部声明后直接使用. 也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)
static: 代表静态全局
仅对当前文件可见, 其他文件不可访问, 其他文件可以定义与其同名的变量, 两者互不影响.
重点
strlen 和 sizeof 的区别(重点):
sizeof:(求实际存储空间)
相当于是个宏一样的东西, 因为它只是一个运算符, 而不是函数, 编译时展开为常数, 编译的时候有每个变量的定义表, sizeof 通过查表确定变量占用的空间, 这是分配内存给 process 之前要确定的.
其实可以简单的理解 sizeof 是针对 "类型" 的, 而非 "变量", 但此时不能这样看如: sizeof("HELLO"); 中括号中为 const char *, 而是一个 "字符串", 所以结果大小为 5. 但:
- char *ps = "HELLO";
- sizeof(ps) = 4 // 只是指针的大小, 即 地址(整数类型占 4 个字节)
- sizeof(*ps) = 1 //*ps+0 代表数组第一个元素的大小, 即 ps[0]
- char as[8];
- sizeof(as) = 8 // 因为 as 的类型为 char [8], 这个大小的确是 8
- sizeof(*as) = 1 //*as+0 代表数组第一个元素的大小, 即 as[0]
- char aa[8][9];
- sizeof((char *)aa) = 4 // 还是 char *
- char arr[100] = "HELLO";
- sizeof(arr) = 100 // 和赋什么值没什么关系, 关键是 "类型" 是什么
- int func(char p[100]) {
- sizeof(p) = 4;
- /*C/C++ 中不能传数组, 只能传指针, 所以任何数组都会隐式转成指针形式进行操作.*/
- }
- strlen:(求字符串长度, 即 字符个数, 不包括结束符)
它是一个函数, 参数是 const char*, 搞清楚它的实现, 就是碰到'\0'(字符串结尾, 就停止计数, 但不包括'\0'). 所以它不是看类型而是看变量, 取决于变量赋的什么值.
函数的递归一定会考.
两种重要的数组长度:
char a[]={'a','b','c'}; 数组长度为3, 字符串长度不定 (因为没有'\0'结束符).sizeof(a) 为3.
char a[5]={ 'a','b','c'}; 数组长度为5, 字符串长度3.sizeof(a)为5.
char a[]={'a','b','c'}; 这是一个字符数组, 占 3 个字节.
char a[]="abc" 则不同, 它是一个字符串, 最后还有一个'\0'结束符, 占 4 个字节.
scanf 和 gets 的区别:
如果输入的是 good good study!
scanf("%s",a);
只会接收 good. 考点: 不可以接收空格.(遇到空格或回车就终止)
gets(a);
会接收 good good study! 考点: 可以接收空格.(遇到回车终止)
指针考点:
- char ch[]="iamhandsome";
- char *p=ch;
问你:*(p+2) 和 *p+2 的结果是多少?
*(p+2) = 'm' *p+2 = 'k'
解析:
第一个是地址 + 2, 所以取 m;
第二个则是数值 + 2, 即 ASCII 码值 + 2,ijk, 所以取 k.
字符串的赋值:
C 语言中没有字符串变量, 所以用数组和指针存放字符串:
char ch[10]={"abcdefgh"}; 对
char ch[10]="abcdefgh"; 对
char ch[10]={'a','b','c','d','e','f','g','h'}; 对
char *p="abcdefgh"; 对
char *p; 对
ch="abcdefgh"; 错! 数组名不可以赋值!(只能一个一个循环赋值)
char *p={"abcdefgh"}; 错! 不能够出现大括号!
宏定义 defind
问题:#define f(x)(x*x) 和 #define f(x) x*x 之间的差别.
define 是 C 语言中的宏定义关键字, 其定义格式如下:
#define [MacroName] [MacroValue]宏定义分为普通宏定义和带参数的宏定义
普通宏定义:#define PI (3.1415926)
带参数的宏定义 (宏函数):#define max(a,b) ((a)>(b)? (a),(b))
注意: 变量在宏中要用括号括起来.
因为, 在 C 语言中 define 宏定义在编译时, 会被展开, 进行 "傻瓜式" 替换, 也称为 "字面" 替换, 如果没有括号有可能会产生歧义.
如:
- int a,b,c,d,e;
- a=1;b=2;c=6;d=4;
- e=f(a+b) * f(c+d) ; // 理论值 e=9*100=900
- #define f(x)(x*x)
替换结果为: e=(a+b*a+b)*(c+d*c+d) = 5*34=170
#define f(x) x*x
替换结果为: e=a+b*a+b*c+d*c+d=1+2+12+24+4=43
#define f(x) ((x)*(x))
替换结果为: e=( (a+b)*(a+b)*(c+d)*(c+d) )=3*3*10*10=900
这个才是我们想要的结果!
来源: https://www.cnblogs.com/blknemo/p/12174011.html