黑马程序员——C语言基础学习(三)---进制和函数的总结学习

时间:2021-11-09 00:21:57

 


------  <a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a> 期待与您交流! -------



                                                  进制和函数的总结学习


.进制

 

  1、计算机中的进制

是一种计数的方式,数值的表示形式

  2、常见的进制

十进制、二进制、八进制、十六进制

  3、进制 数字 进位方法

十进制0、1、2、3、4、5、6、7、8、9 逢十进一

二进制 0、1 逢二进一书写形式:需要以0b或者0B开头,比如0b101

八进制 0、1、2、3、4、5、6、7 逢八进一   书写形式:在前面加个0,比如045

十六进制 0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F 逢十六进一  

书写形式:在前面加个0x或者0X,比如0x45

:16进制就是逢16进1,但我们只有0~9这十个数字,所以我们用A,B,C,D,

   E,F这五个字母来分别表示10,11,12,13,14,15。字母不区分大小写。

  4.进制表

  黑马程序员——C语言基础学习(三)---进制和函数的总结学习


  5.进制转换的要素 

了解计算机的进制最重要的是进制之间的转换

进制转换的3个基本要素:数位、基数和位权

数位: 数位是指数码在一个数中所处的位置

基数:每个数位上所能使用的数码的个数 (二进制取值0、1基数为2,十进制取值0-9基数为 10)

位权:位权是指一个固定值 既:数码*基数^数位

 

  6.常见的进制转换

10-> 2 : 除2取余法,把10进制数除以2,然后取得余数的序列,再倒序

2-> 10 : 所有位的位权相加 101 = 1*2^0+0*2^1+1*2^2

2--> 16 : 4合1法, 整数部分从右向左 4位结合成一位,小数部分从左向右4位结合1位, 不足部分补0

16-->2: 1拆4法, 16进制的1位拆成二进制的4位 2-->8 :3合1

8-->2:1拆3

10-->8:除8取余

8 --> 10 :8--> 2 --> 10

16 --> 10: 16-->2 -->10

 

 

  7.机器数和真值

1)机器数

一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的

2)真值

将带符号位的机器数对应的真正数值称为机器数的真值



  8.原码、反码、补码的基本概念

对于正数:反码==补码==原码。

对于负数:反码==除符号位以外的各位取反。补码=反 码+1

1)原码

原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值.

 2)反码

反码的表示方法是: 正数的反码是其本身

负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.

3)补码

补码的表示方法是:

正数的补码就是其本身

负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

 

 

  9.-1在内存中存储细节

64为计算机中,-1的原码、反码、补码 如下

-1原码1000 0000 0000 0000 0000 0000 0000 0001 

-1反码 11111111 1111 1111 1111 1111 1111 1110

-1补码 11111111 1111 1111 1111 1111 1111 1111

正整数取反+1就是对应负数

 

  10.位运算符介绍

(1)这些运算符只能用于整型操作数,即只能用于带符号或无符号的char,short,intlong类型。

1)&按位与       口诀:同1为1

2) | 按位或  口诀:有11,00

3) ^ 按位异或  口诀:相同为0,不同为1

4) ~ 取反     口诀:01,1


(2)<< 左移1、各二进位全部左移n,高位丢弃,低位补

注意:

1)左移可能会改变一个数的正负性 2)左移1位想当于*2

2、用途:快速计算一个数乘以2的n次方 (8<<3 等同于8*2^3)


(3)>>右移 各二进位全部右移n位,保持符号位不变

1、右移不会改变一个数的符号

    x 右移 n 位就相当于除以2的n次方

2、用途:快速计算一个数除以2的n次方 (8>>3等同于8/2^3)


(4)位运算技巧:

1)任何数和1进行&操作,得到这个数的最低位1001

          &0001

     ------------

           0001

2)想把某一位置0

        11111111

     &  11111011

     ------------

        11111011

  


  11.变量地址获取及存储原理


(1)获取变量地址的方法

%p 输出一个地址 定义在函数中变量我们称为局部变量 

先分配字节地址大内存,然后分配字节地址小的内存

(2)变量在内存中存储的原则

