C语言学习笔记

1、F4指出error 、 Alt+F8用于自动对齐、shift+tab前移, 去除左边的查找标记ctrl+shift+F2 , Ctrl + F查找【通用的】

2、输出结果显示框,选择标记,可以复制输出结果,不必要截屏

3、printf()-----将变量的内容输出到显示器上
四种用法:
1.printf("字符串");
2.printf("输出控制符",输出参数);
3.printf("输出控制符1 输出控制符2 ...",输出参数1,输出参数2...);
输出控制符和输入控制符一一对应
4.printf("输出控制符 非输出控制符",输出参数);
输出控制符包括:%d,%ld,%c,%s,%f,%lf,%x-2f,%X-2F,%#x-0x2f,%#X-0X2F(推荐)
例:printf("i = %d, j = %d ",i,j);
非输出控制符原样输出

4、注释 //或者/* ---*/

5、彻底关闭-----关闭工作空间

6、工具-选项-格式,调整字体

7、编译--链接--执行,编译--链接之后产生一个可执行文件.exe,然后vc软件请求CPU执行该文件,执行之后的结果返回到软件显示

8、ASCII码就是一种硬性规定,字符存储本质上与整数一样

9、字节就是存储数据的单位,并且是硬件所能访问的最小单位,1字节=8位

10、scanf()------通过键盘将数据输入到变量中
两种用法:
1、scanf("输入控制符",输入参数);
功能:将从键盘输入的字符转化为输入控制符所规定格式的数据,然后存入以输入参数的值为地址的变量中。
例:scanf("%d",&i);//&i表示i的地址,&取地址符
2、scanf("非输入控制符 输入控制符",输入参数);
例:scanf("m = %d",&i);//非输入控制符必须原样输入
scanf("%d %d",&i,&j);//前面这个空格不管你敲不敲,你输入的时候必须有空格,作为区分两个int
原则:使用scanf前最好先使用printf输出提示信息;
scanf中尽量不要使用非输入控制符,尤其是 ;
应该编写代码对用户的非法输入做适当的处理
while((ch = getchar()) != ' ')
contiue;

11、运算符

算术运算符------ + - * /(除) %(取余)

关系运算符------ > >= < <= == !=

逻辑运算符------ ! &&(与)左边为假,右边不执行 \(或)左边为真,右边不执行

赋值运算符------ = += *= -= /=

优先级别:
算数 > 关系 > 逻辑 > 赋值

C语言对真假表示:非0为真【1】,0为假【0】

12、流程控制-----------程序代码执行的顺序

分类:顺序执行

选择执行
if
1、if最简单用法
格式: if(表达式)
语句;
2、if的范围问题
if默认只能控制一条语句,若想控制多条语句,需用花括号{}括起来
3、if....else....
4、if....else if.....else....
格式:if(1)
A;
else if(2)
B
else if(3)
C
5、if常见问题分析
1.空语句的问题
if(3 > 2);
等价于
if(3 > 2)
;//这是一个空语句

循环执行

13、文件命名时会自动加后缀.cpp,命名时不要加‘.’,否则系统不会自动加后缀.cpp,程序就没法执行,果需要加点的话,后面一定要加上.cpp

14、程序 = 算法 + 语言,1、流程 2、每个语句的功能 3、试数

15、for的范围为一个语句

16、1/2 = 0,除数和被除数都是整数,结果一定是整数,1.0 / 2 = 0.5,其中一个是小数,结果就是小数
举例1:
int i;
i = 1 / 2;
printf("i = %d ",i);
输出结果:i = 0
举例2:
int i;
i = 1 / 2;
printf("i = %f ",i);
输出结果:i = 0.000000
举例3:

int i;
i = 1.0 / 2;
printf("i = %f ",i);
输出结果:i = 0.000000
举例4:
float i;
i = 1 / 2;
printf("i = %d ",i);
输出结果:i = 0
举例5:
float i;
i = 1 / 2;
printf("i = %f ",i);
输出结果:i = 0.000000
举例6:
float i;
i = 1.0 / 2;
printf("i = %d ",i);
输出结果:i = 0
举例7:
float i;
i = 1.0 / 3;
printf("i = %f ",i);
输出结果:i = 0.333333

17、强制类型转换----------------(数据类型)(表达式)
类型:(int)(4.5 + 2.2) = 6
(float)(5) = 5.000000

18、十进制转化r进制,一直除r取即可余,余数从下往上倒序排序,

19、编程时尽量i++ 和 ++i单独成为一个语句,不要用于复合语句

20、逗号运算符:
(A,B,C,D)
从左到右执行,表达式的值为最后一项的值。

