函数
构成C程序的基本单元是函数,函数包含程序的可执行代码。所有简单的程序都可以定义其他额外的函数,编写程序的时候,并不是将所有的内容都放在主函数 main 当中为了方便规划、组织、编写和调试,一般的做法是将一个程序划分成若干个程序模块,每一个模块都可以完成一个功能。这样不同的模块程序可以由不同的人去完成,从而可以提高软件的开发效率。
- 主函数可以调用其它的函数;
- 其它的函数当中也是可以去互相调用。
函数的定义形式:
返回类型 函数名称(参数){函数体(实现函数的功能)}
返回类型:是函数返回值的数据类型,有些函数不需要返回值,这种函数的返回类型为void。
函数名称:是函数的实际名称,调用的时候用函数名来调用。
参数:就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数 参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。
函数主体:就是执行某种特定任务的代码块。
int add(int a,intb) //函数头部 { int c=a+b;//实现特定任务 return c;//返回一个值 }
下面是函数调用的代码:
int Add(int a, int b) { int c = a + b; return c; } int main() { int a = 5; int b = 5; int count = Add(a, b); printf("%d", count); return 0; }
注意:
自定义函数不能写在主函数(main函数)后面,这样会造成程序的出错。
数组
- 数组的声明不是声明一个一个的变量,而是集合。
- 所有的数组都是由连续的内存位置组成的。最低的地址对应第一个元素,最高的地址对应最后一个元素。如下图:
数组定义
类型说明符 数组标识符【常量表达式】
- 类型说明符 :表示数组中所有元素的类型。
- 数组标识符:表示数组类型变量的名称,命名规则和变量名一样。
- 常量表达式:定义了数组中存放的数据元素个数,即数组长度。
例如定义一个数组如下:
int arr[10]={0,1,2,3,4,5,6,7,8,9};
数组下标
C语言规定:数组的每个元素都有下标,下标是从0开始。
数组可以通过下标来访问的。
int arr[10]={0,1,2,3,4,5,6,7,8,9};
在数组arr[10]中只能使用下标[0~9],因为数组下标是从0开始的。
数组使用
如要打印1~10的元素!如果不用到数组的话就需要创建10个变量来存储,会显得很麻烦。
那么我们用到数组就可以很好得存储起来呢,因为数组就是一组相同的元素集合。如下图:
#include<stdio.h> int main() { int i = 0; int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; for (i = 0; i < 10; i++) { printf("%d ",arr[i]); } return 0; }
操作符
C语言提供了非常丰富的操作符,有如下几种操作符。
算术操作符
+ - * / %
加减乘,在以前数学里学到的一样呢,重点说下除法(/)和取模(%)
除法(/):
分为整数除法和浮点数除法
整数除法中的得到的整数时商,不会管余数,如下图所示int 9/2得到的结果时4,
为什么没有得到4.5呢,因为除号两端都是整数时,执行的是整数除法,如果两端有一个为浮点数时就执行浮点数除法。
下面我将一边改为浮点数结果入下图所示:
取模(%):
得到的是余数,只能操作整数
移位操作符
<< >>
左移 右移
移位操作符涉及二进制,在后面的博客会详细讲解的。
位操作符
& ^ |
按位与 按位或 按位异或
这个也在后面的博客会详细讲解的,这里只是初始C语言不过多的讲解。
赋值操作符
= += -= *= /= &= ^= |= >>= <<=
赋值 加等 减等 乘等 除等 按位与等 按位或等 按位异或等 右移等 左移等
在赋值操作符中我们使用最多的就是前5中操作符,我们可以这样理解“加等”
int a,b; a=a+b; //或者这样写 a+=b;
包括减等,乘等,除等,和加等的使用时一样的。至于剩下的赋值操作符,在后面的博客我会详细给大家一一介绍的。
单目操作符
什么时单目操作符?就是只有一个操作数的操作符。
! | 逻辑反操作 |
- | 负值 |
+ | 正值 |
& | 取地址 |
sizeof | 操作数的类型长度(以字节为单位) |
~ | 对一个数的二进制按位取反 |
– | 前置、后置– |
++ | 前置、后置++ |
* | 解引用操作符 |
(类型) | 强制类型转换 |
下面我简单介绍几个操作符,至于剩下的操作符我在后面的博客会详细的介绍。
在C语言中,规定非0为真,0为假。那就可以理解为-1为真。下面代码:
int main() { int a = 0; if (!a)//a等于0时为假,!a为真 { printf("hello"); } return 0; }
输出的结果为:
hello
这就是“!”单目操作符的简单介绍。下面介绍一个大家经常容易误解的一个操作符:sizeof()
sizeof是一个操作符,不是函数。
int main() { int a = 0; printf("%d", sizeof(a));//计算a所占空间的大小 printf("%d", sizeof(int));//也可以换成类型 printf("%d", sizeof a);//因为sizeof不是一个函数,可以去掉(), //这一点进一步证明sizeof是操作符不是函数 但sizeof int 这样是不行的。 return 0; }
下面再介绍一个前置、后置++或者–
由此可以得出:
- 前置++ 或–先自增再赋值
- 后置++ 或–先赋值再自增
至于剩下的单目操作符再以后的博客再详细给大家介绍。
关系操作符
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
!= | 不相等 |
== | 相等 |
int main() { int a = 10; if (a=3) { printf("hello"); } return 0; }
这里会打印"hello",但是这里时赋值,不是判断需要改成a==3
int main() { int a = 10; if (a==3)//判断a是否等于3 { printf("hello"); } return 0; }
逻辑操作符
&& | 逻辑与 |
|| | 逻辑或 |
- &&就是要两个都为真则为真,如果其中一个为假,那么所有的都为假。
- ||就是只要有一个为真结果就为真。
条件操作符
exp1?exp2:exp3
条件操作符也可以称为三目操作符,表达式1为真表达式2算,表达式3不算(表达式结果为表达式2的结果);表达式1为假,表达式2不算,表达式3算(表达式结果为表达式3的结果)。
逗号表达式
exp1, exp2, exp3, …expN
逗号表达式是从左向右计算的,逗号表达式的结果是最后一个表达式的结果。
下标引用、函数调用和结构体成员
[ ] () . ->
这里我介绍下前面两个
void Print(int arr[], int b) { for (int i = 0; i < b; i++) { printf("%d\t", arr[i]); } } int main() { int arr[] = { 1,2,3,4,5,6,7,8,9 }; arr[4] = 20;//这里的[]操作符就是下标引用操作符 arr和4就是[]的操作数 printf("%d\n", arr[4]); Print(arr, 9);//()就是函数调用操作符,Print,arr,9都是()的操作数 return 0; }
关于剩下的操作符我会在后面进行细致的介绍。
常见关键字
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
C语言中提供了丰富的关键字,用户不能自己创建关键字。
关键字分类
- 数据类型关键字(12个)
char | 声明字符变量或函数 |
double | 声明双精度变量或函数 |
enum | 声明枚举类型 |
float | 声明浮点变量或函数 |
int | 声明整型变量或函数 |
long | 声明长整型变量或函数 |
short | 声明短整型变量或函数 |
signed | 声明有符号类型变量或函数 |
struct | 声明结构体变量或函数 |
union | 声明联合类型 |
usigned | 声明无符号类型变量或函数 |
void | 声明函数无返回类型或参数,声明无类型指针 |
- 控制语句关键字(12个)
for | 循环语句 |
do | 循环语句的循环体 |
while | 循环语句的循环条件 |
break | 跳出当前循环 |
continue | 结束当前循环,进入下个循环 |
if | 条件语句 |
else | 条件语句否定分支 |
goto | 无条件跳转语句 |
switch | 用户开关语句 |
case | 开关语句分支 |
default | 开关语句中的其他分支 |
return | 返回 |
- 存储类型关键字(4个)
auto | 声明自动变量 |
extern | 声明变量是在其他文件中 |
register | 声明寄存器变量 |
static | 声明静态变量 |
- 其它关键字(4个)
const | 声明只读常量 |
sizeof | 计算数据类型长度 |
typedef | 用来个数据类型去别名 |
volatile | 说明变量在程序执行中可被隐含的 |
typedef关键字
在C语言中有一个typedef关键字,其用来定义用户自定义类型。当然,并不是真的创造了一种数据类型,而是给已有的或者符合型的以及复杂的数据类型取一个我们自己更容易理解的别名。总之,可以使用typedef关键字定义一个我们自己的类型名称。例如:
//将unsigned int 重命名为uint, 所以uint也是一个类型名 typedef unsigned int uint; int main() { //观察num1和num2,这两个变量的类型是一样的 unsigned int num1 = 0; uint num2 = 0; return 0; }
static关键字
在C语言中:
static是用来修饰变量和函数的
- 修饰局部变量-称为静态局部变量
- 修饰全局变量-称为静态全局变量
- 修饰函数-称为静态函数
修饰局部变量
#include <stdio.h> void test() { //static修饰局部变量 static int i = 0; i++; printf("%d ", i); } int main() { int i = 0; for(i=0; i<10; i++) { test(); } return 0; }
结论:
- static修饰的变量改变了变量的生命周期
- 让静态变量出了作用域还存在,直到程序结束变量的生命周期才结束。
修饰全局变量
//代码1 //add.c int g_val = 2018; //test.c int main() { printf("%d\n", g_val); return 0; } //代码2 //add.c static int g_val = 2018; //test.c int main() { printf("%d\n", g_val); return 0; }
结论:
- 一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。
修饰函数
修饰函数和修饰全局变量一样的呢,都只能在本源文件内使用了。
define定义常量和宏
//define定义标识符常量 #define MAX 1000 //define定义宏 #define ADD(x, y) ((x)+(y)) #include <stdio.h> int main() { int sum = ADD(2, 3); printf("sum = %d\n", sum); sum = 10*ADD(2, 3); printf("sum = %d\n", sum); return 0; }
指针
指针是c语言中的一个重要概念,也是C语言的一个重要的特色,正确而灵活地运用它,可以使程序简洁,紧凑,高效,每一个学习和使用c语言的人,都应当深入了解地学习和掌握指针,可以说,不掌握指针就是没有掌握C的精华也可以说指针是C语言的灵魂。
内存
- 内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。
- 所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。
- 为了有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
每个变量都是创建在内存中的,即每个内存单元都有地址,所以变量也是有地址的。
#include <stdio.h> int main() { int num = 20; #//取出num的地址 //注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地址) printf("%p\n", &num);//打印地址,%p是以地址的形式打印 return 0; }
如何存储地址呢?这就需要用到指针变量。
int mun=20; int *p;//p为整型指针 p=#
怎么使用指针呢?如下所示:
#include<stdio.h> int main() { int mun=20; int *p=# *P=30; printf("%d",mun); return 0; }
其他类型使用方法也是一样的。
指针变量的大小
#include <stdio.h> //指针变量的大小取决于地址的大小 //32位平台下地址是32个bit位(即4个字节) //64位平台下地址是64个bit位(即8个字节) int main() { printf("%d\n", sizeof(char *)); printf("%d\n", sizeof(short *)); printf("%d\n", sizeof(int *)); printf("%d\n", sizeof(double *)); return 0; }
指针的大小在32位平台上是4个字节,在64位平台上是8个字节。
结构体
结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可以不同,每个这样的变量或数组都称为结构体的成员。结构的成员可以是标量、数组、指针,甚至是其他结构体。
struct 结构名 { 类型 变量名; 类型 变量名; ... } 结构变量;
举例:
struct Stu { char name[20];//名字 int age; //年龄 char sex[5]; //性别 char id[15]; //学号 };
初始化结构体:
//打印结构体信息 struct Stu s = {"张三", 20, "男", "20180101"}; //.为结构成员访问操作符 printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id); //->操作符 struct Stu *ps = &s; printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps- >id);
以上介绍了函数、数组、操作符、关键字、指针和结构体,其中还有很多内容没有介绍,每个内容后面都会单独一篇博客来介绍的,这里主要是初始C语言其中的东西。