低位保存在低地址字节上,高位保存在高地址字节上 


  12.整型变量修饰符


     (1)改变整型变量所占存 

short2字节 %hd
int 4字节 %d %i
long 8字节 %ld
longlong 8字节 %lld (主要是为了解决32位机器问题)
所有修饰符都是用来修整形
 *long long 类型
32位系统下: long4个字节 long long 8个字节
64位系统下: long8个字节 long long 8个字节


     (2)改变整型变量的符号

signed表示是有符号的(默认的就是有符号数)
unsigned表示是一个无符号的数 (正数的取值范围会扩大一倍)

 


  13.char类型数据存储


(1)char型常量存储问题

字符型变量占一个字节,奇怪的是C语言认为'a'是4个字节,而C++语言认为'a'是1字节.

(2)存储原理

chara='a' ----->取出'a'的ASCII码值,97,然后转换2进制,存储在一个字节中

(3)注意事项

1)当把一个字符赋值给一个char类型变量,那么系统首先查这个字符所对应的ASCII码,

  然后把这个ASCII值放到变量中

2)根据变量中存储的ASCII值,去查ASCII表中对应字符,然后把这个字符打印控制台上,

  整形和字符型可以互相转换。

3)charz = '我'; char字节,一个中文字符占3字节(unicode表),所有char不可以存储中文

4)不支持多个字符,多个字符是字符串 





二.函数


  1.函数的概述

C源程序是由函数组成的。虽然在前面各章的程序中大都只有一个主函数main(),但实用

往往由多个函数组成。函数是C源程序的基本模块,通过对函数模块的调用实现特定的功能。

       

  2.函数的分类

1) 从函数定义的角度看,函数可分为库函数和用户定义函数两种。

2) 语言的函数兼有其它语言中的函数和过程两种功能,从这个

   角度看,又可把函数分为有返回值函数和无返回值函数两种。

3) 从主调函数和被调函数之间数据传送的角度看又可分为无参函数和有参函数两种。

4) C语言提供了极为丰富的库函数,这些库函数又可从功能角度作以下分类。

 

  3.自定义函数的书写格式

函数定义到使用分三步:1、声明。2、定义函数。3、调用函数。

 

函数的基本格式:

 

返回值类型 函数名称(函数参数){

 

函数体;

 


  4.自定义函数的类型

(1)无参无返回值函数

一般形式如下:

void 函数名(){

 

声明部分      //定义局部变量

语句

 

}

 

(2)无参有返回值函数

一般形式如下:

返回值类型 函数名(){

 

声明部分

语句

 

return 返回值类型变量或常量;    //返回给主调函数

 

}

    (3)有参有返回值函数

一般形式如下:

返回值类型 函数名(形式参数表列){

 

 声明部分

语句

 

return 返回值类型变量或常量;

 

}

 

 

(4)有参无返回值函数

 

一般形式如下:

void 函数名(形式参数表列){

 

声明部分

语句

 


    形式参数表列表的格式:类型 变量名,类型 变量2,.......

 
:定义函数的时候,函数名后面小括号中的参数,简称形参
     调用函数的时候,函数名后面小括号中的参数,简称实参 


  5.函数的参数传递过程

1)形参变量只有在被调用时才分配内存单元在调用结束时,即刻释放所分配的内存单元。

  因此,形参只有在函数内部有效。函数调用结束返回主调函数后则不能再使用该形参变量。

2)实参可以是常量、变量、表达式、函数等无论实参是何种类型的量,在进行函数调用时,它

  必具有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使实参获得确定值。

3)实参和形参在数量上,类型上,顺序上应严格一致,否则会发生类型不匹配”的错误。 

  6.函数的返回值及注意事项

(1)函数的返回值

函数的值(或称函数返回值)是指函数被调用之后,执

函数体中的程序段所取得的并返回给主调函数的值。

(2)使用注意事项

1) 函数的值只能通过return语句返回主调函数。

2) 函数返回值的类型和return实际返回的值类型应保持一致。如果两者不一

   致,则以return实际类型为准,自动进行类型转,最后转换成返回值类型返回.