21、while(默认控制一个语句) //内部表达式不一定执行
格式:while(表达式)
语句;

do....while //内部表达式至少执行一次,多用于人机交互
格式:
do
{
........
}while(表达式);//不等价于while和for

22、while与for的比较,二者在逻辑上完全等价,但for的逻辑性更强
for(1; 2; 3)
A;
等价于
1;
while(2)
{
A;
3;
}//注意A和3的顺序不能更换,这是由for的顺序决定的。

23、break用法
1、用于终止循环、用于终止switch、 break不能直接用于if,除非if属于for循环内部的子句,但break终止的还是外部的for循环
2、用于多个for循环时,只用终止距离它最近的循环
3、在多层switch嵌套中,break只能终止距离他最近的switch

24、continue用法
用于跳过本次循环余下的语句,转去判断是否需要执行下次循环

25、数组中的元素就是变量,
用于大量同类型数据的存储与使用,
为多个变量连续分配存储空间,
所有的变量数据类型一致,
所有变量所占的字节大小一致

26、一维数组
完全初始化:int a[5] = {1,2,3,4,5};
未完全初始化:int a[5] = {1,2,3}; //a[3],a[4]自动为0
不初始化:int a[5]; //所有元素为垃圾值
清零: int a[5] = {0};

错误写法:
int a[5];
a[5] = {1,2,3,4,5}; //错误,
只有在定义数组的时候才可以整体赋值,其他情况整体赋值都是错误的
只有在定义数组的时候,‘5’即数字,表示数组长度,其他情况均表示下标,下标从0开始
一维数组名代表第一个元素的地址

int a[5] = {1,2,3,4,5};
int b[5];
把a数组元素赋给b数组的错误写法:b = a;
正确写法: for(i=0, i<5; i++)
b[i] = a[i];


27、二维数组
int a[3][4];//三行四列
a[0][0]-----a[0][3]
-------------------
------- a[2][3]
a[m][n]最大到a[m-1][n-1]

初始化: int a[3][4] = {1,2,3,4.......12};
int a[3][4] = {
{1,2,3,4},
{5,6,7,8},
{.......}
}

28、函数
1、为相似的大量的数据设计,相当于设计的一个工具,有利于程序的模块化 格式:函数类型 函数名 (参数类型 形式参数)
2、每次调用函数随机为形参分配空间,使用完毕,释放空间 int max( int a, int b ) void f (void)
3、函数返回值的类型也称为函数的类型,因为如果函数名前的返回值类型 { {
和函数执行体中的return表达式的类型不一致的话,则最终函数返回值的 return 10; return;或者没有return
类型以函数名前的返回值类型为准。 } }

29、return 表达式:
1、是用来终止整个被调函数的,向主调函数返回
2、如果表达式为空,则只终止函数,不返回 ( 适用于函数类型为void )

30、一个程序有且只有一个主函数
主函数可以调用普通函数
普通函数可以相互调用
主函数是程序的入口、出口

31、浮点数是不能准确存储的

32、什么叫函数:
逻辑上:能够完成特定功能的独立的代码块
物理上:
能够接受数据【当然也可以不接收数据】
能够对接收的数据进行处理
能够将数据处理的结果返回【当然也可以不返回任何值】
总结:函数是一个工具,它是为了解决大量类似问题而设计的,函数可以当作一个黑匣子

如何定义一个函数:
函数的返回值 函数的名字(函数的形参列表)

函数执行体;

函数放在main函数前面的话不需要函数声明,放在后面的话,必须要函数声明,函数声明必须与是语句,例如:int max ( int a, int b);注意分号,
目的是告诉编译器该函数已经定义过了。

33、函数定义一定要放在函数调用前面,先定义,后调用,如果函数定义放在了函数调用后面,则在函数调用前面要加上函数前置声明。
对库函数的声明是通过 # include < 库函数所在的文件的名字.h>来实现的。

34、形参和实参的个数,位置,类型相互兼容(整形和浮点型),,,,等必须严格对应。

35、如何在软件开发中合理的设计函数来解决实际问题?
1、一个函数的功能尽量独立,单一
2、多学习,多模仿牛人的代码

36、变量的作用域
局部变量:在一个函数内部定义的变量或者函数的形参,只能在本函数内部使用
全局变量:在所有函数的外部定义的变量,使用范围为从定义位置开始到整个程序结束
注意的问题:在一个函数内部,如果定义的局部变量的名字和全局变量的名字一样,局部变量会屏蔽全局变量。

37、指针和地址同一个含义,指针变量或者地址变量

