1.什么是C语言
1.1计算机与机器语言
计算机俗称电脑,是现代一种用于高速计算的电子计算机器,可以进行数值计算,又可以进行逻辑计算,还具有存储记忆功能。
能够按照程序运行,自动、高速处理海量数据。而要想让电脑按照程序和指令运 行,就需要给机器下达指令。
对于早期的机器它们只能直接识别两种状态, 一种是通电一种是断电,意味着机器通过电路和二极管来完成。
科学家们为了简化机器,利用数学语言0和1来表示计算机能够识别的通电和断电两种状态。所以计算机能识别的所有指令以及存储和操作的数据都是由0和1组成的。计算机里都采用二进制。
“二进制”,就是一种仅用“1”和“0”的排列组合来表示具体数值的,一种记数方法。
虽然简化了很多,但这时候机器就只能听得懂0和1,给机器下达一条简单的指令需要很长的一串01数字。写程序下指令还是很复杂,编程只有科学家会,写的过程也很痛苦,还需要不断地查表,出现了问题也很难检查。
这些可以由计算机直接识别的二进制代码就叫做机器语言,无需编译即可下达指令给计算机。
类似说,英语也是一门语言,用于人和人之间交流合作。说出英语后,懂英语的人会根据你说的指令去干活。而机器语言就是电脑机器等可以听懂或者看懂的言语。人输入机器语言机器听懂以后会做出你指定的相关动作,例如打开软件,计算数字之和。
1.2汇编语言
为了进一步地简便化,科学家们发明了助记符。
举一个例子,假设0101 0110 表示需要机器去做加法,这时候科学家们用add标记这一串数字,以后下达命令写代码的人只需要写这些标记符就可以了,会有专门的编译器把助记符翻译成复杂的机器语言传达给机器。
由这些助记符构成的语言就叫汇编语言。
1.3高级语言
后来科学家依次发明了b语言和 c语言 c++ java Python等高级语言,编程越来越方便。
对于C语言来说:
特点
C语言是一门通用计算机编程语言,广泛应用于底层开发。作为面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。它既具有高级语言的特点,又具有汇编语言的特点。 设计目标是提供一种能以简易的方式编译、处理低级存储器的编程语言。
标准与跨平台
尽管C语言提供了许多低级处理的功能,但仍然保持着跨平台的特性,以一个标准规格写出的C语言程序可在包括类似嵌入式处理器以及超级计算机等作业平台的许多计算机平台上进行编译。
C语言出现后,各个公司都自己改造c语言,导致各个人用的符号都不一样。二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,让c语言成为通用语言,由美国国家标准局为C语言制定了一套完整的美国国家标准语法,称为ANSI C,作为C语言最初的标准。
目前2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。
2.编程环境的构建
2.1C语言编译器
C语言编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。
Gcc是最常用的编译器,但对于初学者来说一般使用集成开发环境(IDE,全称Integrated Development Environment用于提供程序开发环境的应用程序,集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务套)如:Visual Studio ,一般不建议使用Devc++。
2.2Visual Studio 安装
Visual Studio 下载 2022 目前官网只提供2022
首先在在浏览器搜索VisualStudio,然后按照图片步骤操作。
根据电脑的系统去选择。
来到这个界面等待下载。
打开文件
等待安装。好之后点击启动,没账号不用登录,有的话可以登录。
安装完了可以设置自己喜欢的字节,颜色等,这需要创建项目进入以后才能操作,在后面第一个c程序创建项目了后面会讲哦。
最新版的一般来说因为刚出可能用的比较少或者还有些小bug,大家一般都比较喜欢用2019.1如果有想要安装vs2019的伙伴可以私信我!
3.第一个c语言程序
3.1写前必备
C语言项目有两部分组成,我们写的一般是源文件。
3.2打印Hello world!
工具:Visual Studio
步骤:创建新项目–>空项目–>起名(尽量用英文)–>选择路径(最好固定一个路径)–>写代码
功能:在屏幕上打印helloworld
学的C语言就改成xx.c,xx.cpp是c++语言。
写代码
#include<stdio.h>
int main()
{
printf("Hello world!");
return 0;
}
运行
第一种方式按ctrl+F5
第二种:
结果
3.3代码初解
注: main函数是程序的入口,编译器系统都是从main 开始进行编译执行。意味着写代码必须要写main函数。
一个项目中可以写多个.c的源文件但是main函数有且只能有一个
main函数基本写法:
int main()
{
…//写自己的代码
return 0;
}
#include <stdio.h>:
#为预处理的意思 因为使用了printf。stdio.h这个文件相当于有这个助记符的能翻译printf的字典,要提前告知机器翻译时要用到这个字典来翻译。
printf实现功能在屏幕打印对应内容。
4. 数据类型
类型
char //字符数据类型
short //短整型
int //整型
long //长整型
long long //更长的整型
float //单精度浮点数
double //双精度浮点数
注:C语言是没有string(字符串)类型的,字符串在后面会介绍。
为什么出现这些类型?利用机算机帮助我们解决实际问题时需要表示价格,名字等。而整型会存在四种类型,小数两种,其实是为了更加丰富的表达生活中的各种值以及节约空间。
类型大小
类型描述这些东西的同时机器要储存数据,像大脑的记忆一样,不同数据类型的空间大小标题。如果想知道每一个类型占用空间多少可以使用操作符sizeof。
#include<stdio.h>
int main()
{
printf("%d ",sizeof(char)); //1
printf("%d ",sizeof(short)); //2
printf("%d ",sizeof(int)); //4
printf("%d ",sizeof(long)); //4
printf("%d ",sizeof(long)); //8
printf("%d ",sizeof(float)); //4
printf("%d ",sizeof(double)); //8 单位都是字节 byte
return 0;
}
一个字节有8个比特位,一个比特位放一个0/1.
各种类型占空间的不同可以用于节约空间 ,例如小数不要求太高精度时可以使用float节约空间。直接写3.14, 编译器默认它是double类型,可以后面加一个f,即3.14f表示它是float类型。
类型的使用:
char ch = 'w';
int weight = 120;
int salary = 20000;
格式控制符
用于控制打印的类型
%d – 打印整型
%s -打印字符串
%c -打印字符
%p-打印地址,一般是十六进制
eg:
int num=0;
printf(" %d ",num);
char arr[7]="abcdef";//这是字符串,第四章会讲到
printf(" %s ",arr);
5. 变量和常量
生活中的有些值是不变的(比如:圆周率,性别,身份证号码,血型等等)
而有些值是可变的(比如:年龄,体重,薪资)。
不变的值,C语言中用常量的概念来表示,变化的值C语言中用变量来表示。
5.1变量
定义变量的方法
类型 变量名 = 值;
int age = 150;
float weight = 45.5f;
char ch = 'w';
其本质是向内存申请一块空间,放入值,出了一定的区域会被系统删除,就像记忆一样。
变量的命名
命名要求:
只能由字母(包括大写和小写)、数字和下划线( _ )组成。
不能以数字开头。
长度不能超过63个字符。
变量名中区分大小写的。
变量名不能使用关键字。比如:char float
变量的分类
局部变量:位于大括号里的
全局变量:在整个项目里的
#include <stdio.h>
int global = 2019; //全局变量
int main()
{
int local = 2018; //局部变量
return 0;
}
注意:
局部变量可以与全局变量同名
当局部变量和全局变量同名的时候,局部变量会被优先使用。就实现了变量覆盖。如:
#include <stdio.h>
int global = 2019;
int main()
{
int global = 2020;
printf("global = %d\n", global);
return 0;
}
//运行结果:2022
一般如果在某块代码处需要给全局变量赋一个新值时可以进行变量的覆盖。
变量的作用域和生命周期
作用域
作用域 (scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
1. 局部变量的作用域是变量所在的局部范围
b只作用于最近的一对大括号{}里。 出了大括号将失去作用,无法访问。
2. 全局变量的作用域是整个工程。不同的源文件都可以使用。
a变量可以在右边的文件一用也可以在左边的文件二用,语法格式要求文件二在最前面加 extern int a;那么就可以使用这个变量了。
生命周期
变量的生命周期指的是变量的 创建 到变量的 销毁 之间的一个时间段。
1. 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
2. 全局变量的生命周期是:整个程序的生命周期。
5.2 常量
C语言中的常量分为以下以下几种:
字面常量
const 修饰的常变量
#define 定义的标识符常量
枚举常量
字面常量:就是平时在代码里直接写出的‘a’,23等字符 数字
123,3.1415
const 修饰的常变量: const是不变的的意思,在语法层面对变量进行修饰告诉编译器这个变量的值不能改变。
const int num=10;
num=20;//会报错,因为const修饰 num的值不能改变了
//注:但是它本质还是一个变量,如果有语法规定只能用常量的地方不能放 num,编 译器默认它不符合语法。
const int num=10;
int arr[num];//报错,因为语法规定,数组定义[]内一定要用常量。(数组后面会介绍,记住就可以)
#define 定义的标识符常量:一个不能改动的常量
#define PI 3.1415926 //PI贯穿整个项目都会用到
枚举常量:一般用于可以一一例举的如血型,性别,星期数;
enum Sex
{
MALE,
FEMALE,
SECRET
};
//枚举常量演示,固定写法
printf("%d\n", MALE); //结果为0
因为系统默认会给它们依次赋值0,1,2,3……,括号中的MALE,FEMALE,SECRET就是枚举常量 是常量就不能改,
// Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday
也是枚举常量
6. 字符串+转义字符+注释
6.1 字符串
"hello world"这种由双引号引起来的一串字符称为字符串字面值(String Literal)简称字符串。
注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不计入
字符串内容。如果直接创建一个字符串,系统自动在最后生成一个'\0',用于标识字符串到达了末
尾。
#include <stdio.h> int main()
{
char arr1[] = "bit";
char arr2[] = {'b', 'i', 't'};
char arr3[] = {'b', 'i', 't', '\0'};
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
return 0;
}
结果及原因:
bit
arr1创建时为字符串系统自动添加'\0'数组长度为4,%s打印字符串时功能原理是会
遇到'\0'自动停下。所以只打印出了bit
bit烫烫烫烫 bc
arr2创建时不是字符串,系统没有自动添加'\0'数组长度为3,%s打印字符串时
功能原理是会遇到'\0'自动停下。bit后面不确定是什么内容,所以会打印出乱码直到遇到'\0'才会
结束。
bit
arr3创建时虽然不是字符串系统没有自动添加'\0'但认为加了'\0'。%s打印字符串时
功能原理是会遇到'\0'自动停下。所以最后打印出了bit。
#include <stdio.h>
#include <string.h>
int main()
{
printf("abc\0"def");
return 0;
}
结果及原因:
abc
strlen 一个专门求字符串长度的库函数,使用时得包含头文件<string.h>。原理是遇到'\0'才
停止统计。同理,strlen(arr1)为3,strlen(arr2)为随机值不能确定什么时候遇到'\0',strlen(arr3)
为3.
6.2 转义字符
这里的'\t'构成转义字符,等价于Tab键。
为了展现出换行和空四格Tab键等含义,C语言里用转义字符来代表类似的含义。
\a 警告字符,蜂鸣
\b 退格符
\f 进纸符
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\ddd ddd表示1~3个八进制的数字。 如: \130 对应字符X
\xdd dd表示2个十六进制数字。 如: \x30 对应字符0
\ddd :打印八进制代表的十进制的数字对应的 ASCII码表 的字符
int main()
{
printf("%c\n",'\130');
return 0;
}
//结果:X 因为130八进制 转为十进制为88,根据 ASCII码表得知对应的为X
ASCII码表:所有的数据在存储和运算时都要使用 二进制数表示像a、b、c、d这样的52个字母(包括大写)以及0、1等数字还有一些常用的符号(例如*、#、@等)在计算机中存储时也要使用二进制数来表示,而具体用哪些二进制数字表示哪个符号,美国有关的标准化组织就出台了ASCII 编码,统一规定了上述常用符号用哪些二进制数来表示 。
还有一部分转义字符是为了避免误会让编译器正确打印相关内容在前面加\构成新释义
#include <stdio.h>
#include <string.h>
int main()
{
printf("abc\\tf");
return 0;
}
//想打出\t,避免编译器认成换行符再前面加上\。
\? 在书写连续多个问号时使用,防止他们被解析成三字母词
\' 用于表示字符常量'
\“ 用于表示一个字符串内部的双引号
\\ 用于表示一个反斜杠,防止它被解释为一个转义序列符。
\? : 过去的编译器原来经常会有三字母词,例如??)打印出来是 ],??(打印出来是[。
为了 防止编译器认为??是参与三字母的字母就在?前面加\。
\' \“ 同理,避免编译器认为是代码里的单引号或者双引号
#include <stdio.h>
int main()
{
//问题1:在屏幕上打印一个单引号',怎么做?
//问题2:在屏幕上打印一个字符串,字符串的内容是一个双引号“,怎么做?
printf("%c\n", "\'");
printf("%s\n", "\"");
return 0;
}
思考练习:
#include <stdio.h>
int main()
{
printf("%d\n", strlen("abcdef"));
printf("%d\n", strlen("c:\test\628\test.c"));
return 0;
}
//结果为14,后面跟着两个八进制的数,\62被解析成一个转义字符
6. 3注释
1. 代码中有不需要的代码可以直接删除,也可以注释掉
2. 代码中有些代码比较难懂,可以加一下注释文字
注释有两种风格:
C语言风格的注释 /*xxxxxx*/
/*
调用add方法
*/
缺陷:不能嵌套注释,系统不会匹配对个/**/,只会找到最近的*/,并注释它之前的所有代码。
C++风格的注释 //xxxxxxxx
可以注释一行也可以注释多行
//调用Add函数,完成加法
7. 选择语句
我们经常会面对不同的选择,如果此时选择保存,电脑会保存文件并退出,选择不保存,电脑就会做出不 同处理。 生活中解决问题时经常需要选择性给机器下命令,意味着编程时就要有选择语句。分不同情况去 下不同的指令。
选择语句有两种实现,一种是if else,一种是switch
if-else
#include <stdio.h>
int main()
{
int coding = 0;
printf("你要保存文件吗?(选择1 or 0)");
scanf("%d", &coding);
if(coding == 1)
{
prinf("文件保存成功\n");
}
else
{
printf("成功退出\n");
}
return 0;
}
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age < 18)
printf("少年\n");
else if (age >= 18 && age <= 30)
printf("青年\n");
else if (age >= 31 && age <= 45)
printf("中年\n");
else if (age >= 46 && age <= 60)
printf("壮年\n");
else if (age >= 61 && age < 90)
printf("老年\n");
else
printf("老寿星\n");
return 0;
}
switch:
#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
int n = 1;
switch (day)//整型表达式
{
case 1: //case 后必须是整型常量表达式
printf("星期1\n");
break;
case 2:
printf("星期2\n");
break;
case 3:
printf("星期3\n");
break;
case 4:
printf("星期4\n");
break;
case 5:
printf("星期5\n");
break;
case 6:
printf("星期6\n");
break;
case 7:
printf("星期天\n");
break;
default:
printf("输入错入");
break;
}
return 0;
}
8.循环语句
生活中,我们经常会重复干一件事,
意味着编程时就要有循环语句
去避免同样功能的代码写很多次。
比如打印要100这个数字200遍,我们不可能去写200行打印代码。
C语言的循环语句有三种,for ,while,do while
while:
语法结构
while(要循环满足的条件)
{
//循环要做的事
}
int i=0;
while(i<10)
{
printf("%d ",i);
i++;
}
//运行结果:0 1 2 3 4 5 6 7 8 9
for:
语法结构
for(初始值; 要满足的条件; 改变控制条件真假的变量)
{
//循环要做的事
}
int i=0;
for(i=0;i<10;i++)
{
printf("%d",i);
}
//运行结果:0 1 2 3 4 5 6 7 8 9
两者相似:
do while:
语法结构
do {
初始值
//循环要做的事
改变控制条件真假的变量
}while(要满足的条件)
int i=0;
do{
printf("%d",i);
i++;
}while(i<10)
//运行结果:0 1 2 3 4 5 6 7 8 9
有些时候我们可能循环到一半会满足了某个条件而停止循环,所以循环语句里还设计了中断和结束的语句, break和contine,goto,这个久比较复杂需要具体学习,在会出具体介绍。
9.函数
类似数学里的函数 f(x)=2X+1,实现计算的对应的值的功能 也可以看成是一个一个封装的加工工
厂,收到原材料以后送出加工好的产品。
函数定义 创建工厂
格式:main函数也是函数的一种
函数调用 使用工厂
应用:求和函数
#include <stdio.h>
int Add(int x,int y)
{
return x+y;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b); //scanf也是库函数 功能将输入的值付给对应的变量
//使用格式: scanf("格式控制符", &变量名);
int sum = Add(a,b);
printf("%d\n", sum);
return 0;
}
补充:scanf 一个库函数
功能:从键盘输入俩数在屏幕打印两数之和
vs里的scanf:
如果直接使用会报错
'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To
disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
解决方案:
1):用scanf_s代替scanf
2):在最前面加上一行话:#define _CRT_SECURE_NO_WARNINGS 1 如果想
要以后系统自动加上这句话,可以在电脑里找到 newc++file.cpp这个文件打开后在文件里加人这 句话。找这个文件可以在文件资源管理器自己搜也可以下载一个everything来找,everything一
个本地文件查找器,很方便的工具。
函数作用
函数的特点就是简化代码,代码复用。函数用于封装实现某一功能的代码,在一个项目
会多次要用函数功能时,利用函数不但可以避免代码的冗余 ,也好检查bug。
10. 数组
生活中需要存储大量的数据,比如一个学校的成绩,不能创建几千个变量,过于复杂。要存储大
量的数据,怎么存储?C语言中给了数组来解决这个问题。数组指的是可以存放一组相同类型元素
的集合类型。
数组定义
不初始化定义:
int arr1[10]; char arr2[3]; double arr3[5];
定义并初始化:
int arr[7] = {1,2,3,4,5,6,7};//定义并初始化一个整形数组10个元素分别为 12 3 4 5 6 7
int arr[10] = {1,2,3,4};//定义并初始化,前四个被初始化,后面未被初始化为0
不规定大小初始化:
int arr[]={1,2,3,};//定义整形数组3个元素分别为 12 3 ,系统根据后面个数创建对应大
小数组
数组的下标
C语言规定:数组的每个元素都有一个下标,下标是 从0开始 的。 数组可以通过下标来访问的。如果数组10个元素,下标的范围是0-9
//arr[3]就是拿到了该数组的下标为3的元素。
int arr[8] = {1,2,3,4,5,6,7,8,};
arr[3]=100;//4变成了100
数组的使用
#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++)
{
scanf("%d ",& arr[i]);
}
for(i=0; i<10; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
11.操作符
11.1算术操作符
+ – * / %
/除法:得到的结果类型与两边的类型有关 两边都是整型,结果为整型 两边有一个小数,结果为小数。
//7,2两边都是整型,结果为整型 7/2 =3余下1 结果为3
%取余:
printf("%d",7%2);//结果为1,因为7除2余1
11.2移位操作符
>> 右移 << 左移
11.3位操作符 位:二进制位
& 按位与
^ 按位异或
| 按位或
~按位取反
移位操作符和位操作符都是针对变量的二进制位进行操作的。比较复杂,会在后面具体介绍。
11.4赋值操作符
=
+= -= *= /= &= ^= |= >>= <<= 复合赋值符
a+=5 —> a=a+5
a-=5 —> a=a-5
a*=5 —> a=a*5
&= ^= |=这三个后面学了&,^,就自然会懂啦。
11.5单目操作符 (+加号左右两边都是操作数为双目操作符,单目操作符为只有一个操作数的符号)
! 逻辑反操作
– 负值 //+ – 与数学中的正号 负号一样
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
— 前置、后置–
++ 前置、后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
//c语言里逻辑的真假有两种:
对于数字而言,0的逻辑是假,非0数字代表真。如果逻辑为真打印时统一用1 逻辑为假统一用0
对于命题而言,命题对的就是真否则为假
int a=3;
printf("%d",!a) //a 非0真 !a为假 输出结果0
int a=0;
printf("%d",!a) //a 0假 !a为真 输出结果1
&和*涉及指针,在后面讲更便于理解
sizeof计算对应变量类型的内存大小 单位 字节
sizeof 不是函数而是操作符所以有:
sizeof a sizeof(a) 两种写法 后面放变量()可以省略
sizeof(int) 后面放类型()不能省略
sizeof(arr) 数组所占空间总大小
计算数组元素个数可以sizeof(arr)/sizeof(arr[1]);
sizeof与strlen
sizeof是操作符,不关注内容只关注内容字节大小
strlen库函数,关注'\0'的位置
++ :
使得值加一 分为前置++和后置++
后置++ 先进行其他的操作如赋值等再进行加操作
int a=10;
int b=a++;
printf("%d %d",a,b);
//结果: 11 10 后置++,先进行赋值操作后再使得a+1
前置++ 先进行加操作再进行其他的操作如赋值等
int a=10;
int b=++a;
printf("%d %d",a,b);
//结果: 11 11 前置++,先使得a+1后再进行赋值操作
–是同样的
注意:
b=(++a)+(++a) +(++a) 类似的题目都是不正确的,不同的编译环境的执行顺序不同结果是不 同的,我们应该避免这种有争议的代码。有的编译器可能先算三个()里面的自增,有的先算一 个()再加再算括号。
(类型)
强制类型转换 把后面的变量转换成()里的类型
int a=3.14//类型不匹配,报错
int a=(int)3.14 //把小数强制装换为int 后面的小数不管有没有大于0.5一概舍掉
11.6关系操作符: 用于比较大小 与数学里的用法一样,部分写法不同
>
>=
< <=
!= 用于测试“不相等”
== 用于测试“相等”,与赋值号不同“=” 注意区分
11.7逻辑操作符
&& 逻辑与 两个为真才为真
|| 逻辑或 两个为假才为假
注:C语言里要表达18>age>10需要使用&&不能直接用数学表达式
11.8条件操作符
exp1 ? exp2 : exp3 三目操作符
可以简化一些代码 整体结果和第一个表达式真假有关
int max=0;
//第一种
if (a < b)
max = b;
else
max = a;
//第二种,更简化
int max=a>b?a:b;
逗号表达式
exp1, exp2, exp3, …expN
从头开始计算,最后的一个表达式作为最后的结果
从第一个开始执行,最后执行a=c+3,赋值表达式的最后结果是那个变量的值,而a为-1,最后a=c+整体结果为-1,d=-1。’
11.9下标引用、函数调用和结构成员
[]
()
. -> //ps:最后两章会具体讲
下标引用:
int arr[]={1,2,3,4,5,6,7,8,9} int a=arr [ 7 ] ;
双目操作符, arr 和 7都是操作数
函数调用:
12.常用关键词
归纳以后可以分为四类:
char short int long float double struct enum union 类型
const unsigned signed extern static typedef void sizeof auto 与类型有关,修饰和操作类型
if else while for goto switch case continue break default do 与选择循环等结构有 关
register return volatile 其它
红体是还没讲到的:
struct,enum和 union:三个自定义的类型 结构体,枚举,联合体,会在后面具体介绍。
unsigned和 signed : 用于修饰变量 前者表示无符号后者表示有符号,涉及二进制的表示,后面精讲。
static:用来修饰变量和函数的
1. 修饰局部变量-称为静态局部变量
#include <stdio.h>
void test()
{
int i = 0;
i++;
printf("%d ", i);
}
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
test();
}
return 0;
}
//222222222
//i局部变量,进入函数会创建i赋值1,出了函数被销毁
#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;
}
//2 3 4 5 6 7 8 9 10 11
结论:
static修饰局部变量使得局部变量变成了静态变量。
改变了变量的生命周期,让静态局部变量出了作用域依然会一直存在,到程序结束,生命周期才
结束。生命周期变长了,作用域不变。而且只会在编译最开始创建一次,不会反复创建,进入函
数时直接跳过这一行代码编译。
2. 修饰全局变量-称为静态全局变量
全局变量具有外部链接属性的,可以被其他源文件访问,各个源文件可以链接到一起完成程序。一个全局变量被static修饰,使得这个全局变量失去了外部链接属性变成内部链接属性。只能在本源文件内使用,不能在其他源文件内使用。
3. 修饰函数-称为静态函数
一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。
typedef:自定义类型 (type 类型 define定义) 可以理解为类型重命名。
typedef unsigned int unit;
unit a=10;//unsigned int过于长给他一个别名,以后定义这样的类型就可以使用重新定义的 // 名字。以后学习链表等也会经常用来定义。
void:用在函数里面表示没有返回值
void add(int a,int b)
{
printf("%d",a+b);
}
auto:自动 的意思,修饰变量,一般都不会写。所有的局部变量都是自动变量,自动创建和销
毁。
register :寄存器关键词 寄存器是计算机上的一种存储设备,可以高速访问和处理数据。 用来 修饰变量请求编译器让变量a直接放在寄存器里面,追求速度快。但最后不一定会被放入寄存器 。在c语 言中,由register修饰的变量不能取地址。现在的编译器会自动地决定是否放置,加不加都无所
谓。
volatile:就是防止编译器对代码进行优化。
13. #define 定义常量和宏
//define定义标识符常量
#define MAX 1000
//define定义宏
宏:和函数很像,都有参数,都可以实现一定功能
#define ADD(x, y) ((x)+(y))
int Add(int x, int y)
{
return x + y;
}
int main()
{
int i = 0;
int j = 0;
scanf("%d %d",&i,&j);
int sum1=Add(i,j);
int sum2=ADD(i,j);
return 0;
}
宏不用定义类型,实际上是把对应部分的值给替换成定义的后面部分表达式
代码里面的ADD(2,3)被替换成((2)+(3))再进行操作
14. 指针
内存
内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。
所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元 的地址。通过地址就可以找到空间存储的东西。 对于机器来说,地址的确定是通过地址线来确定的。地址线根数有两种。
32位平台有32根地址线,每一根地址线可以有两种状态,通电或者断电,数字信号就是 0/1两种
选择。那么一共有2^32个地址可以用,如
00000000 00000000 00000000 00001001 为了方便表示地址一般转换成16进制来表示:
0x 00 00 00 09 //0x用来表示十六进制
同理64位平台一共能产生2^64个地址。
内存单元的编号叫地址也是指针。 变量是创建在内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址 的。变量创建的时候就会开辟空间,并且有自己的地址。
取出变量地址:
#include <stdio.h>
int main()
{
int num = 10;
printf("%p\n", &num); //打印地址,%p是以地址的形式打印 默认16进制
//取出num的地址,&取地址符
//注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地
址)
return 0;
}
地址可以取出来那就需要有东西让地址存起来,以后用这个地址来找到变量从而进行一些操作,
就像手机里存的电话号码一样,先存起来以后有需要的时候用来联系朋友。C语言用来存放地址的
类型叫做指针,该变量叫指针变量。不同类型的地址存放的类型也是不同的。
地址的存储就需要定义指针变量,如整型指针:
int* pa=&num //把整型num的地址取出来放到指针变量pa里面,pa类型int*。
int * pa=&num //把整型num的地址取出来放到指针变量pa里面,pa类型int *。
其中*号表明它是一个指针类型,*号前面指明改地址所存放的变量类型。
类比可以得到:
double num=3.14;
double* pa=# char c='a';
char* pa=&c;
有了地址如何根据地址找到对应变量对变量进行操作?可以使用*(解引用操作符)
#include <stdio.h>
int main()
{
int num = 10;
int *p = #
*p = 20;//*p就是找到了该地址存的变量num. *p==num
return 0;
}
指针变量的大小
指针变量也是变量,那它也有大小。指针变量存的是地址,那存地址需要的空间就是指针变量需
要的空间。
#include <stdio.h>
int main()
{
printf("%d\n", sizeof(char*));
printf("%d\n", sizeof(short*));
printf("%d\n", sizeof(int*));
printf("%d\n", sizeof(double*));% zu 专门打印sizeof大小
return 0;
}
结论:指针变量的大小取决于地址的大小地址多大就需要开辟多大空间
//32位平台下地址是32个bit位(即4个字节)
//64位平台下地址是64个bit位(即8个字节)指针大小与指向的类型大小无关,只和地址大小有
关。32位平台或者64位平台取决于程序要用哪种平台,不取决于机器和编译器,对于机器和编译
器两种平台都有。
15. 结构体
内置类型就能描述单一的名字价格等 int double ,为了描述人等复杂对象描述,c语言提供了非内置类型struct。 结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。
比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息,只用int等类型无法表述,所以
我们可以定义struct Stu。
struct Stu
{
char name[20];//名字
int age; //年龄
char sex[5]; //性别
char id[15]; //学号
};
//自定义的类型,struct Stu就类比int double,两个单词一起等价一个类型
struct Stu s={"zhangsan",18,"boy","2106060103"}; //初始化 类比int num=19;
取到结构体里面信息有两种情况:
//直接用结构体变量获取
.为结构成员访问操作符,相当单独拿到对应的int ,char[]类型等
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语言给出了新操作符->代替
printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps-
>id);
如果要键盘录入来创建信息可以:
scanf("%d %s %s %s",&s.age,s.name,s.sex,s.id); //数组名就代表地址,不用取地址符号。
本文到此就结束了,难以会有错误和存在观点片面的时候,非常感谢读者指正!希望能在这里与大家共同进步!
————————————————
版权声明:本文为CSDN博主「写完这行就睡觉」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_62918577/article/details/125882396