本文是简要介绍,具体会在后面详细介绍。
一、选择语句
if else 语句(注意形式)
#include<stdio.h>
int main()
{
int a = 0;
printf("你选择努力(1)还是摆烂(0):");
scanf("%d", &a);
if (a)
printf("success\n");
else
printf("期待你的努力\n");
return 0;
}
输入1,得到:success; 输入0,得到:期待你的努力。
二、循环语句
(1)while语句
(2)for语句
(3)do……while语句
这里以while语句为例
举例代码如下:
#include<stdio.h>
int main()
{
int line = 0;
//循环
while (line < 30000)//while循环
{
printf("写代码:%d\n",line);
line++;
}
if (line == 30000)
{
printf("质变\n");
}
return 0;
}
运行结果:
可以看到当line<30000时,一直写代码,当line等于30000时,跳出循环,执行下面的if语句,输出:质变。
三、函数
函数可以重复使用。
下面是两种求和方法。一种是普通方法,一种是函数的方法。
int Add(int x,int y)//函数的定义
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int num1 = 0;
int num2 = 0;
printf("请输入需要相加的两个值:\n");
scanf("%d %d", &num1, &num2);
printf("两数之和:\n");
//直接求和
printf("%d\n", num1 + num2);
//函数的方式解决
int sum=Add(num1, num2);
printf("%d\n", sum);
return 0;
}
int Add(int x,int y) 其中第一个int定义的是返回值的类型,后两个是局部变量的类型。
运行结果:
四、数组
定义:一种相同类型元素的集合
注:数组是用下标来访问的,例如arr[0]访问的是数组的第一个值。
注意代码中数组不完全初始化的形式。
int main()
{
//数组-一种相同类型元素的集合
//10个整型1-10存起来
//数组是用下标来访问的
//arr[0]访问的是第一个值
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//数组创建和初始化
int i = 0;
while (i < 10)//调试按F10-很重要的功能
{
printf("%d\n", arr[i]);
i++;
}
char ch[5] = { 'a','b','c' };//不完全初始化,剩余的赋0
return 0;
}
运行结果:
按住F10可以实现调试功能。
如何使用监视功能:
调试->窗口->监视
可以看到arr中下标0~9储存的值是1~10
arr[10]中的10必须是常量
arr[n]这种形式是错误的,数组指定大小的部分必须有常量。
五、操作符
1、算术操作符
+ - * / %
以除法操作符为例。
注意整数除法和小数除法的结果和区别。
#include<stdio.h>
int main()
{
float a = 9 / 2;//整数除法
float b = 9 / 2.0;//小数除法
printf("%f %f\n", a,b);
return 0;
}
运行结果如下:
可以看到整数除法只保留小数部分,小数除法才会显示全部。所以需要注意。
2、移位操作符
>> <<
以左移<<为例。
#include<stdio.h>
int main()
{
int a = 2;//整型有32个bit
printf("%d\n", a << 1);//a左移1位,输出结果应该是4
//00000000000000000000000000000010 2
//00000000000000000000000000000100 4
return 0;
}
上述代码定义的a是整型,占4个字节,也就是32个bit位
那么2的二进制为:00000000000000000000000000000010
左移一位:00000000000000000000000000000100
最后的结果是4。
3、位操作符
& 按位与
| 按位或
^ 按位异或
4、赋值操作符
= += -= *= /= &= ^= |= >>= <<=
5、单目操作符:只有一个操作数
! - + & sizeof ~ -- ++ * (类型) | 逻辑反操作 负值 正值 取地址操作 数的类型长度(以字节为单位) 对一个数的二进制按位取反 前置、后置-- 前置、后置++ 间接访问操作符(解引用操作符) 强制类型转换 |
(1)以逻辑反操作为例
#include<stdio.h>
int main()
{
//0表示假,非零就是真
int a = 0;
printf("%d\n", !a);
if (a)
{
//如果a为真做事
}
if (!a)//a为假,取反之后就为真,然后执行程序
{
//如果a为假做事
}
return 0;
}
(2)sizeof:计算变量或者类型的大小。
//单目操作符:sizeof
#include<stdio.h>
int main()
{
int a = 0;
//sizeof是一个操作符
// 不是函数,求变量的时候a的括号是可以省略的
//计算变量或者类型的大小
printf("%d\n", sizeof(int));
printf("%d\n", sizeof(a));
return 0;
}
运行结果如下:
sizeof计算大小的单位是字节。
int是一个数据类型,占4个字节。
a是变量,是int类型,也占4个字节。
sizeof操作符也可以用来计算数组元素的个数:
#include<stdio.h>
int main()
{
int arr[10] = { 0 };
printf("%d\n", sizeof(arr));//计算的是数组的总大小,单位是字节
printf("%d\n", sizeof(arr[0]));//4
int sz = sizeof(arr) / sizeof(arr[0]);//计算个数
printf("%d\n", sz);
return 0;
}
先计算数组总大小,再计算单个元素占多少空间,最后两者一除,就是数组元素的个数。
运行结果如下:
总大小为40,单个数组元素占4空间,除后可得10个。
(3)~对一个数的二进制位按位取反(包括符号位全部取反)
就是把二进制位中的所有数字,原来是1变成0,0变成1。
//~按位取反
int main()
{
int a = 0;
printf("%d\n", ~a);
//~按位取反
return 0;
}
注:这里非常容易出错。
数据在内存中存储的是补码。所以按位取反时,操作的是补码。
上述代码中定义的a是0,它的原码,反码,补码相同,都是:
00000000000000000000000000000000
对补码进行按位取反
111111111111111111111111111111111111
但是printf打印出来的值是原码的十进制,所以改成原码如下:
1000000000000000000000000000001
它的十进制是-1。
运行结果:-1
补充:原码,反码和补码的知识。
以负数为例:-1的原码是
原码:10000000000000000000000000000001(最高位是符号位。负数是1,整数是0)
反码:111111111111111111111111111111111110(符号位不变,其他位按位取反)
补码:111111111111111111111111111111111111(反码加1)
正数的原码,反码补码均相同。
(4)前置和后置++
//前置和后置++
#include<stdio.h>
int main()
{
int a = 10;
int b = a++;//后置++:先使用,再++(先赋值给b,a再++)
printf("%d\n", b);//10
printf("%d\n",a);//11,此时a已经变成11了
//int a = 10;
//int b = ++a;//前置++:先++,后使用
//printf("%d\n", b);//11
//printf("%d\n",a);//11,此时a已经变成11了
return 0;
}
运行结果:
后置++:b=a++;先使用,再++(先赋值给b,a自己再++)
前置++:b=++a;先++,再使用(自己先加,再赋值给b)
(5)(类型):强制类型转换
#include<stdio.h>
int main()
{
//(类型)强制类型转换
int a = (int)3.14;
printf("%d\n", a);
return 0;
}
(int):将浮点型3.14强制转换成整型。其他情况同理。
6、关系操作符
>
>=
<
<=
!= 用于测试“不相等”
== 用于测试“相等”
7、逻辑操作符
&& || | 逻辑与 逻辑或 |
介绍何位为真:值不是0就为真,例如a=10,a不是0,所以a为真。
a&&b:a和b都要是真
a||b:a和b有一个是真,结果就是真。
8、条件操作符
exp1?exp2:exp3 (三目操作符)
exp1成立,exp2计算,整个表达式的结果是exp2的结果
exp1不成立,exp3计算,整个表达式的结果是exp3的结果
//求最大值
#include<stdio.h>
int main()
{
int a = 0;
int b = 3;
int max = 0;
/*if (a > b)
max = a;
else
max = b;*/
//另一种方法
max = a > b ? a : b;//三目操作符
printf("%d\n", max);
return 0;
}
9、逗号表达式:逗号隔开的一串表达式
exp1,exp2,exp3,……,expn
#include<stdio.h>
int main()
{
int a = 0;
int b = 3;
int c = 5;
//a=5 c=1 b=3
int d = (a = b + 2, c = a - 4, b = c + 2);
//逗号表达式是从左向右依次计算的
//整个表达式的结果是最后一个表达式的结果
printf("%d\n", d);
return 0;
}
从左向右依次计算,整个表达式的结果是最后一个表达式的结果
a=3+2 ——c=5-4 ——b=1+2,结果为3,可以自行验证。
10、下标引用、函数调用和结构成员
[] 下标引用
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%d\n", arr[5]);//[5]中的方框是下标引用操作符
return 0;
}
() 函数调用
#include<stdio.h>
int main()
{
//调用函数时,函数名后边的圆括号()就是函数调用操作符
printf("heheheh\n");
printf("%d\n,100");
return 0;
}
. 结构成员
-> 结构成员
六、关键字
关键字是C语言提供的,不能自己创建。
变量名不能是关键字。
下面列出常见的关键字(格式有些问题,一个词是一个关键字)
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 |
(1)auto-自动的 变量自动创建,自动销毁
auto 一般省略掉
#include<stdio.h>
int main()
{
{
int a = 10;//自动创建的,自动销毁的-自动变量
//auto 省略掉了
//auto 新的C语言语法中也有其他-暂时不考虑
}
return 0;
}
(2)extern--用来声明外部符号
当定义一个全局变量a时,在一个源文件中定义了,在另一个源文件中可以使用,但需要进行一下声明: extern int a;
格式:extern 数据类型 变量名
也可以声明函数
//声明函数
extern int Add(intx, inty);//不加x和y也可以,如右侧,extern int Add(int, int);
int main()
{
int a = 10;
int b = 20;
int sum = Add(a, b);
printf("%d\n", sum);
return 0;
}
(3)register--寄存器关键字
大量被频繁使用的数据,放在寄存器中可以提升效率。
注:CPU和内存之间有寄存器,可以提升效率。
#include<stdio.h>
int main()
{
//大量、频繁被使用的数据,放在寄存器中,提升效率
register int num = 100;//建议num的值存放在寄存器中
return 0;
}
(4)typedef-类型定义
可以称之为类型重定义。起到简化的作用。
例如 typedef unsigned int u_int;
下面的代码u_int就可以替代unsigned int
#include<stdio.h>
typedef unsigned int u_int;
int main()
{
unsigned int num = 100;
u_int num2 = 1000;
return 0;
}
(5)static--静态的
-static修饰局部变量
//static修饰局部变量
#include<stdio.h>
void test()
{
static int a = 1;//不加static就是10个2,加上就是2到11
//加入static,出了局部变量之后不消毁,下次进去之后保留原来的值,非常重要。
a++;
printf("%d ", a);
}
int main()
{
int i = 0;
while (i < 10)
{
test();
i++;
}
return 0;
}
上述代码中局部变量a,每执行一次test函数,就给a附一个1;
但是如果用static修饰之后,改变了局部变量a的生命周期,也就是执行完一次test之后,a保留原来的值,例如a执行一次之后,加1,变成2,下次在开始执行test时,a不再是1,而是2。
-static修饰全局变量
static修饰全局变量之后,使得全局变量只能在自己所在的源文件中使用,其他源文件不再可以使用。
-static修饰函数
static修饰函数,使得函数只能在自己所在的源文件内部使用,不能在其他源文件内部使用
本质上,static是将函数的外部链接属性,变成了内部连接属性(和static修饰全局变量一样)
七、#define定义常量和宏
注:define和include不是关键字,是预处理指令。
1、define定义标识符常量(在讲常量时已经讲过)
#include<stdio.h>
#define MAX 1000
int main()
{
printf("%d\n", MAX);
return 0;
}
2、define定义宏
宏是完成一个替换的作用。
#define ADD(X,Y) ((X)+(Y))
用ADD(X,Y)代替 ((X)+(Y))
所以如果写成
#define ADD(X,Y) X+Y
可能会出现歧义
4*ADD(X+Y)=4*X+Y(就不对了)
#include<stdio.h>
#define ADD(X,Y) ((X)+(Y))
int main()
{
printf("%d\n", 4*ADD(2, 3));
return 0;
}
八、指针
学习指针,我们首先要了解内存。
1、内存
内存的编号
对于一个32位的系统来说,有32根地址线。
所以内存编号共有2^32次方。
注意:一个内存单元的大小:规定就是1个字节=8个bit。
分配地址,一个字节给一个编号。
比如,int a=0; a需要占用4个字节的空间,如上图中黑框内。虽然有4个字节,但是只取第一个字节所占的地址。
2、指针定义和初始化
#include<stdio.h>
int main()
{
int a = 10;//a在内存中要分配空间-4字节
printf("%p\n", &a);//%p转门用来打印地址,此时打印的地址是四个字节中第一个字节所处的地址
int * pa = &a;//打印出来的地址要存放,pa是用来存放地址的,在C语言中pa叫指针变量
//*说明pa是指针变量,,这个*是为了说明pa是指针变量,二*pa中的*是解引用操作,不一样
//int说明pa执行的对象是int类型的
char ch = 'w';
char* pc = &ch;//(书写方式)
return 0;
}
%p---专门用来打印地址时使用的。
int * pa = &a;
&:把存放a的地址取出来。
*说明pa是指针变量,用来存放地址。
int说明pa执行的对象(也就是a)是int 类型的。
运行的结果是a的地址。
3、接下来介绍一个解引用操作。
这个解引用操作,可以通过指针变量pa直接给变量a赋值。
*pa=20; 相当于把20赋值给a。(通过pa里面的地址找到a)
//指针就是地址
#include<stdio.h>
int main()
{
int a = 10;
int * pa = &a;
*pa = 20;//*解引用操作 *pa就是通过pa里面的地址,找到a
printf("%d\n", a);
return 0;
}
4、讨论指针变量的大小
sizeof操作符可以计算指针变量所占的空间。
#include<stdio.h>
int main()
{
printf("%d\n", sizeof(char*));
printf("%d\n", sizeof(short*));
printf("%d\n", sizeof(int*));
printf("%d\n", sizeof(long*));
printf("%d\n", sizeof(long long*));
printf("%d\n", sizeof(float*));
printf("%d\n", sizeof(double*));
return 0;
}
运行结果:
可以看到:不管是整型还是浮点型都是8;
我们注意:指针变量是用来存放地址的,所以指针变量的大小取决于地址存放时需要多大的空间。
由于我这个电脑时64位操作系统,所以64个bit位,也就是8字节,所以打印出来是8。
如果是32位,打印出来就是4。
注意:要注意区分内存单元(一个字节)的大小和地址(64位系统和32位系统不一样)的区别!
九、结构体
结构体可以让C语言创造新的类型出来。
//创建一个学生
#include<stdio.h>
struct Stu
{
char name[20];//成员变量
int age;
double score;
};
//创建一个书的类型
struct Book
{
char name[20];
float price;
char id[30];
};
int main()
{
//结构体的创建和初始化
struct Stu s = {"张三",20,85.5};//创建的一个学生
printf("1:%s %d %lf\n", s.name, s.age, s.score);// 结构体变量.成员变量 .操作符
struct Stu* ps = &s; //ps是指针变量,struct Stu是类型
printf("2:%s %d %lf\n", (*ps).name, (*ps).age, (*ps).score); //*ps就是s
printf("3:%s %d %lf\n", ps->name, ps->age, ps->score); //结构体指针->成员
//当我们知道结构体变量,就用1;当我们知道结构体指针最好用3,简单
return 0;
}
注意结构体打印的几种方式!