int * p; //p是变量的名字,int * 为数据类型,表示p变量存放的是int类型变量的地址
//所谓int *类型,就是存放int变量地址的类型

p = &i;
1、p保存了i的地址,因此p指向了i;
2、p不是i,i也不是p,修改p不影响i,修改i不影响p;
3、如果一个指针变量指向了某个普通变量,则
* p == i;或者说二者完全等价
4、*p就是以p的内容(i的地址)为地址的变量

38、 指针就是地址,地址就是指针,
地址就是内存单元的编号;
指针变量是存放地址的变量;
指针和指针变量是两个不同的概念,但是通常我们叙述时会把指针变量简称为指针

39、指针的重要性:
表示一些复杂的数据结构
快速的传递数据,减少内存的损耗
使函数返回一个以上的值
能直接访问硬件
能够方便的处理字符串
是理解面向对象语言中引用的基础
总结:指针是c语言的灵魂

指针的定义:
地址:内存单元的编号,从0开始的非负整数,范围:【一般4G, 0--4G-1】
指针:指针就是地址,地址就是指针,指针变量就是存放内存单元编号的变量
指针本质就是一个操作受限的非负整数,只能进行减运算

40、函数声明一般不写形参,例如:int huhuan ( int *, int *);

41、*号的含义
1、乘号
2、定义指针变量; int * p; 定义了一个名字叫p的变量,int * 表示p只能存放整形数据的地址
3、指针运算符;该运算符放在已经定义好的指针变量的前面,如果p是一个已经定义好的指针变量,则 * p表示以p的内容为地址的变量

42、int *p; == int * p; ==int* p;

43、如何通过被调函数修改主调函数普通变量的值
1.实参必须为该普通变量的地址
2.形参必须为指针变量
3.在被调函数中通过 【 * 形参名 = ........ 】 的方式就可以修改主调函数相关变量的值

44、指针和数组
指针和一维数组
一维数组名,是个指针常量,存放的是一维数组第一个元素的地址,a == &a[0];

下标和指针的关系: 如果p是个指针变量,则 p[i] == *(p+i)

确定一个数组需要几个参数【如果一个函数要处理一个一维数组,则需要接收该数组的哪些信息】
需要两个参数:
、 数组第一个元素的地址
数组的长度

指针变量的运算
指针变量不能+和*/,只能相减【如果两个指针变量指向的是同一块连续空间中的不同存储空间,则可以相减】
一个指针变量到底占用几个字节
预备知识:
sizeof(数据类型)
功能:返回值就是该数据类型所占的字节数
sizeof(int) ==4
sizeof(变量名)
功能:返回值就是该变量所占字节数

假设 p 指向char类型变量【1个字节】
假设 q 指向char类型变量【4个字节】
假设 r 指向char类型变量【8个字节】
p q r本身所占字节数是否一样?答:一样,都是4个字节,与所指向的变量类型无关
总结:一个指针变量,无论他指向的变量占几个字节,该指针变量只占4个字节
一个变量的地址,是用该变量首字节的地址来表示


指针和二维数组

45、数组是一片连续的地址空间,字节的地址用4个字节去保存,32根地址总线,4*8=32,共4G大小
指针变量均占4个字节,只有用malloc分配的空间是动态,其他均为静态

46、关于改变形参能否改变实参的总结
如果不用指针是无法通过形参去改变实参的,因为程序会临时单独为形参分配一个内存存储空间,和实现的
内存存储空间是不同的,所以改变形参无法改变实参,并且函数调用结束,会释放形参的空间。
对于指针来说,将实参数组名 a【数组的起始地址】和数组长度 5 传递给形参 int * pArr, int len,
则pArr也就作为数组名【整形指针类型】,指向了是a数组的内存存储空间的起始地址,len赋值为了数组长度,
此时形参pArr 和len 可以唯一的确定实参中a数组,二者是完全等价的,系统并没有单独为形参临时开辟存储空间,
由于pArr指向了实参a数组,所以对于pArr的操作是直接建立在实参a数组的内存空间上的,pArr == a;
关键:理解清楚对形参的处理的内存是否是实参的内存,归结到底是内存存储的问题
47、动态内存分配【重点,难点】
传统数组的缺点:
1、数组长度必须事先制定,且是能是常整数,不能是变量
例子:int a[5];
int len = 5 ; int a[len];//error
2、传统形式定义的数组,系统为该数组分配的存储空间就会一直存在,程序员无法手动编程释放存储空间,只能在本函数运行完毕时由系统自动释放
3、数组长度不能在函数运行过程中动态的扩充或缩小
数组长度一旦定义,就不能改变
4、A函数定义的数组,在A函数运行期间可以被其他函数使用
A函数结束之后,其中定义的数组就不再能被其他函数使用
传统方式定义的数组不能跨函数使用
为什么需要动态分配内存
动态数组很好的解决了传统数组的四个缺陷
传统数组也叫静态数组

