目录
1>字符型:特殊的整型,占据 1 个字节(1byte---8bit)
3 关系运算符和关系运算表达式:> < == >= <= !=
1>在同一个作用域内,不能出现相同的标识符,同一个作用域内,不能重复定义变量名。
3>局部变量:就是在函数作用域或者是语句块作用域中定义的变量 全局变量:就是在文件作用域中定义的变量(实际开发中尽量不要使用全局变量)
4>全局变量和函数都属于文件作用域内的标识符,文件作用域内的标识符是可以通过 extern 扩展作用域的
1>并非所有的变量都可以声明为 static,形式参数不能声明为 static,只能声明 为 auto.
3>全局标识符如果用 static 修饰,并不是表示在全局区而是表示该标识符只能在本文件内被扩展使用。

5 6 7 ---> 101 110 1112 3 4 ---> 010 011 100
011 010 111 100 110 ---> 3 2 7 4 6011 010 111 101 110--->32756011 101 110 101 011--->35653
0----00001----00012----00103----00114----01005----01016----01107----01118----10009----1001A----1010 10B----1011 11C----1100 12D----1101 13E----1110 14F----1111 151 2 8 9 A D F ---> 0001 0010 1000 1001 1010 1101 1111
1110 1101 1111 1001 1110 ---> E D F 9 E
数据在计算机里面都是以补码的形式存储。
原码 反码 补码37:0010 0101--->0010 0101--->0010 0101-37:1010 0101--->1101 1010--->1101 1011


C 语言的数据类型分为:基本类型和构造类型两种。
有符号字符型 signed char/char:有符号位取值范围:1000 0000( -128 ) ----0111 1111( 127 )无符号字符型 unsigned char:没有符号位,都是数值位取值范围:0000 0000( 0 )---1111 1111( 255 )
有符号的整型 signed int/int , 占据 4byte1000 0000 0000 0000 0000 0000 0000 0000( -2147483648 )---0111 1111 1111 1111 1111 1111 1111 1111( 2147483647 )无符号的整型 unsigned int , 占据 4byte0000 0000 0000 0000 0000 0000 0000 0000( 0 )---1111 1111 1111 1111 1111 1111 1111 1111 ( 4294967295 )短整型 short int:占据 2byte1000 0000 0000 0000( -32768 )---0111 1111 1111 1111( 32767 )无符号短整型 unsigned short int: 占据 2byte0000 0000 0000 0000( 0 )---1111 1111 1111 1111( 65535 )长整型 long long int: 占据 8byte( -9223372036854775808--9223372036854775807 )无符号长整型 unsigned long long int: 占据 8byte( 0--18446744073709551615)
float : 单精度浮点型,占据 4bytedouble : 双精度浮点型,占据 8bytelong double : 长双精度浮点型,占据 8byte 或者 16byte
类型名 变量名 = 初值 , 变量名 = 初值 ;char a , b , c ;int e ;char a = 0 , b = 0 , c = 0 ;char a = 0 ;unsigned char e = 0 ;int height = 170 ;int weight = 0 ;int a = 0 ;//在变量定义时,给变量赋值叫赋初值a = 0 ;//不是赋初值,这叫赋值

int a = 100; //100 是整型常量,占用 4byteunsigned int a = 200U; //200 是一个无符号的整型常量long int a = 200L; //200 是一个 long int 型常量long long int a = 200LL; //200 是一个 long long int 型常量,占据 8bytefloat f = 3.14f; //3.14 是一个单精度浮点型常量double d = 3.14; //3.14 是一个双精度浮点型常量long double ld = 3.14L; //3.14 是一个长双精度浮点型常量
char a = 11; //11 是十进制常量char b= 0 11; //11 是八进制常量,以数字 0 开头表示的是八进制char c= 0x 11; //11 是十六进制常量,以 0x 开头表示的是十六进制
const int a = 45;a = 100;// 错误,不能修改 a 的值

