(作为初学者,写博客,便当作学习记录了,写的不妥之处,望见谅)
目录
一: 初识c语言
1.1 c语言发展
机器语言>汇编语言>高级语言(或 非结构化语言>结构化语言>面向对象语言)
1.2 程序功能
1.数据表达
2.流程控制
- (1)顺序控制结构(2)分支控制结构(3)循环控制结构
1.3 算法表示
1.3.1 算法特点
(1)确实性:指令确定(2)有穷性:步骤有穷(3)可行性:能够执行(4)有零个或多个输入 (5)有一个或多个输出
1.3.2 描述算法
(1)文字(2)流程图(3)伪代码(4)程序设计
1.4 c语言特点
(1) 简短紧凑、使用方便(2)运算符丰富(3)可移植性好(4)代码质量高(5)结构化语言
1.5 c语言约束
(1)标识符(2)关键字(3)用户自定义标识符(4)预定义标识符(5)分隔符
1.6 c语言语法成分
(1)常量(2)变量(3)运算符(4)表达式(5)语句(6)函数的定义与调用(7)输入与输出
1.7 其他
- 1.关于在电脑上编写代码,是在下载在电脑上的软件编写具有一定功能的代码(仿佛没说),而软件是开发环境,如Visual C++ 2010、Visual studio 2019等,具体下载浏览器搜索有较好的过程
- 2.代码的敲打,按老师、学长的说法,只有经常练习,同时开始阶段不能看一句敲一句,加油。
- 3.其他的慢慢积累了。
二: 数据类型、运算符和表达式
2.1 数据类型
大概就是:
2.2 c语言中 常量
2.2.1直接常量
①整形常量
(正整数,负整数,零)(可十进制,八进制,十六进制表示)
(1)十进制:0~9 和 + - 组成。
(2)八进制:0(数字)为前缀,0~7 组成,无符号。
(3)十六进制:以0X或0x为前缀,0~9和A~F(表10~15)组成,无符号
(另)整形常量后加个u或者U,为unsigned int型、加个l或者L,为long int型
②实型常量(又称浮点数)(只能十进制,有小数,指数两种表现形式)
(1)小数形式:如1. 、 1.0 、 .1 小数点不能省
(2)指数形式:1.23E-2 (为1.23*10^-2)
- (2.1)E后面必须要有数字,正负号放在E后面
- (2.2)c语言中,浮点数是double型,若数字后面有f,则为float型
③字符型常量('a' 、'B'、 '='、'?'...)
- (1)单引号
- (2)单个符号不是字符串
- (3)一个字符一个字节
- (4)字符对应ASCII
- (5)转义字符是用 '\' 开头后加一个字符或八进制、十六进制表示
④字符串常量
- (1)双引号
- (2)n个字符组成的字符串,占内存加一(内隐藏一个 '\0' , 其不记录长度)
- (3)字符串如遇到 '\0' 表示结束 "HelloWorld"长度为10、"Hello\0World"长度为5
- (4)可以把一个字符常量赋予一个字符变量,但是不能把一个字符串常量赋予一个字符变量
2.2.2符号常量
如:#define 标识符 常量值
- (1)为预处理命令,不加“;”
- (2)目的:①增加程序可读性②提高程序可维护性、容易修改③简化程序代码④方便数组定义
- (3) 一个“define”一个标识符(符号常量)
2.3 c语言中变量
2.3.1变量的定义与使用
(1)格式: 类型说明符 变量名表;
(2)定义类型
- int 整形
- float 单精度浮点型
- double 双精度浮点型
- char 字符型
tip:定义时可以同时赋值(即初始化)
2.3.2 整形变量
- (1)取值范围
- (2)无符号整数所占的字节数与相应有符号整数相同,但是由于省去了符号位,故不能表负数。
- (3)有符号整数以二进制补码形式存储。最左边第一位表示符号,0表示正数,1表示负数。
- (4)无符号整数以二进制原码形式存储。
2.3.3 浮点数变量
- (1)取值范围
- (2)单精度数据保留7位有效数字,双精度保留16位有效数字(超出可能是无效数字)
2.3.4 字符型变量
- (1)字符型变量的值是字符常量,类型说明为 char
2.4 运算符和表达式
2.4.1 赋值运算符和赋值表达式
(1)运算符
- '='、'+='、'-='、'*='、'/=' 和 '%='
(2)赋值表达式
- 一般形式:变量 = 表达式
- 注意:①赋值运算符左侧必须是一个变量
- ②赋值语句末尾必须要有分号
- ③'=' 两边的类型不一样时,会右侧强行转换成左侧(这是的得到的值,但是运行一般为int或相对更大取值范围那个)
- ④赋值运算符具有右结合性
2.4.2 算术运算符和算术表达式
- (1)
p:求余要求参与运算的两个运算对象必须都是整型,其结果也是整型
- (2)特殊运算符
- '++'和'--':对使用的值进行加一或者减一
- 在变量前:先计算(++),后使用(变量)、
- 在变量后:先使用(变量),后计算(++)
- (3)算术表达式
- (应该和数学差不多吧)
2.4.3 逗号运算符和逗号表达式
- (1)一般形式: 表达式1,表达式2,...表达式n
- (2)左往右依次计算,最后一个表达式的值作为整个表达式的值
2.4.4 求字节数运算符
- (1)sizeof(表达式)或sizeof 表达式
- (2) sizeof(数据类型名)
p:指针类的都是4(x32)或者8(x64)、大小为字节。
2.4.5 数据类型转换
- (1)自动类型转换
p:①横向是必定的转换,纵向是横向之后仍然不同的转换(自己不是特别懂)
②类型转换不改变原变量
- (2)强制类型转换
一般形式:(类型说明符)(表达式)
p: 高到低的转换会缺失精度
三 顺序结构
3.1 c语言的语句
(1)说明语句
- 用于定义程序所使用的变量和类型
- 如:int a,b; /*定义两个整型变量*/
- char ch; /*定义一个字符型变量*/
(2)表达式语句
- 一般形式: 表达式;
- p:未加上 ‘ ; ’ 则为表达式(仿佛没讲)
(3)分支语句
- 分支语句实现分支控制过程,根据条件成立与否执行不同的语句。有两种分支结构:if-else和switch
(4) 循环语句
- 3种结构:for 和while 和do-while
(5)转向语句
- 有:break;goto;continue;return;
(6)复合语句
- 用一对大括号{}将若干语句顺序组合在一起所组成的语句称为复合语句
(7)空语句
- 一个分号组成
(8)函数的定义与调用
(9)输入与输出
- (scanf()和printf())
3.2 数据的输入输出
(较复杂的细节在平常见到的代码中能够很好的了解到,开始不用了解太多)
(1)printf()函数
printf("格式控制字符串",输出项表列)
(2)scanf()函数
scanf("格式控制字符串",输入项列表)
(3)整型数据的输入和输出
(4)浮点型数据的输入和输出 
(5)字符型数据的输入和输出
(1)scanf()和printf()
- p:printf("%c%c\n",a,b)可在%与c之间加修饰符,同表3.2.2和表3.2.3
(2)getchar()和putchar()
- ① ch = getchar() 运行时从键盘缓冲区读取一个字符赋值给ch。
- ② putchar(输出参数) 输出一个字符 (字符型变量或字符型常量)
四 分支结构
4.1 关系/逻辑/条件运算符
①关系运算符:> ; >= ; < ; <= ; == ; != ;
- 关系表达式: 表达式1 关系运算符 表达式2
②逻辑运算符:
- && 逻辑与 (两边都为真时得真)
- || 逻辑或 (两边都为假时得假)
- ! 逻辑非 (真得假,假得真)
- 逻辑表达式:表达式1 逻辑运算符 表达式2 或者 逻辑运算符 表达式1
- p:一般&&左边为假,那右边便不考虑了,||左边为真,右边也不考虑了
③条件运算符:? ;
- 条件表达式: 表达式1?表达式2;表达式3
4.2 if-else实现分支
(1)双分支if语句
- 一般形式:if(表达式)
- 语句1;
- else
- 语句2;
(2)单分支if语句
- 一般形式: if(表达式)
- 语句;
(3)嵌套:
- 复合一下就好了
- p:else只是寻找其上最近得未与else配对的if进行配对,合适的缩进,或者{}可减少争议
(4) 多分支if语句:
- if(表达式1)
- 语句1;
- else if(表达式2)
- 语句2;
- ...
- else if(表达式n-1)
- 语句n-1;
- else
- 语句n;
4.3 switch语句实现分支
(1)一般形式:
- switch(表达式)
- {
- case 常量表达式1:语句1;break;
- case 常量表达式2:语句2;break;
- ...
- case 常量表达式n:语句n;break;
- default:语句n+1;break;
- }
p:每个case分支下应该带上break;若没有,则会继续执行下去,直到结束或者碰到break
五 循环结构
5.1 for语句实现循环
(1)一般形式:
- for(表达式1;表达式2;表达式3)
- 循环体语句;
(2)执行 :
- 先表达式1(初始化 仅一次) ,
- 然后表达式2(每次循环都判断),
- 为真进入循环语句体(为假跳出循环),
- 然后表达式3(修改循环变量),
- 再进入表达式2...
p:
- (遇到break跳出这整层循环,遇到continue跳过这次循环)
- (for()括号里的分号不能省!!)
- (表达式1,3某些情况可以省)
5.2 while语句实现循环
(1)一般形式:
- while(表达式)
- 循环体;
(2)
- 执行: 表达式判定,真便进入循环体
p :循环体中应当改变循环变量,避免进入死循环
5.3 do-while语句实现循环
(1)一般形式:
- do
- 循环体;
- while(表达式)
(2) 执行:
- 先执行循环体,再判断 (循环体改变循环变量)
5.4 改变循环结构的跳转语句
- (1)break 跳出
- (2)continue 跳过
- (3)goto 跳至...(goto语句标号),语句标号是有效标识符,其后跟一个“:”(建议少用)
5.5 嵌套
- 复合即可,不可交叉,内外循环一般不相干,注意循环变量
六 数组
6.1 一维数组
(1)一般形式:
- 类型名 数组名[常量表达式]; 如 int arr[10];
提示 :
- ①常量表达式 表示数组元素的个数(长度),不能是变量
- ②方括号[]
- ③数组元素下标从0开始,最大值为长度减一
(2)一维数组元素的引用
- 数组名[下标]
(3)一维数组的初始化
一般形式:
- 类型名 数组名[数组长度] = {初值表}
- 如:int a[] = {6,1,4,5,8,9} ; int a[2] = {1,2};
提示:
- ①定义数组没有对其初始化,则数组长度不能省略
- ②静态存储(未初始化,赋值0) static int a[3]; 相当于 static int a[6]={0,0,0};
- 动态存储(未初始化 ,赋值未知数)
- ③可以只是赋值数组的前几个元素
- ④初值个数小于长度
- ⑤别忘记{}
- ⑥初值表不能是变量
6.2 二维数组
(1)一般形式:
- 类型名 数组名[常量表达式1][常量表达式2] ; 如 int a[3][4]
(2)引用:
- 数组名[行下标][列下标]
(3)初始化:
- 类型名 数组名[行数][列数] = {初值表}
- 如:int a[][4] = {1,2,3,4,5,6,7,8,9};
6.3 字符数组
(1)
- 一维字符数组的一般形式:char 数组名 [常量表达式]
- 二位字符数组的一般形式: char 数组名 [常量表达式1][常量表达式2]
初始化 : char 数组名 [常量表达式] = {初值表} ;
p:①不能在定义数组以后,对数组进行赋值
6.4 字符串
(1)字符串的存储
- ①n个字符组成的字符串,占内存加一(内隐藏一个 '\0' ,其不记录长度)
(2)字符串的输入和输出
- 除了getchar(),putchar(),scanf()和 printf() 可以输入输出字符串,还有gets(),puts()
- ① gets(字符数组名)
char str[80]; gets(str);
- 键盘输入: How are you?则str中的字符串是“How are you?”
- 该函数可以将键盘输入的一行字符以字符串的形式存放到一个字符数组中,只能输入一个字符串
- ② puts(字符数组名)
- 该函数可以将一个字符串(以'\0'结束的字符序列)输出到屏幕,输出后自动换行
6.5 字符串处理函数
(1)复制函数: strcpy(字符串1,字符串2)
- ①字符串2 可以是字符数组名,也可以是字符串常量,但是1 必须是字符数组名
- ②1 要有足够的空间容纳2
- ③复制时碰到2 中的“\0”停止
- ④若要复制2 中的前n给字符可以用 strncpy(字符串1,字符串2,n)
(2)连接函数: strcat(字符串1,字符串2)
- ①字符串2 可以是字符数组名,也可以是字符串常量,但是1 必须是字符数组名
- ②1 要有足够的空间容纳2
- ③碰到2 中的“\0”停止
(3)比较函数: strcmp(字符串1,字符串2)
- ① 1<2 返回值小于0
- ②1=2返回值等于0
- ③1>2返回值大于0
- ④比较规则是从首字符串开始,依次比较对应字符的ASCII码,到‘\0’为止。如果所有的字符都相同,返回0;否则,以第一个不协调字符的比较结果为准,返回则两个字符的差。
(4)求字符串长度函数: strlen(字符串)
- ①计算长度,不包括 '\0'
(5)大写字母转小写字母函数:strlwr(字符串)
(6)小转大函数: strupr(字符串)
七 函数
7.1 概述
(1)
- 1.所有c语言都是由一个或者多个函数构成的,函数完成其中某种功能。
- 2.c语言规模小时,一个源文件来实现。规模较大时,可以由多个源文件组成,但是只有一个源文件含有主函数main(),其他源文件不能包含主函数。
- 3.主函数可以调用其他函数,反过来则不能。其他函数则可以相互调用,一次或多次。
- 4.一个函数调用另一个函数,前者叫调用函数,后者叫被调函数。
(2) 函数分:
- 标准函数和自定义函数
- 无参函数和有参函数
- 外部函数和内部函数
7.2 函数定义
(1)无参函数的定义
- 类型名 函数名()/*函数首部*/
- {
- 函数体
- }
或者
- 类型名 函数名(void) /*函数首部*/
- {
- 函数体
- }
void类型的函数不直接返回值,只是完成某一特定功能
(2)有参函数的定义
- 类型名 函数名(形式参数列表)/*函数首部*/
- {
- 函数体
- }
形式参数格式:
- 类型1 形参1,类型2 形参2,...,类型n形参n;
(3)空函数的定义
类型名 函数名()
{}
7.3 函数调用
(1)一般形式和调用方式
一般形式:
- 函数名(实际参数列表)
方式
- ①函数语句(完成一定功能,不做返回值)
- ②函数表达式(以函数返回值参与表达式的运算)
- ③函数嵌套
(2) 参数传递
- 1. 调用有参函数,调用函数与被调函数存在数据传递关系。主要通过参数进行的,一般是由return语句来实现的。
- 2. 形参是函数定义时函数名后面括号中的变量;实参时指调用函数时函数名后面括号中的常量、变量、或表达式。在调用函数时将实参的值传递给形参,使形参的数值与实参相同。
3. 两种传递方式
(1)按值传递
- ①实参的个数,数据类型,应与形参一样
- ②只有函数调用时才会分配存储单元,定义时不会。调用结束时存储单元释放
- ③实参形参即使同名,也会分配不同的存储单元
- ④参数传递是值传递
(2)按地址传递
- 当函数的形参为数组或指针类型时,函数调用的参数传递成为按地址传递。
- 由于传递的是地址,使形参与实参共享相同的存储单元,这样通过形参可以直接引用或处理该地址中的数据,达到改变实参的目的。
(3)函数的返回值
return 表达式;
return (表达式);
- ①只能从被调函数中返回一个函数值
- ②不需要返回值,可以省略return
- ③返回类型应与函数类型一样,(函数类型决定返回值类型,所以定义函数时指定好类型)
- ④void类型,不能拿使用return
(4)函数声明
先声明后使用
格式:
- 类型名 函数名(参数类型1,参数类型2,...)
- 类型名 函数名(参数类型1 形参1,参数类型2,形参2,...)
(5)函数的嵌套使用
- 函数的定义是,互相平行的独立的,就是说函数的定义不能包含另一个函数的定义。而调用过程中又可以调用另一个函数,调用称为嵌套。
7.4 递归函数
(1)概念:
- ①自己调用自己,直接递归调用;通过函数调用自己,间接递归函数。
- ②构造递归函数的关键是寻找递归算法和递归的终止条件。
(2)两个条件:
- ①问题简化为一个新的问题,解决方法仍然相同(寻找递归表达式)
- ②结束条件(寻找递归出口)
(3)调用过程两个阶段:
- ①递推阶段
- ②回归阶段
7.5 数组作为函数的参数
(1)数组元素做函数实参
- 与普通变量相同
(2)数组作函数参数
- c语言中,数组名代表数组首元素地址,数组名作为函数的参数,此时形参和实参所指向的是同一块存储单元(形参可以改变实参)
- 格式:
- 函数名(数组名)
(3)一维数组作函数参数
- 形参数组无需指定大小,但数组名后面的方括号不能省略
(4)二维数组作函数参数
用数组名作函数参数与用数组元素作函数实参的几点不同:
- ①数组元素:数组类型和函数的形参变量的类型一致即可。
- 数组名:要求形参和相对应的实参都必须是相同的类型
对数组作为函数参数几点注意:
- ①形参数组和实参数组的名称不要求相同但必须类型一样
- ②形参数组和实参数组的长度可以不同,但不提倡
- ③在函数形参表中,允许无形参数组长度,可以增加一个变量表示数组元素个数
- ④二维数组作函数的参数时,形参数组第一维度的长度可以省略,但是第二维度的长度不能省略
- ⑤函数调用中形参和实参的取值和关系:
7.6 局部变量与全局变量
(1)c语言只允许在3个地方定义变量
- ①函数内部的声明部分
- ②所有函数的外部
- ③复合语句中的声明部分
(2)局部变量
- 尽量为了更好的阅读给变量定义
- ①不同的函数或复合语句中可以使用相同的变量
- ②主函数定义的变量只能在主函数使用,主函数也不能使用其他函数定义的变量
- ③形参也是局部变量
- ④复合语句中只能在当前复合语句中使用
- ⑤编译系统并不检查函数名与局部函数是否同名
(3)全局变量
- ①定义:同一作用域只能定义一次,在所有函数之外,系统会根据定义分配存储单元。初始化在定义时进行
- ②声明:说明变量在外部定义过,可使用了
- ③如果全局与局部同名,则在局部变量作用域,全局变量没有用(程序对作用域遵循最小作用域原则)
- ④全局变量也是函数间进行数据传递的渠道之一
7.7变量生命期与存储类型
(1)静态存储与动态存储
从变量的生命期分:变量的存储类别分为静态存储方式和动态存储方式
- ①静态:程序运行期间分配固定的存储空间
- ②动态:程序运行期间根据需要进行动态的分配存储空间
(2)变量的存储类别
1.
- c语言中变量和函数有两个属性,即变量的数据类型及变量的存储类型。用变量的存储类型说明变量的存储位置。
2. 一般形式:
- 存储类型 数据类型 变量名;
3. 存储类型有:
- ①auto(自动类型)
- ②register(寄存器类型)
- ③static(静态类型)
- ④extern(外部类型)
(3)介绍
1.auto
自动变量
形式:
auto 类型名 变量名;
2.register
也是自动变量
3.static
静态变量
(1)形式:
static 类型名 变量名;(2) 如果函数中局部变量的值在函数调用结束后仍然能保留,便于下一次调用时使用,可以定义为static 类型。
(3)静态局部变量,生命周期与全部变量相同,作用域与局部变量相同。
(4)静态局部变量和自动变量注意
- ①静态编译时赋初值,只赋值一次,自动每调用过一次赋初值一次
- ②自动没有赋初值,初值是不确定的,静态不赋初值则自己赋0,后面调用值为前一次调用保留的值
- ③没静态保存的要求,补建议使用
4.extern
外部变量
形式:
- extern 类型名 变量名;
7.8 内部函数与外部函数
(1)内部函数
- 如果一个函数只能被文本中其他函数调用,则函数称为内部函数
定义格式:
- static 类型名 函数名(形参表);
- 减少与外部相同名字函数的干扰
(2)外部函数
允许被文本外函数调用
定义格式:
- extern 类型名 函数名(形参表);
另:
- 外部函数在整个源文件中都可以使用。
- c语言中,省略extern,默认为外部函数。
- 外部函数定义后,要在调用此函数的程序文件中使用extern声明所使用函数的原型,表示被定义。
八 指针
- 在c语言中,使用指针来标示变量在内存中的位置。
- 指针与变量的关系类似于门牌号码与房间的关系。
8.1 指针与指针变量
8.1.1地址与指针
(1)内存的使用方法
- ①内存以字节为单位,一个字节就是一个内存单元,每个内存单元都有一个不重复的编号,称为内存地址,是一个无符号整数
- ②单个变量(包括数组)按照其数据类型分配一个或者多个内存单元,这些内存单元内存地址上是连续的,变量的值存放在这些内存单元中
- ③分配给单个变量的内存单元中,第一个内存单元的地址称为变量的地址或者首地址
(2)指针就是某个对象所占用的内存单元的首地址
8.1.2 指针变量的定义与初始化
(1)定义的形式:
- 类型名* 指针变量名[=地址];
- (类型名是指针变量所指对象的类型;*是用于区分指针变量和其他变量的字符;)
(2)指针初始化(赋值)的方法:
①指针指向变量
- 指针变量名=&变量名;
②指针指向数组
- 指针变量名=数组名;
③指针初始化其他同类型指针变量
- 指针变量名1=指针变量名2;
④指针可以被初始化为0或NULL
- 指针变量名=0(NULL);
8.1.3 指针变量的引用
(1)访问指针所指对象的运算符
- ① * :间接访问(引用)运算符
- ② [] :下标运算符
注意:
- ①定义指针变量时, * 号表示其后是指针变量。其他位置是运算符(乘号或者间接访问运算符)
- ② * 与 & 作用正好相反,& 取变量地址,* 则取指针所指对象的值(在表达式中,若p指向a,则p与&a等价,*p与a等价)
8.2 指针与函数
8.2.1 指针作函数的参数
- (1)指针作为函数的形参时,在形参寿命时需要使用“类型名 *指针名”,*不能省略,而在函数定义的说明部分,*号的作用是类型说明符。
- (2)指针作为函数参数,在定义,声明和调用时,数据类型都必须一致;
- (3)指针做函数的形参时,函数可以修改指针所指对象,一个函数可以获得多个返回值,只要在定义这个函数使用多个指针变量作为形参即可
8.2.2 返回指针值得函数
- 数据类型名 *函数名(参数表)
- 如
int *max(int n);
- max是函数名,n是函数max()的形参,函数名前面的* 表示调用该函数返回一个整形数据的指针(地址)
8.2.3 指向函数的指针
- 类型名 (*指针变量名)(参数表)
- 如
int (*pc)(int,int); /*定义指向函数的指针pc,限定pc所指函数有两个整型参数*/ int ave(int a,int b); /*声明两个整型参数的函数*/ pc=ave; /*指针pc指向ave*/
- 如果目标函数没有返回值,则定义void(*pc)().
- 定义了指向函数的指针以后,必须将一个函数名(函数的入口地址)赋值给函数指针,然后才能用函数指针间接调用该函数。
8.3 指针与一维数组
8.3.1 关系
- (1)数组中的元素按顺序存放在地质连续的内存单元内,每个数组元素都有各自的地址,数组名是数组首元素的地址。对数组元素的访问,可以使用下标,也可以使用指针变量,移动指针可以指向数组数组中的任意一个元素。
- (2)数组名是指针常量,不能进行运算操作
8.3.2 指针的运算
(1)指针加减整数的运算
- 结果是地址。指针加减n,其结果是第n个元素的首地址,指针变量的值不变。
(2)指针自加和自减运算
- 结果是地址
(3)指针的关系运算
- >、<、==、!=
- 比较前后,是否同一元素
(4)指针相减运算
- 只适用于两个指针所指对象在同一数组中的情况,用于获得两个指针间有多少个元素。
(5)指针表达式
- 根据实际情况结合表达式与结合性理解
8.4 指针与二维数组
8.4.1 关系
- (1)二维数组与以为数组一样也是连续存储。
- (2)对于二维数组名a,虽然a与a[0]所代表的值都是2000,但二者的类型是不同的,数组名a为列地址,a[0]为行地址。+1后地址不一样。
注意:
- (1)行地址指向二维数组的一行,无法访问二维数组的元素,必须转换为列地址,行列地址的转换方式为:行地址前加“ * ”,将变为列地址,如a为行地址,*a为列地址;列地址前加“&”将变为行地址,如:a[0]为列地址,&a[0]为行地址。
- (2)将行列地址作为指针使用时,行地址即为行指针,指向的对象即为一个一维数组而非数组中的具体元素;列指针即为列地址,用于指向一维数组中的具体元素。
- (3)a[i][j] 的等价表达式有三种:
- ①a[i][j] (下标法)
- ②*(a[i]+j) (指针法)
- ③*(*(a+i)+j) (指针法)
8.4.2 指向二维数组元素的指针
(1)格式如下:
- ①*指针变量名=&二维数组名[行下标][列下标]
- ②*指针变量名=*二维数组名
- ③*指针变量名=二维数组名[行下标]
- 行下标和列下标都为0时,则指针变量指向二维数组首元素地址
8.4.3 指向二维数组的行指针变量
(1)声明行指针变量的一般格式:
- 类型名(*指针变量名)[n]
- n表示二维数组分解为多个一维数组的长度,也就是所指向的二维数组的列数。格式中,()号,*号和[n]都不能省略。
- 注意:行指针变量用于指向一行数组元素的起始位置,而非数组中的元素。定义后指针变量以后,需要将二维数组的首地址赋给行指针变量,以便访问元素。
8.5 指针与字符串
8.5.1 字符串与字符指针
- 字符指针的使用方法:
char *str = "hello"; puts(str);
- 字符串“hello”在内存中以字符数组形式存储,语句“char*str=hello;”的含义是指针str指向字符串“hello”的首字符,这里的“=”号表示将字符串“hello”的第一个字符的地址赋给str
- 如
8.5.2 使用字符数组与字符指针处理字符串的区别
- (1)赋值方法不同
char *str; //这是正确的 str ="hello";
char str[10]; //这是错误的 str = "hello";
- 字符指针指向的是hello的首地址
- 字符数组名str为一常量地址,不能被赋值
(2)系统为其分配内存单元的方法不同
- 字符数组定义后,系统分配一段连续的内存单元,字符数组名为内存单元的首地址;
- 字符指针变量定义以后,系统为其分配一个存放指针值(地址)得内存单元,其指向的对象并不明确。
(3)修改值(地址)的方法不同
- 字符指针可以修改,字符数组名只能被引用,不能被修改。
8.6 二级指针与指针数组
8.6.1 二级指针
- 类型名 **变量名
很套娃,简单理解就好8.6.2 指针数组
- 存放指针
- 类型名 *数组名[数组长度]
- 定义时完成相关初始化操作
8.6.3 main函数的参数
- c语言中main函数通常是没有参数的,但也可以有参数声明方式:
- main(int argc,char *argv[])
- argc表示main所接受参数的个数;字符指针数组*argv[]指向命令行中的程序名和参数字符串,main函数参数需要在命令行给出
九 结构体
9.1 概念及定义
(1)一般形式:
- struct 结构体
- {类型名 成员名1;
- 类型名 成员名2;
- ...
- 类型名 成员名n;
- };
说明:
- ①关键字struct与结构名一起构成结构类型名
- ②大括号中的内容是结构所包括的成员
- ③定义并不分配空间,在用结构类型定义了结构变量后才会分配空间
- ④定义结构类型时,不允许将成员的数据类型定义成自身的结构类型(系统不知道分配多少空间)但是可以含有指向自身类型的指针变量
- ⑤结构与数组的区别:数据数目固定、具有相同数据类型的有序数据的集合;结构是数目固定、不同数据类型的有序数据的集合(结构可以有数组,数组中每个元素也可以是同一个数据结构)
- ⑥c语言把结构的声明看成是语句,后面需要有分号
struct books //定义一个结构类型
{
int bno;
char bname[20];
char field[10];
char author[10];
char publisher[30];
float price;
};
(2)结构的嵌套定义
嵌套...
9.2 结构变量
9.2.1 定义与初始化
(1)类型和变量是不相同的,变量可以赋值、存取、运算;而类型不可以。因此在声明结构类型后,还需要定义结构变量。
三种定义方法
- ①先定义结构类型,在定义结构变量
- ②定义结构类型同时定义结构变量
- ③直接定义结构变量
(2)结构变量的初始化
- 一般形式:在定义变量的后面加上“={初值表列};”即在一对花括号中分别列出结构变量中各成员的初始值,逗号隔开。
注意:
- ①初始化,需要按照其成员出现的顺序对每个成员依次赋值,不能跳过
- ②不能在结构内部给成员赋值
9.2.2结构变量的引用
- 结构变量名.成员
注意:
- ①可以引用结构变量成员的地址,也可以引用结构变量的地址
- ②对结构中数组成员的引用也是通过逐个引用数组元素来实现的
- ③相同类型的结构变量之间可以进行整体赋值,但不能进行关系运算
- ④结构变量可以作为函数参数或返回值
9.3 结构数组
9.3.1结构数组的定义与初始化
(1)定义
- 与结构变量类似
struct books { int bno; char bname[20]; char field[10]; char author[10]; char publisher[30]; float price; }; strct books book[5];
- 结构数组book共有5个元素,book[0]~book[4],每个数组元素都具有struct books的结构类型
(2)初始化
- struct 结构名 数组名[元素个数]={初值表列};
9.3.2 结构数组的使用
(1)几种形式
- ①结构数组名[下标].成员
- ②(*(结构数组名+下标))。成员名
- ③(结构数组名+下标)->成员名
其中:
- “.”的优先级高于“*”,“->”的优先级与“.”相同
9.4 结构指针
9.4.1 概念
- 指向结构变量的指针叫做结构指针
形式:
- struct 结构名 *指针变量名;
- 结构指针也需要先赋值后在使用(把结构变量的首地址赋给结构指针)
三种访问结构变量的成员的等价形式:
- ①结构变量名.成员名
- ②(*结构指针变量名).成员名
- ③结构指针变量名->成员名
9.4.2 指向结构数组的指针
- 指向的是数组的首地址
9.4.3 结构指针作函数参数
- 要求对应的形参是一个同类型的结构指针,此时实参先形参传递的是结构指针的值(地址)
- 效率高
10.结尾
文章参考《c语言程序设计》,所写下的也并不完全正确与全面,只是个人的一些理解。真正需要掌握的需要我们更多的钻研和练习。加油吧。