3) 如函数值为整型,在函数定义时可以省去类型说明.也就是说如果没有指

   定返回类型,那么C语言默认是int的类型(开发中不要省略返回值类型)

4) 不返回函数值的函数,可以明确定义为“空类型”,类型说明符为“void”.为了

   使程序有良好的可读性并减少出错,凡不要求返回值的函数都应定义为空类型。 

 

  7.函数的声明

在调用函数中调用某函数之前,应对该被调用的函数进行说

(声明),这与是实用变量之前要先进行变量说明是一样的.


在主调函数中对被调函数作说明的目的是使编译系统知道被调函数

返回值的类型,以便在主调函数中按此种类型对返回值作相应的处理。

其一般形式为:

返回值类型 被调函数名( 类型 形参, 类型 形参... );

返回值类型 被调函数名( 类型, 类型...);

注意

1) 如果被调函数的返回值是整型时,可以不对被调函数作说明,

   而直接调用。这时系统将自动对被调函数返回值按整型处理。

2) 当被调函数的函数定义出现在主调函数之前时,在主

   调函数中也可以不对被调函数再作说明而直接调用。

3) 普通的函数声明 

  8.函数的调用

C语言中,函数调用的一般形式为:

函数名(实际参数表);

1) 函数表达式函数作为表达式中的一项出现在表达式中,以函数

   返回值参与表达式的运算。这种方式要求函数 是有返回值的。

2) 函数语句函数调用的一般形式加上分号即构成函数语句。

3) 函数实参函数作为另一个函数调用的实际参数出现。这种情况是把该

   函数的返回值作为实参进行传送,因此要求该函数必须是有返回值的。

4)函数名不能和变量名同名 


  9.函数的嵌套调用说明

C语言中不允许作嵌套的函数定义。因此各函数之间是平行的,不存在上一级

函数和下一级函数的问题。但是C语言允许在一个函数的定义中出现对另一个

函数的调用。这样就出现了函数的嵌套调用。即在被调函数中又调用其它函

数。这与其它语言的子程序嵌套的情形是类似的。 


  10.递归函数 

(1)递归函数概述

   

   一个函数在它的函数体内调用它自身称为递归调用。这种函数称为递归函数。


(2)递归函数构成条件

   1)自己调用自己

   2)存在一个条件能够让递归结束

   3)问题的规模能够缩小 


  11.函数的应用实例

     例1:

/*

题目:由用户输入任意两个数,并进行累加求和.

*/

#include <stdio.h>
#include <stdlib.h>


int leiJa(int min, int max) {
int sum = 0;
for (int i = min; i < max; i++) {
sum += i;
}
return sum;
}

int inputIntNumWithRange(int min, int max) {
int input, count;
while (1) {
printf("请输入一个在 %d, %d 之间的数字\n", min, max);
count = scanf("%d", &input);
while (getchar() != '\n');

if( count > 0 ) { // 输入数字成功

if( input >= min && input < max ) {
// 输入的数字是符合要求的, 成功
break;

}
// 不再指定范围
printf("您输入的数字不在指定范围, ");
continue;
}
// 没有输入数字
printf("输入的不是数字, ");
}
return input;
}

int inputIntNumWithMax(int max) {
// int res = inputIntNumWithRange(0, max);

return inputIntNumWithRange(0, max);
}

int inputIntNum() {
return inputIntNumWithRange(INT32_MIN, INT32_MAX);
}


int main(int argc, const char * argv[]) {
// 使用上面的两个函数, 完成累加的运算
// int min = inputIntNumWithMax(102);
// int max = inputIntNumWithMax(102);

int min = inputIntNum();
int max = inputIntNum();


int res = leiJa(min, max);

printf("%d 累加到 %d(取不到) 的结果是 %d\n", min, max, res);

return 0;
}



  例2:

/*

题目:求阶乘: n!

// 含义: n * (n-1) * (n-2) * ... * 2 * 1

*/

#include <stdio.h>

int jiecheng(int n) {
if(n == 1) return 1;
return jiecheng(n - 1) * n;
}


int main(int argc, const char * argv[]) {

for (int i = 1; i < 10; i++) {
printf("%d\n", jiecheng(i));
}

return 0;
}