- int main(void)
- {
- int a = 0;
- a = 20;
- a++;//相当于 a = a + 1; 21
- printf("%d\n", a++);//先读后写,先把 a 的值(21)读出来,再 a = a + 1;
- printf("%d\n", a);//22
- }
- printf("%d\n", a++);
- //相当于
- //printf("%d\n", a);
- //a = a + 1;
- int main(void)
- {
- int a = 0;
- a = 20;
- ++a;//相当于 a = a + 1; a = 21
- printf("%d\n", ++a);//先写后读,先 a = a + 1;再把 a 的值(22)读出来
- printf("%d\n", a);//22
- }
- printf("%d\n", ++a);
- //相当于
- //a = a + 1;
- //printf("%d\n", a);
int a = 15;int b = 10;a > b //1a < b //0a < 15 //0a > 15 //0a >= 15 //1a == 15 //1a == b //0a != b //1
int a = 15;int b = 10;a > b && a < b//0a > b && a != b//1a && b//1
int a = 15;int b = 10;a > b || a < b //1 a>b为真,有真则为真a > b || a != b //1a < b || a == b //0 两边都为假,则为假a || b //1 运算对象不为0,为真
int a = 15;int b = 10;!(a > b) //0 a>b为真!(a < b) //1 a!a //0 a为真5 赋值运算符和赋值运算表达式:
简单赋值运算符: =变量 = 表达式 ;a = 45;复合的赋值运算符: += -= *= /= %=
int a = 15;a += 10; //a = a + 10; a = 25;a -= 10; //a = a - 10; a = 15;a *= 2; //a = a*2; a = 30;a /= 2; //a = a/2; a = 15;a %= 6; //a = a % 6; a = 3;a++; // 相当于 a += 1;a / = 10; // 错误 ,不能有 空格6 逗号运算符和逗号运算表达式:,
表达式 1,表达式 2,表达式 3,...逗号表达式的最终值是 最后一个 表达式的值,但是所有的表达式 都会运行 。
int main(void) { int a = 0; int b = 0; int c = 0; a = 5; b = 15; c = 10; printf("%d\n", (++a, ++b, c++));//10 printf("%d\n",a);//6 printf("%d\n", b);//16 }7 sizeof 求字节运算符
sizeof(表达式) 结果为表达式的数据类型占据的字节数
int a = 10;sizeof( int ) //4sizeof(unsigned int) //4sizeof(a) //4sizeof(165) //4sizeof(a + 10) //4sizeof(float) //4sizeof(double) //8sizeof(long double) //88 强制类型转换运算符:(类型名)(表达式)
int main(void){float a = 0;int b = 0;int c = 0;float d = 0;a = 7.5;b = 2;d = 1.5;c = a * b;//c = 15.000 000 000 000 000;printf("%d\n", c);//15c = (int)a * b;//c = 7*2;printf("%d\n", c);//14c = (int)(a * b) ;//c = 15;printf("%d\n", c);//15c = a*b*d;//c = 22.5; c = 22printf("%d\n", c);//22c = (int) a *b*d;printf("%d\n", c);//21c = (int)a *b* (int)d ;printf("%d\n", c);//14}9 不同类型的数据混合运算
为了保证运算的精度,计算机会自动转向精度高的数据类型进行转换
char 一定会转换为 intfloat 一定会转换为 doublechar b = 0;float c = 0;char d = 'M';b = 'A'+ 32; //b = 65+32;c = 7 / 2.0f; //c = 3.500 000 000 000 000;四 输入与输出函数、选择结构
1 数据的输出和输入
把数据从计算机内存送到计算机外部设备上的操作称为“输出” 。例如,把计算机运算结果显示在显示屏或打印机上,或者送到磁盘上保存起来。从计算机外部设备将数据送入计算机内部的操作称为“输入” 。说明: C 语言本身并没有提供输入输出语句 ,但是可以通过调用标准库函数中提供的输入 和输出函数来实现输入和输出。 C 语言中提供了丰富的输入和输出库函数。在调用标准库 中的函数时,必须包含标准库的头文件 stdio.h 。写法:#include2 输出函数
C 语言中,最常用的输出函数时 printf 函数,用来在终端设备上按照指定格式进行输出。
1.printf 函数的调用形式:
printf(格式控制,输出项 1,输出项 2,...);说明:格式控制是 字符串 的形式在 printf 函数调用之后加上” ; ”, 才能构成一条完整的输出语句。2.printf 函数的使用方法:
1>使用方法 1:输出单个数据--不换行
printf("%格式字符",输出的数据 );
说明:
格式字符输出说明 c 输出一个字符 d 或 i 输出带符号的十进制整型数据,若为长整型用%ld ,短整型 %hd o 以八进制格式输出整型数据,若以%#o,则在实际八进制数前加了先导 0 x 或 X 以十六进制格式输出整型数据,若以%#x,则在实际十六进制数前加了先导 0x,格式字符的大小写决定了十六进制数中的大小写 f 以带小数点的数学形式输出浮点型数据(单精度和双精度) e 或 E 以指数形式输出浮点型数据 s 输出一个字符串,直到遇到’\0’结束 % %%,实际输出的是一个%注意:float 类型数据一般有 7 位 有效数字double 类型数据一般有 15 位 有效数字2>使用方法 2:有数据需要原样输出的
int a = 100;printf("a = %d",a); //输出的结果是: a = 100 ,输出结果不换行3>使用方法 3:同时输出多个数据
int a = 110;char c = 'a';//调用一次 printf 函数,就能输出这两个变量的值printf("%d%c\n",a,c);printf("a = %d c= %c\n",a,c);printf("a = %d,c= %c\n",a,c);3.输出数据所占宽度说明
在做数据输出操作时,有的时候需要规定输出数据的宽度。
1>整型数据的输出宽度
int a = 250;int b = 20;要求输出的两行结果右对齐。
分析:
a 的数值有 3 位,b 的数值有 2 位
b 的数据前应该补一位空格 ,此时就要设定输出 b 的数据的宽度,输出的宽度应该为 3
printf("%d",a);
printf(" %3d ",b);假设:int a = 1234; printf("%6d\n",a); printf("%4d\n",a); printf("%3d\n",a); printf("%2d\n",a);
总结:
printf(“% m d”,a);1> 若 m <= 实际数据的宽度,则按 实际情况 输出2> 若 m > 实际数据的宽度,则在实际数据的 左边用空格补齐3>printf( “ % 0m d ” ,a); 则实际的结果不够 m 位的在数据的 左边用 0 补齐2>浮点型数据的输出宽度说明
浮点型:若用 %f 输出,则宽度为: 整数部分的位数+小数点+小数部分的宽度float a = 3.14159; printf("%7.4f\n",a); printf("%6.6f\n",a); printf("%6.6f\n",a); printf("%0.3f\n",a);
总结 :若 float a = 1.2345; ,以%f 输出printf(“% m . n f” ,a);m ----整个数据的宽度n----小数位数1>>实际小数位数>n,截去小数右边多余的小数,截去的第一位要注意 四舍五入2>>实际小数位数< n,在小数的 最后变补 03>> m 省略,%.n , 则整数部分 按照实际输出 ,小数部分按照以上两个规则进行4>> m < n+1,自动突破,按照实际数据进行输出5>> m > n+1,整个数据的最左边补空格4.输出的数据左对齐
由于输出的数据都是 隐含的右对齐 ,如果想要输出的数据实现 左对齐 ,可以在格式控制中 的 % 和宽度之间加一个“ - ”来实现。double a = 3.141592653;double b = 3.14;printf("% - 10.7f,%f\n",a,b);// 输出结果 :3.1415927 ,3.140000//3.1415927 后面有一个空格3 输入函数
数据的输入函数,通常会使用 scanf 函数。scanf(格式控制,地址列表);int a = 0;scanf("%d",&a);char a = 0;scanf("%c",&a);//a = 'M';注意:1>scanf 函数中的地址列表应当是变量地址,不能是变量名。
scanf("%d",a);//错误,缺少 &2>如果在格式控制字符串中除了格式字符还包括其他字符,则输入时要在对应的位置输入相同的字符。scanf("a=%d,b=%d",&a,&b);要输入 :a=123,b=456输入时 a= , b= 也要在对应的位置手动输入3>在用%c 格式字符时,输入空格也是有效字符。scanf("%c%c",&a,&b);如果输入 :M N则 a 为 'M',b 为空格字符必须是输入 :MNb 的值才是 'N'4>在使用 %d 输入数据时,如输入空格、回车、Tab 键或遇到非法字符(不属于数值的字符),则认为数据输入结束。scanf("%d%d",&a,&b);输入时 :123 456输入 123 后加空格表示 123 输入完成并赋值给 a4 算法的基本结构
算法的三种基本结构:顺序结构、选择结构(分支结构)和循环结构。4.1 顺序结构:
按语句书写的先后顺序依次执行的结构。
复合语句:
由大括号{}中的 0 个或多个声明和语句列表共同构成。
int main(void) { int a = 0; int b = 0; a = 5; b = 4; { int a = 6;//变量声明 printf("%d\n",a);//这个 a 的值是 6,和前面的 a 不是同一个 a++;//自增表达式语句 printf("%d\n",a);//函数调用语句 ++b; } printf("%d\n", a);//这个 a 的值是 5 printf("%d\n",b); return 0; }注意:1>复合语句不以分号;作为结束符,即 最后的}后面不加分号 。2>在复合语句中 可以定义变量,但仅在复合语句中有效 ,即作用域是{}括起来的部分。
int main(void) { int b = 0; b = 4; { int a = 6; printf("%d\n",a); a++; printf("%d\n",a); ++b; };//错误,不能加; printf("%d\n", a);//错误,a 没有定义 printf("%d\n",b); return 0; }4.2 选择结构(分支结构)
根据条件判断来选择执行哪一条语句。选择结构的语句有: if 条件语句 和 switch 多路分支语句 。
//输入 a 和 b 的值,判断并输出最大值 int main(void) int main(void) { int a = 0; int b = 0; int max = 0; printf("请依次输入 a 和 b 的值:"); scanf("%d%d",&a,&b); max = a; if(max < b) max = b; printf("max:%d\n",max); return 0; }if 条件语句中的 语句 1 不是只有一条语句的意思,可以是多条语句用 {} 括起来的复合语句。
int main(void) { int a = 0; int b = 0; int max = 0; printf("请依次输入 a 和 b 的值:"); scanf("%d%d",&a,&b); max = a; if(max < b) { max = b; printf("a < b \n"); } printf("max:%d\n",max); return 0; }2.if...else 语句
if(条件表达式)语句 1;else语句 2;执行过程:如果条件表达式的值为 真,则执行语句 1 ,否则执行语句 2 。
//输入 a 和 b 的值,判断并输出最大值 int main(void) { int a = 0; int b = 0; int max = 0; printf("请依次输入 a 和 b 的值:"); scanf("%d%d",&a,&b); if(a < b) max = b; else max = a; printf("max:%d\n",max); return 0; }3.if...else if 语句
if(条件表达式 1)语句 1;else if(条件表达式 2)语句 2;else if(条件表达式 3)语句 3;....else语句 n;执行过程:依次判断条件表达式的值,当某个值为真时,则执行相应的语句,然后跳出整个 if 语句之外,继续执行后面的程序。如果所有的 表达式都为假,则执行语句 n, 然后继续执行后面的程序。
//输入成绩分数,并判断该成绩属于哪个等级 int main(void) { int score = 0; printf("请输入成绩:"); scanf("%d",&score); if (score >= 0 && score <= 100) { if(score >= 90) printf("A+\n"); else if(score >= 80) printf("A\n"); else if(score >= 70) printf("B+\n"); else if(score >= 60) printf("B\n"); else printf("不合格\n"); } else printf("请输入合法的成绩!"); return 0; }4.if 语句嵌套
当 if 语句中的执行语句又是 if 语句时,则形成了 if 语句嵌套。if(条件表达式)if 语句;或者if(条件表达式)if 语句;elseif 语句;1 修改下面的程序使程序:输入 a 和 b 的值,判断最大值是否大于 100,是则输出最大值。
int main(void) { int a = 0; int b = 0; printf("请依次输入 a 和 b 的值:"); scanf("%d%d",&a,&b); if(a < b) if(b > 100) printf("max:%d\n",b); else if(a > 100) printf("max:%d\n",a); return 0; }注意:C 语言规定,else 总是与它前面最近的为配对的 if 配对。
//所以修改后应为: int main(void) { int a = 0; int b = 0; printf("请依次输入 a 和 b 的值:"); scanf("%d%d",&a,&b); if(a < b) { if(b > 100) printf("max:%d\n",b); } else { if(a > 100) printf("max:%d\n",a); } return 0; }2 输入 a 、 b 、 c 的值,判断并输出最大值
int main(void) { int a = 0; int b = 0; int c = 0; int max = 0; printf("请依次输入 a、b、c 的值:"); scanf("%d%d%d", &a, &b,&c);// if (a > b) { if (a > c) max = a; else max = c; } else//b > a { if (b > c) max = b; else max = c; } printf("max:%d\n", max); return 0; }switch(表达式)//1{case 常量表达式 1:语句 1(集合);case 常量表达式 2:语句 2(集合);...case 常量表达式 n:语句 n(集合);default:语句 n+1;}执行过程:首先计算表达式的值,与常量表达式 i 进行比较,如果与其中一个常量表达式 i 的值相等,就执行其后的语句 直到遇到 break 语句才结束 switch 语句 ,如果 case 后无 break语句,则继续执行随后所有的 case 后的语句 。如果没有找到与表达式的值相匹配的常量表达式,则执行 default 后的语句 n+1 。
输入数字 1-7 ,并输出显示对应的星期
int main(void) { int week = 0; printf("今天星期几:"); scanf("%d", &week);//1---'1' switch (week)//week 是表达式 { case 1:printf("今天是星期一\n"); break; case 2:printf("今天是星期二\n"); break; case 3:printf("今天是星期三\n"); break; case 4:printf("今天是星期四\n"); break; case 5:printf("今天是星期五\n"); break; case 6:printf("今天是星期六\n"); break; case 7:printf("今天是星期天\n"); break; default:printf("输入数据有误!\n"); } return 0; }注意:1>switch 后面括号中的表达式可以是 整型、字符型和枚举型 。2> 在 case 后的各常量表达式的值 不能相同3> 在 case 后,允许有多个语句,可以不用 {} 括起来,而整个 switch 结构一定要有一对{}4> 各 case 和 default 语句的先后 顺序可以改变 ,不影响程序执行结果。表达式 1 ? 表达式 2 : 表达式 3求值过程:如果 表达式 1 的值为 真 ,则以 表达式 2 的值作为条件表达式的值,否则以 表达式 3 的值作为条件表达式的值 .//输入 a、b 的值,判断并输出最大值,使用条件表达式。
int main(void) { int a = 0; int b = 0; int max = 0; printf("请依次输入 a 和 b 的值:"); scanf("%d%d",&a,&b); max = a>b?a:b; printf("max:%d\n",max); return 0; }五 循环结构
什么时候用到循环结构:处理重复的问题的时候。循环结构的三大语句: while 语句、do while 语句、for 语句 。while(循环条件表达式)循环体语句;执行过程:只有循环条件表达式的值为 真就 执行循环体 语句,先判断后执行。
1. 输出 1---n 之间的数
int main(void) { int i = 1; int n = 0; printf("请输入 n 的值:"); scanf("%d",&n);//10 15 while(i <= n) { printf("%d\n",i); i++; } return 0; }2. 计算 m+...+n 的值
int main(void) { int n = 0; int m = 0; int sum = 0; printf("请依次输入 m 和 n 的值:"); scanf("%d%d",&m,&n);//m+...n 10 15 while (m <= n) { sum = sum + m; m++; } printf("sum=%d\n", sum); return 0; }do{循环体语句;}while(循环条件表达式);执行过程: 先执行 循环体语句, 再检查 循环条件表达式的值是否为真,如果为真则继续 执行循环体语句,否则结束循环。
1计算 m+...+n 的值,使用 do while 语句。
int main(void) { int n = 0; int m = 0; int sum = 0; printf("请依次输入 m 和 n 的值:"); scanf("%d%d",&m,&n);//m+...n 10 15 do { sum = sum + m; m++; }while (m <= n); printf("sum=%d\n", sum); return 0; }2输出 1---n 之间的数,使用 do while 语句
int main(void) { int i = 1; int n = 0; printf("请输入 n 的值:"); scanf("%d",&n);//10 15 do { printf("%d\n",i); i++; }while(i <= n); return 0; }while 语句和 do...while 语句的区别 :while 语句是先判断后执行,do...while 语句是先执行,至少会执行一次。3.for 语句
for( 表达式 1 ; 表达式 2 ; 表达式 3 )循环体语句;说明:表达式 1 :设置初始条件, 只执行一次 ,为 0 个或多个变量设置初值。表达式 2 :是循环条件表达式,用来判定是否继续循环。在每次 执行循环体之前 要先执行表达式 2,然后再决定是否继续执行循环。表达式 3 :作为 循环的调整 ,比如是循环体变量增值,它是执行循环体语句之后再执行。
1.while 语句与 for 语句的替换:计算 1+2+3+...+n 的值
使用 while 语句实现 :
int i = 1; while(i <= n) { sum = sum + i; i++; }使用 for 语句实现 :
int i = 1; for(i = 1;i <= n;i++) { sum = sum + i; }2. 输出 1---n 之间的数,使用 for 语句。
int main(void) { int i = 1; int n = 0; printf("请输入 n 的值:"); scanf("%d",&n);//10 15 /*while(i <= n) { printf("%d\n",i); i++; }*/ for(i = 1;i <= n;i++) { printf("%d\n",i); } return 0; }3.计算 m+...+n 的值,使用 for 语句。
int main(void) { int n = 0; int m = 0; int sum = 0; printf("请依次输入 m 和 n 的值:"); scanf("%d%d",&m,&n);//m+...n 10 15 /*while (m <= n) { sum = sum + m; m++; }*/ for(;m <= n;m++) { sum = sum + m; } printf("sum=%d\n", sum); return 0; }注意:1>for 语句的 三个表达式不是必须的 。2>当条件表达式 ( 表达式 2)的值为假(为 0)时 for 循环语句就结束 。3>可以在循环体内执行 break,continue,goto 语句。4> 表达式 2 是空 的,表明表达式 2 的值一直是真,即 死循环 。for(;;)//死循环语句{}相当于while(1){}小结:for(i=m;i < n;i++)//循环次数 :n-m 次for(i=m;i <= n;i++)//循环次数 :n-m+1 次2 中断语句
break 语句 :跳出本层循环,执行循环后的语句。continue 语句 :跳出本次循环,执行下一次循环。goto 语句 :跳出到指定的标号位。1.break 语句
1 计算 m+...+n 的值,当累加的值大于 100 时退出循环
int main(void) { int n = 0; int m = 0; int sum = 0; printf("请依次输入 m 和 n 的值:"); scanf("%d%d",&m,&n);//m+...n 10 50 for(;m <= n;m++) { sum = sum + m; if(sum > 100) break; } printf("sum=%d\n", sum); return 0; }2 输出 1---n 之间的数 ,当输出的数大于 100 时结束循环
int main(void) { int i = 1; int n = 0; printf("请输入 n 的值:"); scanf("%d",&n);//10 15 for(i = 1;i <= n;i++) { printf("%d\n",i); if(i > 100) break; } return 0; }2.continue 语句
只用于结束本次循环 ,即 直接去执行表达式 3 .
int main(void) { int i = 1; int n = 0; int sum = 0; printf("请输入 n 的值:"); scanf("%d", &n);//150 for (i = 1; i <= n; i++) { sum = sum + i; printf("sum:%d\n",sum); if (i > 100) continue; printf("i=%d\n", i); } return 0; }3.goto 语句(了解)
int main(void) { int i = 1; int j = 0; int k = 0; for (j = 0; j < 2; j++)//2 { for (i = 0; i < 15; i++)//15 { if (i == 10) goto again; printf("i=%d\t", i); } } again:printf("穿越啦\n"); return 0; }六 函数
1 函数的定义
函数的定义:包括两个部分,分别是“ 函数头 ”和“ 函数体 ”。返回值类型 函数名(形式参数 1, 形参 2, ...)// 函数头{}// 函数体注意 1 :函数的返回值和参数可以是 任意类型 ,包括空类型!!
void printfStart(void)//打印一行星号 { printf("************\n"); return; }注意 2 :函数名是一种标识符,必须符合标识符的命名规则!通常用动词注意 3 :函数的参数可以是一个变量
void sel(int n)//n 表示输入的分数 { if (n > 90) printf("你的成绩属于优秀!"); else if (n > 80) printf("你的成绩属于良好!"); else if (n > 70) printf("你的成绩属于中等!"); else if (n > 60) printf("你的成绩属于及格!"); else printf("你的成绩属于不及格!"); }总结:1.函数名要 符合标识符命名规则2.定义时的参数叫 形参,个数没有限制 ,类 型没有限制3. 返回值的类型没有限制4.return 表达式:return 语句后面的表达式是 可以省略 的如果 return 后有表达式则返回值类型必须和表达式类型 一致如果 return 后没有表达式则用于中断函数执行函数不调用是无法得到运行的,函数要想被执行必须调用之2 函数的调用
语法 : 函数名(实际参数 1,实参 2,。。。。)注意:1 > A 函数 调用 B 函数 ,则 A 函数叫主调函数 , B 叫被调用函数2 > 调用的参数个数、顺序、类型要与定义相同 demo add(1, 2);3 > 函数调用步骤step1.实参的值赋值给形参step2.执行函数体step3.返回主调函数3 函数的声明
声明的方式: 只保留函数头 且后面 加分号总结:函数的定义:包括 函数头 和 函数体函数的调用:用于执行定义的函数,通常 先定义后调用函数的声明:用于 扩展函数名称的作用域 ,使得可以先声明后使用!4 函数的设计原则
1.一个函数实现一个功能
2.返回值的原则:如果计算有结果需要加返回值
3. 形参 的设计及原则:如果计算的过程需要有数值进行 辅助 , 则需要加参数。4.如果函数有形式参数则必须进行 参数检查 ,检查参数是否有 异常。通常用 分支结构 (选择结构)进行参数检查,如果有错误则返 回-15.函数体的设计思路第一步:定义变量第二步:逻辑关系运用,选择结构还是循环结构还是综合运用。1.定义一个函数实现:求 n 以内的奇数累加和。主函数实现:输入 n 的值,调用该函数后, 输出对应的累加和。
int sum(int n); int main(void) { int m = 0; int result = 0; printf("请输入一个整数:"); scanf("%d",&m); result = sum(m); if(result == 0) printf("形参异常!\n"); else printf("%d 以下的奇数的累加和是:%d\n",m,result); return 0; } //函数的功能:求奇数的累加和,1+3+5+...+n int sum(int n) { int i = 0; int s = 0; if(n<1)//形参的异常检查 return 0; //for(i=1;i<=n;i++) //{ // if(i%2 != 0)//if(i%2 == 1)//if(i%2) // s = s + i; //} for(i=1;i<=n;i+=2) { s = s + i; } return s; }2.定义一个函数实现:计算 10 - 1/2 - 1/3 - ...- 1/n 的值。主函数实现:输入 n 的值, 调用该函数后,输出对应的结果。
float sum_div(int n);//函数的声明 int main(void) { int m = 0; float s = 0; printf("请输入一个整数:"); scanf("%d",&m); s = sum_div(m); if(s == 0) printf("形参异常\n"); else printf("10-1/2-1/3-...-1/%d 的值:%f\n",m,s); return 0; } //函数要实现的功能:计算 10 - 1/2 - 1/3 - ...- 1/n 的值 float sum_div(int n) { int i = 0; float sum = 10; if(n<2)//判断形参是否异常 return 11; for(i=2;i<=n;i++) { sum -= 1.0/i; } return sum; }3.定义一个函数实现:![]()
根据 x 求 y 的值。主函数实现:输入 y 的值,调用该函数后,输出对应的结果。
int y_value(int x);//函数的声明 int main(void) { int m = 0; int y = 0; printf("请输入一个整数:"); scanf("%d",&m); y = y_value(m); if(y == -1) printf("形参异常\n"); else printf("x:%d,y:%d\n",m,y); return 0; } //函数要实现的功能:求 y 的值 int y_value(int x) { int y = 0; if(x<1) y = 2*x;//return 2*x; else if(x>=1 && x<5) y = 3*x - 2;//return 3*x - 2; else if(x>=10) y = 4*x - 3;//return 4*x - 3; else//形参异常 y = -1;//return -1; return y; }七 递归调用、作用域和存储类别
1 函数的递归调用
1>递归的概念
C 语言中的函数可以递归调用,即:可以 直接或者间接地自己调用自己 。2>递归思想应该关注的几点:
(1)找到规律(2)递归调用的条件(3)结束递归调用的条件1. 使用递归调用的形式编写函数实现求 :1+2+3+...+n
#include int sum(int m);//函数的声明 int main(void) { int n = 0 ,s = 0; printf("请输入 n 的值:"); scanf("%d",&n); s = sum(n);//函数的调用 printf("1+2+3+...+%d 的值为%d\n",n,s); return 0; } int sum(int m) { if(m<1)//形参异常检查 return -1; else if(m==1)//当形参为 1 时返回 1,即结束递归调用的条件 return 1; else return m+sum(m-1); }2 作用域
1.作用域:一个代码空间
作用域解决的是标识符的使用范围,是空间的问题。分类:文件作用域:从文件头到文件尾的代码空间。函数作用域:函数的参数和函数体属于函数作用域,函数的返回值和函数名属于文件作用 域。注意:1>在同一个作用域内,不能出现相同的标识符,同一个作用域内,不能重复定义变量名。
int foot(void) { int a = 0; } void foot(void)//错误,函数名不能相同 { char a = 0; } int main(void) { char a; char a;//错误,重复定义变量 a return 0; }2>一个标识符不能同时属于两个作用域,使用就近原则
#include char height = 10;//height 属于文件作用域 int main(void) { char height = 12;//height 属于函数作用域 printf("%d\n",height);//使用的是函数里面的 height,结果:12 return 0; }3>局部变量:就是在函数作用域或者是语句块作用域中定义的变量 全局变量:就是在文件作用域中定义的变量(实际开发中尽量不要使用全局变量)
4>全局变量和函数都属于文件作用域内的标识符,文件作用域内的标识符是可以通过 extern 扩展作用域的
//指出下面程序的错误 int main(void) { foo();//error printf("%d", g_a);//error return 0; } void foo(void){} int g_a = 0; //改进如下 extern void foo(void); extern int g_a; int main(void) { foo();//error printf("%d", g_a);//error return 0; } void foo(void){} int g_a = 0;3 存储类别
1.存储类别解决的是标识符的“ 生命周期 ”或者 变量内存的开辟时间和销毁时间2.学习 存储类别 时不要去考虑 作用域,两者没有关系 !
void foo(int a) { int b = 0; }//a 内存销毁 int main(void) { foo(10);//a 内存开辟 return 0; }4 栈变量:auto 声明的变量
变量 内存开辟 时间:栈变量是在 执行到变量定义语句时 开辟内存变量 内存销毁 时间: 所在作用域结束后 销毁
void foo(int a) { int b = 0;//b 开辟内存 { int i = 0;//i 开辟内存 }//i 内存销毁 i = 10;//错误,i 内存已经销毁 }//b 内存销毁,a 内存销毁 int main(void) { foo(10);//a 开辟内存 foo(20);//a 重新开辟内存 return 0; }注意: 只有局部变量可以用 auto 修饰,全局变量不行,默认情况下是可以省略。
auto int a = 0;//错误,a 是全局变量不能用 auto 修饰 int main(void) { auto int i = 0; int b = 0; }5 全局区变量:用 static 声明的变量
变量 内存开辟 时间: 编译时变量 内存销毁 时间: 主函数结束时
void foo(int a) { static int b = 0;//b 编译时开辟内存,该语句只在编译时执行一次,后面不再执行 { int i = 0;//i 开辟内存 }//i 内存销毁 b++; printf("%d\n",b); }//a 内存销毁 int main(void) { foo(1);//a 开辟内存 foo(2);//a 重新开辟内存 return 0;//主函数结束时 b 销毁内存 }注意:1>并非所有的变量都可以声明为 static,形式参数不能声明为 static,只能声明 为 auto.
void foo(static int a);//错误,形参 a 不能用 static 声明 void foo(auto int a);//正确2>变量声明为 static 时,不赋初值时默认为 0.
void foo(void) { static int count;//默认是 0 count++; printf("%d", count); } int main(void) { foo(); foo(); foo(); return 0; }3>全局标识符如果用 static 修饰,并不是表示在全局区而是表示该标识符只能在本文件内被扩展使用。
main.c: extern int g_a;//正确 static int g_a; fun.c extern int g_a;//错误
main.c: extern void foo(void);//正确 static void foo(void){}; fun.c extern void foo(void);//错误八 指针与变量
1 指针的预备知识
int a = 0;
1.变量是要占据内存的。2.内存的大小由数据类型决定。char b = 0;//b 占据 1byte3.变量名是内存的标识,用来读写内存b = 10;//写内存printf("%d\n",b);//读内存4.内存是有地址的,每个字节都有一个唯一的整数作为编号, 这个整数就是地址。2 指针的基本概念和指针常量
int 地址绑定 4bytedouble 绑定 8bytechar 绑定 1byte4.指针(地址)常量的写法
int a = 0; float f = 3.14f; double d = 3.14; char c = 'M'; &a;&f;&d;&c;//指针常量4 = 100 ; //错误 ,常量 4 不能被修改&a = &b; //错误 ,&a 是指针常量不能修改
int a; int b = 10; a = b;//a = 10;3 指针的类型
int a = 0;//那么&a 的类型名是 int * double d = 0;//那么&d 的类型名是 double * char c = 0;//那么&c 的类型名是 char * long long int L = 0;//那么&L 的类型名 long long int **:指针运算符int * 绑定 4bytedouble * 绑定 4bytechar * 绑定 4byte4 指针变量的定义
普通变量的定义:类型名 变量名 = 初始值;
int a = 0;指针变量的定义:类型名 变量名 = 初始值;
int * a;//int *是类型名,a 是指针变量 int * b = 10;//错误,10 是整型常量,不是地址常量 int c = 0; int * d = &c;//正确 int e = 0,f = 0; int * g = &e,h = 10,*i = &f;//指针变量 i 前面的*不能少,h 是 int 型变量5 指针变量的基本用法
int a = 0; int * b = &a; *b = 100;//*b 是 a 的小名或别名,a 和*b 都标识同一块内存