1.关键字、标示符、注释
1)关键字都是小写的
auto break case char const continue
default do double else enum extern
float for goto if int long register return
short signed sizeof static struct switch
typedef union unsigned void volatile while
_Bool _Complex _Imaginary
2)标示符
标示符命名规则:
(1)只能由字母(区分大小写)、数字、下划线组成;
(2)必须以字母或下划线开头;
(3)不可以是C保留字或C库函数名。
3)注释
多行注释,或段注释,可以出现在代码内部。/*说明文字*/
单行注释,只能在代码最后出现。//说明文字
2.数据类型
常量声明使用const,常量的值是不能被更新的。
1)基本类型
(1)整型数据类型:
短整型 short, 占内存2字节
整型 int, 占内存4字节
长整形 long, 占内存4字节
(2)浮点类型:
单精度 float, 占内存4字节
双精度 double,占内存8字节
(3)字符类型:char,占内存1字节
2)构造类型
(1)数组
(2)结构体 struct
(3)联合体 union
(4)枚举 enum
3)函数、void、指针
后文详解。
3.表达式和运算符
1)算数运算符
加法:+
减法:-
乘法:*
除法:/
取余:%
2)逻辑运算符
&& 且,如果左边为假,则直接返回假,不再判断右边
|| 或,当左边为真,则直接返回真,不再判断右边
! 非,一元运算,如果紧跟的操作数为真,则返回假
3)关系运算符
== 值等,判断值是否相等,相等则返回真true
!= 不等于,判断值是否不相等,不相等则返回真true
> 大于,判断是否左边的值大于右边的值,大于则返回真
< 小于,判断左边的值是否小于右边的值,小于则返回真
>= 大于等于,判断左边的值是否大于或等于右边的值
<= 小于等于,判断左边的值是否小于或等于右边的值
4)一元运算符
++ 自增运算符
a++,首先返回a的值,然后执行a=a+1
++a,首先执行a=a+1,然后返回a的值
-- 自减运算符
a--,首先返回a的值,然后执行a=a-1
--a,首先执行a=a-1,然后返回a的值
sizeof
计算一个变量或基本数据类型占用多少内存
printf("%d\n", sizeof(short)); //结果为2
short i; printf("%d\n", sizeof i); //结果为2
5)三目运算符
三元运算,有三个操作数或算式,当第一个算式为真,则返回第二个算式结果,否则返回第三个算式的结果,使用方法:
算式1 ? 算式2 : 算式3 ;
int i=90;i = ( i > 0 ) ? 87 : 34;printf("%d\n", i); //87
4.流程控制语句
1)if 判断
形式1:if (条件) { 执行语句1; } else { 执行语句2; } 。else部分不是必须的。只要条件为真,就执行语句1,省略语句2。
if (3 > 2) {printf("3>2\n"); //输出} else {printf("3<2\n"); //省略}
形式2:if (条件1) { 执行语句1; } else if (条件2) { 执行语句2; } else { 执行语句3; } 。如果条件1不为真,就会判断条件2 ,如果条件2也不为真,则执行语句3。如果条件1假单条件2真,则仅执行语句2。
if (3 < 2) {printf("3<2\n");} else if (3 > 1) {printf("3>1\n"); //输出} else {printf("3<0\n");}
2)switch 匹配
int i = 9;_Bool b = i>5; //布尔型switch (b) {//case的条件只能是常量case 0: //0为假printf("9<5 \n");break;case 1: //非0为真printf("9>5 \n"); //输出break;default:printf("9...5 \n");break;}
3)while、do-while 循环
int i = 5;//while(条件),条件可以使算式,结果必须为真。首先判断条件,非0(负数也是非0)才执行while (i) {printf("%d \n", i);i--;}int j = 0;//无论如何,首先至少执行一次do{printf("%d \n", j);j--;}while (j == 0);//while(条件),先执行再判断
4)for 遍历
int i;//for(表达式1;表达式2;表达式3)//表达式1:仅执行一次,一般做初始化//表达式2:控制执行语句,一般是保证循环结束的条件//表达式3:动态控制语句,动态改变控制语句状态for (i = 0; i < 5; i++) {printf("%d \n", i);}
5.函数
printf格式控制:
%c 输出单个字符
%d 输出带符号的十进制整数
%4d 若表示的位数大于4,再按原样输出; 若小于4,左侧补空格,-4空侧补空格
%e 输出标准指数形式的单、双精度整数,默认6位小数
%f 输出小数形式的单双精度数字,默认6位小数
%.2f 输出两位小数
%o 输出不带符合的8进制整数
%p 输出内存的地址。如:int a; printf("%p", &a);
%s 输出单个或多个字符
%u 输出不带符号的十进制整数
%x 输出不带符号的十六进制整数
printf转义字符:
\a 蜂鸣,响铃
\b 回退:向后退一格
\f 换页
\n 换行,光标到下行行首
\r 回车,光标到本行行首
\t 水平制表
\v 垂直制表
\\ 反斜杠
\' 单引号
\" 双引号
\? 问号
\0 空字符(NULL),什么都不做
\ddd 三位八进制
\xhh 二位十六进制
scanf参数控制:
scanf("格式符分隔符格式符分隔符格式符", &a, &b, &c);
接收多个参数时,分隔符可以是空格、制表符、回车。
函数是把实现某一功能的一段代码的封装,可以提高代码的复用性,避免代码冗余。
/*使用<> 先去系统目录中找头文件,如果没有,再到当前目录下找。标准的头文件 stdio.h、stdlib.h等一般都用这个方法。使用"" 首先在当前目录下寻找,如果找不到,再到系统目录中寻找。自定义的头文件一般用这个方法。
*/
#import <stdio.h>
// #import比起#include的好处就是不会引起交叉编译,由GCC支持。//返回值类型 函数名(参数类型 形参)
//返回值类型省略,则默认是int
int funcCount(int i, int j){return i+j; //如果没有return语句,则返回i
}//自定义函数要声明或创建在main之前
void funcShow(char str[]); //C语言里没有方法重载
void funcShow(char str[]); //可以重复声明同一个函数int main() {int i=10, j=9;//int k = myFunc(i, j);printf("%d, %d, %d\n", i, j, funcCount(i, j));//如果不在main之前声明自定义函数,可以直接在调用前声明//void funcShow(char str[]);funcShow("Hello Function !");
}//返回值类型 函数名(参数类型 形参)
void funcShow(char str[]){printf("%s\n", str);return; //尽管这个函数无返回值(void),但仍可以return,表示程序执行到这里就结束printf("这里不会执行了...\n");
}
6.进制转换
#include <stdio.h>int main() {//无特殊标注,默认10进制int i = 10;//以0b开始,2进制//int j = 0b10; //须编译器的支持//以0开始,8进制int k = 010;//以0x开始,16进制int l = 0xA;printf("%d \n", i);//printf("%d \n", j);printf("%d \n", k);printf("%d \n", l);/*10进制 -> 2进制方法1:10 = 8 + 2= 2的3次方 + 2 * 2的0次方= 0b1000 + 0b10= 0b1010方法2(10进制转n进制方法):10/2 = 商 5 余 05/5 = 商 2 余 12/2 = 商 1 余 01/2 = 商 0 余 1倒序余数 1010*//*2进制 -> 10进制//自右向左四个数字依次匹配2的0次方、2的1次方、2的2次方、2的3次方0b1010=1 * 2的3次方 + 0 * 2的2次方 + 1 * 2的1次方 + 0 * 2的0次方=1*8 + 0*4 + 1*2 + 0*1=8 + 0 + 2 + 0=10*//*n进制 -> 10进制//自右向左四个数字依次匹配n的0次方、n的1次方、n的2次方、n的3次方、...1010=1 * n的3次方 + 0 * n的2次方 + 1 * n的1次方 + 0 * n的0次方*/return 0;
}
7.位运算
1)与或异或取反
int i = 9; //1001int j = 5; //0101//----------------//i&j = 1; //0001//i|j = 13; //1101//i^j = 12; //1100//~i = -10; //1111 1111 1111 1111 1111 1111 1111 0110//位运算 与 & ,位置一一对应,都为1时得到一,否则为0//任何位置和1与操作,都得到原值printf("%d\n", i&j);//位运算 或 | ,位置一一对应,只要有一个1即得1printf("%d\n", i|j);//位运算 异或 ^ ,位置一一对应,不相同即得1//相同数值异或操作得0//多个数值异或时位置可交换。9^7^3 == 7^3^9//任何数值和0异或,得原值printf("%d\n", i^j);//位运算 按位取反 ~ ,把原位置的0变为1,1变为0printf("%d\n", ~i);return 0;
2)位移
int i = 9;//-------------------向左位移-----------------------------//原二进制数 0000 0000 0000 0000 0000 0000 0000 0000 1001//向左位移一位 000 0000 0000 0000 0000 0000 0000 0000 10010//最左侧超出的一位舍弃,右侧空缺的一位补0 。得到10010int j = i << 1; //如同 i*(2的1次方)printf("%d \n", j);//最左侧超出的2位舍弃,右侧空缺的2位补0 。得到100100j = i << 2; //如同 i*(2的2次方)printf("%d \n", j);//i左移N位,同i*(2的N次方)//-------------------向右位移-----------------------------//原二进制数 0000 0000 0000 0000 0000 0000 0000 0000 1001//向右位移一位 00000 0000 0000 0000 0000 0000 0000 0000 100//最右侧超出的一位舍弃,左侧空缺的一位按原符号位的值补齐 。得到100j = i >> 1; //如同 i/(2的1次方)printf("%d \n", j);//最左侧超出的2位舍弃,右侧空缺的2位补0 。得到100100j = i >> 2; //如同 i/(2的2次方)printf("%d \n", j);//i右移N位,同i/(2的N次方)//-------------------交换两个变量的值------------------------------int a = 9, b = 8;int t = a;a = b;b = t;printf("a=%d, b=%d \n", a, b);a = 9;b = 8;a = b-a; //a=-1b = b-a; //b=9a = a+b; //a=8printf("a=%d, b=%d \n", a, b);a = 9;b = 8;//a = 1001, b = 1000。异或:不相同得1a = a^b; //a = 0001b = a^b; //b = 1001a = a^b; //a = 1000printf("a=%d, b=%d \n", a, b);int m = 10;//匹配16、32、64位系统中int占多少位内存int n = (sizeof(m) << 3) - 1;//从最左侧的位开始打印while(n >= 0){//向右移,保留最左侧位int v = m >> n & 1;printf("%d", v);//依次打印全部的位n--;//逢4留空if((n+1)%4 == 0){printf(" ");}}
- end