动态内存分配举例--动态数组的构造

静态内存和动态内存的比较
静态内存是由系统自动分配,由系统自动释放
静态内存是在栈分配的
动态内存是由程序员手动分配,手动释放,函数终止内存不释放
动态内存是在堆分配的

跨函数使用内存的问题
48、多级指针


49、C语言没有规定int类型占用4个字节,不同的编译软件可能有不同的字节数

50、结构体
为什么需要结构体?为了表示一些复杂事物,而普通的基本类型无法满足需求
什么叫结构体?把一些基本类型数据组合在一起形成的一个新的复合数据类型
如何定义结构体?
3种方式,//第一种[推荐使用],这只是定义了一个新的数据类型,没有定义变量
struct Student
{
int age;
float score;
char sex;
};

//第二种
struct Student2
{
int age;
float score;
char sex;
}st2;

//第三种
struct
{
int age;
float score;
char sex;
}st3;
怎样使用结构体变量
赋值和初始化
定义的同时可以整体初始化
如果定义完之后,只能单个赋值
如何取出结构体变量中的每一个成员
1、结构体变量名.成员名
2、指针变量名->成员名 (更常用) //在计算机内部会被转化成(*指针变量名).成员名来执行,二者等价
例子:
# include <stdio.h>

struct student
{
int age;
float score;
char sex;
};

int main(void)
{
struct student st1 = {21,95.5,'m'};//初始化,定义的同时赋初值

struct student * pst1 = &st1;//struct student为数据类型,相当于int,&st不能改为st,注意类型匹配

st1.age = 10;
printf("%d ", st1.age);

pst1->age = 20;
printf("%d ", st1.age);

return 0;
}
1、pst->age在计算机内部会被转化为(*pst).age,这是一种规定
2、pst->age == (*pst).age ==st1.age
3、我们之所以说pst->age 等价于st1.age,是因为pst->age会被转化为(*pst).age来执行
4、pst->age的含义:
pst所指向的结构体变量中的age这个成员,
结构体变量的运算
结构体变量不能进行加减乘除,但可以相互赋值,st1 = st2;是可以的
结构体变量和结构体变量指针作为函数参数传递的问题【推荐使用结构体指针变量作为函数参数传递】
举例:
动态构造存放学生信息的结构体数组
动态构造一个数组,存放学生成绩,并按成绩输出
枚举:
什么是枚举
把一个事物所有可能的取值一一列举出来
怎样使用枚举

枚举的优缺点
代码更安全
书写麻烦
位运算符:
&------按位与,【&&---逻辑与】
|-------按位I或,【||------逻辑或】
~ -----按位取反
^------按位异或【相同为0,不同为1】
<<----按位左移,右边补0,左移n位==乘以2的n次方,执行速度快
>>----按位右移,左边一般补0,也可能补1,右移n位==除以2的n次方,【前提是数据不能丢失,溢出】
位运算符的现实意义:对数据的操作精确到每一位

补码:
原码:
也叫 符号-绝对值码,最高位0表示正,1表示负,其余二进制位是该数字绝对值的二进制位
原码简单易懂,加减运算复杂,0的表示不唯一,存在加减乘除四中运算,增加cpu的复杂度

反码:
运算不便,也没有在计算机中应用

移码:
表示数值平移n位,n称为移码量
移码主要用于浮点数的阶码的存储
补码:
十进制转二进制
正整数转二进制:除2取余,直至商为零,余数倒数排序
负整数转二进制:先求与该负数相对应的正整数的二进制代码,然后将所有位取反,末尾加1,不够位数时,左边补1
零转二进制:全是0
二进制转十进制
如果首位是0,则表明是正整数,按普通方法求
如果首位是1,则表明是负整数,将所有位取反,末尾加1,所得数字就是该负数的绝对值【验证的话要写够32位,因为机器默认补0】

学习目标:
在Visual C++ 6.0中的一个int 类型的变量所能存储的数字范围?
int【4个字节,32位】类型变量能存储的最大正数用十六进制表示:7FFFFFFF
int【4个字节,32位】类型变量能存储的绝对值最大负整数用十六进制表示:80000000
具体参见下表:


最小负数的二进制代码?
最大正数的二进制代码?
数字超过最大正数会怎样?

进制转换:

字符串的处理:

链表:
算法:
通俗定义:解题的方法和步骤

狭义定义:对存储数据的操作
对不同的存储结构要完成某一功能所执行的操作是不一样的
这说明算法是依附于存储结构的,不同的存储结构,所执行的算法是不一样的

广义定义:广义的算法也叫泛型,无论数据是如何存储的,对该数据的操作都是一样的

我们至少有两种结构可以存储数据
数组
优点:存取速度快
缺点:需要一个连续的很大内存,插入和删除元素效率低

链表
专业术语:
首结点:存放第一个有效数据的节点
尾节点:存放最后一个有效数据的节点
头结点:
头结点的数据类型和首节点的类型是一模一样的
头结点是首节点前面那个节点
头结点并不存放有效数据
设置头结点的目的是为了方便对链表的操作
头指针:存放头结点地址的指针
确定链表只需要一个元素【头指针】
优点:插入删除元素效率很高,不需要一个很大的连续内存
缺点:查找某个元素的效率低


51、66.6在C中默认为double类型,66.6f或者66.6F则为float类型,并且浮点型数据存储是非准确存储的
在使用结构体的时候,编译一下,便于输入结构体成员
在函数调用中,要想改变某个数的值,只能发送该值的地址作为实参,其他方式均不可能修改该值
给指针类型的变量命名时前面最好加个p
一个指针变量永远只占4个字节,因为一个变量的地址永远只用它第一个字节的地址表示,认为是起始地址,
从开始往下1个或者4个或者8个字节作为一个变量是由变量数据类型决定的,char,int ,double
硬件按字节编号【地址,8位】
举例:
char * p = &i;//p存放变量i的第一个字节的地址,并且p指向一个字节,所以p+1,指针以1个字节为单位移动
int * p = &i;//p存放变量i的第一个字节的地址,并且p指向从首地址向下4个字节的变量,即p指向4个字节,并将其作为一个变量,所以p+1,指针以4个字节为单位移动
double * p = &i;//p存放变量i的第一个字节的地址,并且p指向从首地址向下8个字节的变量,即p指向8个字节,并将其作为一个变量,所以p+1,指针以8个字节为单位移动
53、 整形数组的赋值和输出都只能借助于for循环
字符型数组【字符串】可以直接输入直接输出
例如:char a[5];
scanf("%s", a);
printf("%s ", a);

54、默认位数不够,左边补0
字符本质上使用整数存储的
构造函数如果只需要判断真假【true false】,函数类型可以设置为【bool】类型
逻辑运算符的结果只能是真或假【0 or 1】
55、期末试题
分配内存:操作系统把某一块内存空间的使用权利分配给该程序
释放内存:操作系统把分配给该程序的内存空间的使用权利收回,该程序不能够再使用这一块内存空间
附注:释放内存不是把该内存的内容清零
1、变量为什么必须初始化?不初始化则变量就是垃圾值
2、详细说明系统是如何执行int i = 5;这个语句的?
1、Vc++6.0软件请求操作系统为i分配 存储空间
2、操作系统会在内存中寻找一块空闲区域,把该区域当做i来使用
3、VC++6.0会把i和这块空闲区域关联起来,今后对i的操作就是对这块空闲区域的操作
4、把5存储到i所关联的内存区域中
附注:所谓内存区域就是内存的一块存储单元
3、函数的优点:避免重复操作,有利于程序的模块化
4、什么是指针?什么是地址?什么是指针变量?三者的关系?
地址是内存单元的编号 指针就是地址 指针和地址是一个概念
指针变量就是存放内存单元编号的变量 指针变量和指针是两个不同的概念,只不过习惯称指针变量为指针
5、请写出静态变量和动态变量的异同?
相同:都需要分配内存
不同:静态变量是系统自动分配,自动释放,程序员无法在程序运行的过程中手动分配,也无法手动释放
静态变量是在栈中分配的,只有在函数终止之后,静态变量的存储空间才被系统自动释放
动态变量是由程序员手动分配手动释放的,程序员可以在程序运行过程中手动释放
动态变量是在堆中分配,程序员可以在程序运行的任何时刻都可以手动释放动态变量的空间,不需要等到函数结束
6、重点:流程控制,函数,指针,静态内存和动态内存
在多层循环中,break只能终止最内层包裹它的那个循环
else只能跟离他最近的if匹配

56、二进制全部为零的含义 ---00000000000000000 的含义
1、数值零
2、字符串结束标记符‘’
3、空指针 NULL
NULL表示的是0,而这个零不代表数字零,而表示的是内存单元的编号为0,0号地址
我们计算机规定了,以零为编号的存储单元的内容不可读,不可写

原文地址:https://www.cnblogs.com/heimu24/p/8747357.html