C语言基础

作者: 无尾树袋熊 | 来源:发表于2019-02-07 13:17 被阅读0次
    • c语言是由函数组成的
    • 先要执行main函数固定格式 :
    • int main(){
    • return 0 ;
      
    • }
    • ()是函数的标示,{}函数管辖的范围。

    注意点

    1. 函数名不可重复
    2. 要执行一个定义好的函数,需要在main函数中调用。格式:函数名();
    3. include<stdio.h>查找系统定义的函数

    4. c语言中的main函数写法多,标准写法如上
    5. 多行注释不能嵌套多行注释/* */
    6. 注释应用场景:思路分析,函数变量说明

    C基础

    一、关键字

    • 保留字,指一些被被赋予特殊含义的单词,一共有32个
    • 不能作为函数和变量的名称

    二、标识符

    • 程序员在程序中给函数、变量等起的名字就是标识符.目的是将某些东西区分开
    • 命名规则:
    1. 只呢由字母,下划线,数字组成
    2. 不能以数字开头
    3. 不能是关键字
    4. 严格区分大小写
    • 命名规范:
    1. 见名知意,驼峰命名:方便阅读

    三、C语言常量和变量

    • 数据的分类:静态,动态

    常量:固定的数据

    整型常量(整数)
    实型常量(小数)
    1. 单精度(例如:10.12f 或 10.12F)
    2. 双精度(默认都为双精度)
    字符型常量
    1. 字符型常量的 ''中只能放一个字符(例: 'a' '1')
    2. 特殊情况:转移字符除外('/t' '/n' '//')
    字符串型常量
    1. 可以放一个或多个字符("123" "你好")
    2. 系统会在末尾加上一个字符 '\0'作为结束标志

    变量:可以改变的数据

    定义变量: 数据类型 变量名1,变量名2;
    • 为什么指定数据类型:1.告诉系统,定义的变量对应的储存空间中,将来能够存储怎样的数据 2. 告诉系统需要分配多大的存储空间
    • 为什么指定变量名:为了找到开辟好的存储空间,并使用
    • 要使用变量,必须先初始化.否则变量中保存的都是一些垃圾数据
    • 变量输出:printf("变量名 = %i " ,变量名) 其中%i是占位符,int
    变量的作用域
    局部变量:定义在{}内的
    • 作用域:从定义变量的一行开始,直到}或return为止
    全局变量:定义在{}内外的
    • 作用域:从定义变量的一行开始,直到文件末尾

    注意点

    1. {}会新开辟一段存储空间
    2. 局部变量:在同一个作用域内,不能出现同名变量.不同作用域可以出现同名变量
    3. 全局变量:相同作用域,可以出现同名变量

    四、printf和scanf函数

    printf函数:

    1. 把指定的数据显示在屏幕上
    格式:
    1. printf("输出的内容");
    2. printf("格式化字符串",输出列表项);
    3. 格式化字符串:%[标示][输出宽度][.精度][长度]类型
    4. %i,%d:整型常量和变量 %f:单精度小数 %lf:双精度小数 %c:字符型常量变量
    输出宽度格式:

    指定输出内容位数 。如果输出内容大于或等于指定的宽度,则按照实际输出的宽度输出。如果如果输出内容小于指定的宽度,则在实际输出的内容前添加空格

    标志格式:
    1. -左对齐,默认右对齐
    2. +当输出值为正时,添加一个+号,默认不显示
    3. 0右对齐时,用0填充宽度,默认用空格(常用在日期格式上)
    4. 空格 输出值为正时,在前面加上空格,为负数加上负号
    精度格式:

    指定输出小数位数保留

    1. 其它格式: %[.]类型(为占位符)

    Scanf函数:

    用于接受键盘输入的内容,是一个阻塞式函数

    格式:
    1. scanf("格式化字符串",地址列表);
    2. &取地址符号: &变量名

    注意点:

    1. 单精度的小数,有效位数只有6-7位,超出后则为垃圾数据(有效位数是从小数点前开始计算)
    2. 双精度的小数,有效位数只有15-16位,超出后则为垃圾数据
    3. scanf如果接受的不是字符类型的数据.输入的空格,TAB,回车都是无效的
    4. scanf函数的格式化字符串不能以\n结尾,不然永远无法结束
    5. ==scanf函数的格式化字符串中还有别的字符串,必须要原样输入==
    6. scanf函数如果需要接受多个非字符类型的数据,可以通过空格,TAB,回车作为分隔符
    7. 清空输入缓冲区:
    • fflush(stdin);不能跨平台
    • setbuf(stdin,NULL);

    五、C语言运算符

    告诉程序执行特定算数或逻辑操作的符号

    • 操作数:参与运算的数
    • 表达式:利用运算符链接在一起的有意义,有结果的语句

    (1)算数运算符

    • 加减乘除:+ - * /

    (2)类型转换

    1.自动类型转换
    1.运算转换

    小类型转大类型:int -> double(大小一样才能运算,编译器自动转换)

    2.赋值转换

    例:

    int num = 3.14;
    printf("num = %i\n",num)
    
    2.强制类型转换

    例:

    double c = 3.33;
    int d = c;
    

    (2)赋值运算符

    1.简单赋值运算符

    = 将右边的值赋值给左边的变量

    • 右结合性
    2.复杂赋值运算符

    += -= *= /= %=
    例:

    b += 5; //b = b + 5;
    b -= 5; //b = b - 5;
    b *= 5; //b = b * 5;
    b %= 5; //b = b % 5;
    
    3.赋值运算符结合性
    1.右结合性
    int b = 10;
    b += 10 -5;// b = b + (10 - 5);
    
    2.优先级

    赋值运算的优先级 低于 算数运算符

    (3)自增自减

    快速加减1 例:

    int num = 1;
    num++; // num--;后加减
    ++num; // --num;先加减
    

    比较:

    int num = 10;
    int res = 10 + num++; //res = 20,num = 11;
    int res = 10 + ++num; //res = 21,num = 11;
    
    • 可以用于字符型变量.例:
    char ch = "m";
    ch++;
    printf("ch = %c\n",ch);//ch = e
    

    (4)sizeof运算符

    1.格式:
    1. sizeof(变量/常量/数据类型);
    int res = sizeof(3.14);
    int res = sizeof(double);
    
    int res = 10;
    int res = sizeof(res);
    //数据类型不能省略圆括号
    
    1. sizeof 变量/常量;
    2.作用:

    用于计算变量/常量/数据类型占用的存储空间

    (5)逗号运算符

    1. 用于简化代码
    2. 有运算结果
    3. 结果是最后一个表达式的值.例:
    int a,b,c;
    a = 10,b = 20,c = 30;
    int res = ((a + b),(a + c));// res = 40 面试常用
    

    (6)关系运算符

    • != == <= >= > <
    • 返回值:0 或 1
    • 非0即真.只有0是假
    int a,b;
    a = 10 ,b = 5;
    int res = a > b;//res = 1
    int res = a < b;//res = 0
    

    (7)逻辑运算符

    1.逻辑与 &&
    • 格式:表达式&&表达式
    • 一假则假 例:
    int res = (10 > 5)&&(20 > 19);//res = 1
    int res = (10 > 11)&&(20 > 19);//res = 0
    
    2.逻辑或 ||
    • 格式:表达式&&表达式
    • 一真则真 例:
    int res = (10 > 11)||(20 > 21);//res = 0
    int res = (10 > 11)||(20 > 19);//res = 1
    
    3.逻辑非 !
    • 格式: !表达式
    • 真为假,假为真 例:
    int res = !(10 > 9);//res = 0
    int res = !(10 < 9);//res = 1
    
    4.逻辑运算符结合性
    • && ||左结合性
    • 逻辑短路,只要第一个假,第二个表达式则不会运行.例:
    int num = 1;
    int res = (10 > 20)&&(++num > 0);
    //res = 1 num = 1 一假则假
    
    int num = 1;
    int res = (10 < 20)||(++num > 0);
    // res = 1 num = 1 一真则真
    
    • !右结合性
    • 可以连续非非非.例:
    int res = !!!(10 > 9);//res = 0
    

    (8)三目运算符

    • 格式:表达式? 结果A : 结果B;
    • 表达式为真,返回A;为假,返回B.例:
    int a = 10 , b = 5;
    int res = a > b ? a : b;//res = 10
    
    • ?:不能分开使用
    • 三目运算符优先级低于算数运算符

    注意点:

    1. 在+ - * /的运算中,整数和整数的运算结果一定是整数.整数和小数的运算结果一定是小数
    2. 在%中不能出现小数
    3. 在%中被除数为0,结果就为0
    4. 在%中,结果的正负性,取决于被除数
    5. 自动类型转换不会改变原有量的值
    6. 自增自减只能用与变量
    7. 自增自减最好单独出现.例如:
    int num = 10;
    int res = 10 + num;
    num++;
    
    1. 同一个表达式同一个变量同时自增自减,没有规定怎么运算,不同编译器结果不一样
    2. sizeof优先级高于算数运算符
    3. 关系运算符是左结合性(无法判断某个值是否在某个区间内).例:
    int res = 10 > 5 > 3;//res = 0
    
    1. <= < > >= 优先级高于 == !== ==先优先级后结合性==.例:
    int res = 10 == 10 > 9;//res = 0
    

    五、流程控制

    • 分为顺序结构,循环结构,选择结构

    (1)if选择结构

    格式:
    if(条件表达式){
        条件成立执行语句
    }
    其它语句
    
    if(条件表达式){
        条件成立执行语句
    }else{
        条件不成立执行语句
    }
    
    if(条件表达式){
        条件成立执行语句
    }else if(条件表达式){
        条件成立执行语句
    }else if(条件表达式){
        条件成立执行语句
    }else{
        条件不成立执行语句
    }
    
    if可以相互嵌套

    (2)switch选择结构

    格式:
    switch(表达式){ 
        case 表达式1:
          被表达式1控制的语句;
          break;
        case 表达式2:
          被表达式2控制的语句;
          break;
        default:
          被default控制的语句;
          break;
    }
    
    1. case穿透问题
    • switch中只要有一个被匹配了,其它的case和default就会失效.(break的作用就是结束当前的switch语句)
    • default==写在最后==,default后的break可以省略
    1. default书写位置可以随便写(尽量写在最后)
    2. switch后()里只能放表达式/变量/常量,并且是整型或能被提升为整型.例:
    switch(num) 
    switch(2) 
    switch(1 + 1) 
    switch(1.1) //报错,小数不能被提升为整型
    switch('a') //char本质为int类型
    
    1. switch的case后面只能放常量/表达式,并且是整型或能被提升为整型.例:
    case num //报错
    
    1. switch的case的值不能重复
    switch(2){
        case 1:
        
        case 1://会报错
    }
    
    1. case后不能定义变量,要定义必须加上{}.(作用域混乱)例:
    switch(1){
        case 1:
        int num = 666;//会报错
    }
    
    switch(1){
        case 1:{
        int num = 666;//没问题
        }
    }
    

    (3)循环结构

    1.while
    • 格式:
    while(条件表达式){
        条件满足才执行的代码
    }
    
    • 应用场景:企业开发中,某些代码需要重复执行的,就用while
    • 累加思想:定义变量记录每次的和
     while (i <= num) {
                res = res + i;
                i++;
            }
    
    2.dowhile
    do{
       被控制的语句 
    }while(条件表达式);
    //先执行,再判断
    

    -应用场景:验证

    3.for
    • 格式
    for(初始化表达式;条件表达式;循环后增量表达式){
        被控制的语句;
    }
    
    1. 初始化表达式在循环执行过程中只会执行一次

    (4)跳转语句

    1.break
    1. 只能用在switch和循环结构中, 离开应用的范围没有任何意义
    2. 作用是跳出循环语句 while , dowhile,,for,switch
    3. 如果循环嵌套的时候,break只会跳出所在(最近的)的循环
    4. 不能离开应用范围,不然会报错.例:
    if(1){
    printf("随便写点东西\n");
    break; 
    // 离开应用范围后会报错
    }
    
    2.continue
    1. 只能用在循环中,离开应用范围没有任何意义
    2. 作用:跳过本次循环,进入下一次循环
    3. 不能离开应用范围,不然会报
    4. 如果循环嵌套的时候,continue只会跳出所在(最近的)的循环
    3.goto
    1. 只能用于在同一个函数中跳转, 可以往前往后跳,只要是在同一个函数中
    2. goto需要配合标签使用(标签可以是任意的名称后面加上:).例:
    printf("第一行代码\n");
    goto lnj; 
    printf("第二行代码\n");
    lnj: printf("第三行代码\n"); //直接执行
    
    1. 一般不使用

    注意点

    1. if结构中只有一个{}中的语句会被执行
    2. if省略大括号后只有紧随其后的那条语句才受控制(else只与最近的没有被匹配的if匹配)
    3. {}单独出现代表的是一个代码块.例;
    int num = 10;
    {
        int num = 18;
        printf("%i\n",num);//18
    }
    printf("%i\n",num);// 10
    
    1. 如果if/while省略了{},那么后面不能再定义变量(作用域混乱)
    int num = 18;
    if(num >= 18)
        int num = 666;
        printf("开网卡");
    //看起来num的作用域是从定义的一行到return或}为止.但实际上num只有在if条件满足时才会执行,两者冲突.
    
    1. 任何值都有真假性
    2. 企业开发中一定不要用==来判断两个小数是否相等,可能会出现精度问题(建议使用 >= <=)
    3. 排序问题:两两比较后,最值会出现在最后
    4. 企业开发中能用if用if
    5. while省略大括号后只有紧随其后的那条语句才受控制
    6. while/if,任何值都有真假性,都可以嵌套其它合法代码
    7. 用于控制while的变量在循环的内部外部都可以使用.控制for的变量只能在循环内使用(企业开发中,能用for就用for)
    8. for和while都可以省略大括号.(省略后只能控制紧随其后的语句,且不能定义变量)
    9. 在企业开发中一般情况下,循环嵌套不会超过两层, 最多不超过三层
    10. 规律:循环嵌套的时候,外循环控制行数, 内循环控制列数
    11. 在企业开发中,但凡遇到需要解决很多行很多列的问题, 就要想到循环嵌套

    六、函数

    • 优点:提高了代码的复用性,有利于维护
    • 作用:将某些代码封装起来
    • 格式:
    返回值类型 函数名称(形参列表){
    被封装到函数中的代码;
    }
    

    (1)如何定义函数

    1. 确定形参列表(告诉调用者调用时是否需要传递一些辅助的数据)
    2. 确定返回值和返回值类型(返回的数据是什么类型, 返回值类型就写什么类型)
    3. return的作用之一就是将后面的数据返回给函数的调用者.例:
    int getMax(int num1, int num2){
        int max = num1 > num2 ? num1 : num2;
        return max;
    }
    int main(){
        int a = 10,b = 20;
        int res = getMax(a,b);
        printf("res = %i\n",res);//20
    }
    

    (2)函数声明

    • 如果将函数定义在调用之后,必须在调用前编写函数声明.
    • 函数声明;在调用前告诉编译器,我有一个名称叫什么,接受什么==类型参数,返回值==是什么.
    voide test{};
    int main(){
        test ();
        return 0;
    }
    viode test(){
        printf("test\n");
    }
    
    1. 函数的声明可以声明多次,但函数只实现一次
    2. 返回值是int类型,可以不用编写函数声明(了解)
    3. 函数声明必须写在调用之前

    (3)main函数

    1. main函数是系统自动调用的函数,不能手动调用
    2. 系统调用main函数时,默认会传递两个参数:
    int main (int argc,const char *argv[]){
        
    }
    //argc:第二个数组保存数据的个数
    //argv:默认保存了一个数据:当前文件的地址.并且可以动态的添加数据
    //默认情况下,调用main函数时,回给argv这个数组中存放一个元素
    
    1. return 0;目的是告诉系统是正常结束的

    (4)函数补充

    1.分类
    • 没有返回值,没有形参
    • 没有返回值,有形参
    • 有返回值,没有形参
    • 有返回值,有形参
    2.注意点
    • 如果没有写函数返回值类型,默认为int
    • 如果实际返回值和指定返回值类型不同,会转换为指定返回值类型

    (5)递归函数

    • 自己调用自己:可以实现循环的功能,但性能比循环差很多.例:
    //求n的阶乘:
    int factorial();
    int main()
    {
        int n = -1;
        printf("请输入一个数n = ?按回车键结束\n");
        scanf("%i",&n);
        setbuf(stdin,NULL);
        int res = factorial(n);
        printf("res = %i\n",res);
        return 0;
    }
    int factorial(int num){
        if(num == 1){
            return 1;
        }else{
             return factorial(num - 1)*num;
        }
    }
    
    • 企业开发中,一般情况下,不会使用递归.在面试或文件操作(遍历目录)中出现较多

    注意点:

    1. 函数可以有参数,也可以没有参数.函数的参数可以是零个或多个.
    int sum(int a, int b){
        return a + b;
    }
    
    1. 函数可以有返回值,也可以没有返回值(如果函数没有返回值, 那么返回值类型写void).例:
    void test(){
        printf("test\n");
    }
    
    1. (即使返回值类型,形参列表不同)函数的==名称也不能相同==
    2. 函数不能嵌套定义
    3. 如果是==基本类型的数据==(int,char,float,double)作为函数的参数,那么在函数内修改形参,不会影响外面实参的值
    4. 在函数内部不能定义和形参同名的变量

    七、进制和位运算

    (1)进制

    • 一种计数的方式
    1. 如果用16进制,前面加上0x(%x 输出)
    2. 如果用8进制,前面加上0(%0 输出)
    3. 如果用2进制,前面加上0b
    1. 2进制转8进制
    • 例如:将二进制01100100转换为八进制数
    从右至左每3位划分为8进制的1位, 不够前面补0
    001 100 100
    第0位: 100 等于十进制 4
    第1位: 100 等于十进制 4
    第2位: 001 等于十进制 1
    最终结果: 144就是转换为8进制的值
    
    2. 2进制转16进制
    • 例如: 将二进制01100100转换为十六进制数
    从右至左每4位划分为16进制的1位, 不够前面补0
    0110 0100
    第0位: 0100 等于十进制 4
    第1位: 0110 等于十进制 6
    最终结果: 64就是转换为16进制的值
    
    3. 其它进制转换为十进制
    101101 = (1 * 2 ^ 5) + (0 * 2 ^ 4) + (1 * 2 ^ 3) + (1 * 2 ^ 2) + (0 * 2 ^ 1) + (1 * 2 ^ 0)
              = 32 + 0 + 8 + 4 + 0 + 1
              = 45
              
    016  =   (0 * 8 ^ 2) + (1 * 8 ^ 1) + (6 * 8 ^ 0)
            =    0  + 8 + 6
            =    14
            
    0x11f =  (1 * 16 ^ 2) + (1 * 16 ^ 1) + (15 * 16 ^ 0)
             =   256  + 16 + 15
             =   287
    
    4.十进制快速转换为其它进制
    十进制        -->     二进制
       100          -->    1100100
       100 / 2   = 50     0
       50  / 2   = 25     0
       25  / 2   = 12     1
       12  / 2   = 6      0
       6   / 2   = 3      0
       3   / 2   = 1      1
       1   / 2   = 0      1
       
       
       十进制        -->     八进制
       100          -->     144
       100 / 8    = 12    4
       12  / 8    = 1     4
       1   / 8    = 0     1
       
       十进制        -->     十六进制
       100          --> 64
       100 / 16   =  6    4
       6   / 16   =  0    6
    
    5. 十进制小数转换为二进制小数
    • 整数部分,直接转换为二进制即可
    • 小数部分,使用"乘2取整(小数部分为0),顺序排列
    // 整数部分(除2取余)
      12
    /  2
    ------
       6    // 余0
    /  2
    ------
       3    // 余0
    /  2
    ------
       1   // 余1
    /  2
    ------
      0   // 余1
    //12 --> 1100
      
    // 小数部分(乘2取整数积)
      0.125
    *     2
      ------
       0.25  //0
       0.25
    *     2
      ------
        0.5  //0
        0.5
    *     2
      ------
        1.0  //1
        0.0
    // 0.125 --> 0.001
    
    // 12.8125 --> 1100.001
    
    6. 二进制小数转换为十进制小数
    • 整数部分按照二进制转十进制即可
      小数部分从最高位开始乘以2的负n次方, n从1开始
    // 整数部分(乘以2的n次方, n从0开始)
    0 * 2^0 = 0
    0 * 2^1 = 0
    1 * 2^2 = 4
    1 * 2^3 = 8
     // 1100 == 8 + 4 + 0 + 0 == 12
    
    // 小数部分(乘以2的负n次方, n从0开始)
    0 * (1/2) = 0
    0 * (1/4) = 0
    1 * (1/8) = 0.125
    // .100 == 0 + 0 + 0.125 == 0.125
    
    // 1100.001  --> 12.125
    
    7.原码反码补码
    • 计算机只能识别0和1,所以计算机中存储的数据都是以0和1的形式存储的
    • 数据在计算机内部是以补码的形式储存的, 所有数据的运算都是以补码进行的
    1. 正数的原码、反码和补码都是它的二进制.例12:
    0000 0000 0000 0000 0000 0000 0000 1100
    0000 0000 0000 0000 0000 0000 0000 1100
    0000 0000 0000 0000 0000 0000 0000 1100
    
    1. 负数的原码、反码和补码:
      • 二进制的最高位我们称之为符号位,最高位是0代表是一个正数,最高位是1代表是一个负数
      • 一个负数的原码,是将该负数的二进制最高位变为1
      • 一个负数的反码,是将该数的原码除了符号位以外的其它位取反
      • 一个负数的补码, 就是它的反码 + 1
      • 例:-12的原码,反码,补码:
    0000 0000 0000 0000 0000 0000 0000 1100 //12二进制
    1000 0000 0000 0000 0000 0000 0000 1100 //-12原码
    1111 1111 1111 1111 1111 1111 1111 0011  //-12反码
    1111 1111 1111 1111 1111 1111 1111 0100 //-12补码
    
    • 为什么要引入反码和补码
      • 计算机只能做加法运算,不能做减法和乘除法,所有的减法和乘除法内部都是用加法来实现的
      • 对于减法来说,如果使用原码结果是不正确的, 所以才引入了反码
      • 对于0来说,前面的负号没有任何意义, 所以才引入了补码
      • 由于int只能存储4个字节,也就是32位数据,而计算的结果又33位,所以最高位溢出了,符号位变成了0,所以最终得到的结果是0.例:
    // 1 - 1; 1 + (-1);
    0000 0000 0000 0000 0000 0000 0000 0001 // 1补码
    1111 1111 1111 1111 1111 1111 1111 1111 // -1补码
      ---------------------------------------
    10000 0000 0000 0000 0000 0000 0000 0000 // 计算结果补码
     0000 0000 0000 0000 0000 0000 0000 0000 //  == 0
    

    (2)位运算

    1. & 按位与
    • 规则: 一假则假
    • 规律: 任何一位和1相与,结果还是原来的那一位
    9 & 3 = ?
    0000 0000 0000 0000 0000 0000 0000 1001 // 9的补码
    0000 0000 0000 0000 0000 0000 0000 0011 // 3的补码
    -----------------------------------------------
    0000 0000 0000 0000 0000 0000 0000 0001 // 1
    
    2. | 按位或

    规则: 一真则真

    0000 0000 0000 0000 0000 0000 0000 1001 // 9的补码
    0000 0000 0000 0000 0000 0000 0000 0011 // 3的补码
    -----------------------------------------------
    0000 0000 0000 0000 0000 0000 0000 1011
    
    3. ~ 按位取反

    规则: 真变假, 假变真

    4. ^ 按位异或
    • 规则: 相同为0, 不同为1
    0000 0000 0000 0000 0000 0000 0000 1001 // 9的补码
    0000 0000 0000 0000 0000 0000 0000 0011 // 3的补码
    -------------------------------------------
    0000 0000 0000 0000 0000 0000 0000 1010 // 10
    
    • 规律:
      • 任何两个相同的值异或之后的结果都是0
      • 任何一个数和0异或之后的结果还是那个数
      • 任何一个数异或另外一个数两次之后, 结果还是那个数
    • 应用场景:简单的加密
    int pwd = 123456789;
    int res = pwd ^ 998;
    printf("加密之前: %i\n", pwd);
    printf("加密之后: %i\n", res);
    int res2 = res ^ 998;
    printf("解密之后: %i\n", res2);
    return 0;
    
    5. << 按位左移
    • 乘以2的n次方
    • 移动规则:从符号位开始整体移动, 多余的砍掉, 缺少的用零补
    • 计算规律: 一个数左移几位就是 这个数乘以2的多少次幂(9 * 2(1) = 18,9 * 2(2) = 36)
     9 << 1
    0000 0000 0000 0000 0000 0000 0000 1001 // 位置参考
    000 0000 0000 0000 0000 0000 0000 10010 // 9的补码
    
    • 应用场景:==在企业开发中一旦想要某个数乘以2的多少次幂, 就要想到左移==
    5. >> 按位右移
    • 除以2的n次方
    • 移动规则:除符号位以外整体右移,多出来的砍掉, 缺少的用符号位填充.例:
    1000 0000 0000 0000 0000 0000 0000 1001 // -9源码
    1111 1111 1111 1111 1111 1111 1111 0110 // -9反码
    1111 1111 1111 1111 1111 1111 1111 0111 // -9补码
    //右移后
    11111 1111 1111 1111 1111 1111 1111 011 //补码
    11111 1111 1111 1111 1111 1111 1111 010 // 右移完毕的结果, 反码
    10000 0000 0000 0000 0000 0000 0000 101 // 右移完毕的结果, 源码
    
    • 输入整数,==输出二进制==:
    void printBinary(char value){
        // int 4 --> 32
        // char 1 --> 8
        // 在企业开发中 , 数字我们称之为魔鬼
    int len = sizeof(value) * 8;
    for(int i = 0; i < len; i++){
        int temp = (value >> (len - 1 - i)) & 1;
        printf("%i", temp);
        if(((i+ 1) % 4) == 0){
        printf(" ");
        }
    }
    

    注意点:

    1. 变量的内存是连续的
    2. 内存地址从大到小(只要定义变量,就会开辟内存空间)
    3. 计算机会从内存地址大的开始分配内存(内存寻址从大到小)也就是说先定义的变量内存地址大于后定义的变量
    4. 由于内存寻址是从大到小,所以存储补码也是从大到小(也就是从高位开始存储)
    //高位         -->           低位
    00000000 00000000 00000000 00001001
    
    1. ==变量的地址是所占用内存空间最小的那个地址==

    类型说明符

    • 一般用于修饰int类型的
    1. 说明长度的:
    short int//2个字节
    long//32位编译器中4个字节,64位8个字节
    long long//8个字节
    
    • 注意点:
      1. 如果存储的数据超出了类型对应的取值范围,那么就会导致存储的数据不对
      2. 由于内存非常有限,所以在编写程序的时候, 尽量合理的定义变量
      3. 由于说明长度的类型说明符一般都是用于说明int类型的,所以在使用的时候可以省略int:
    short num1 = 123; // short == short int
    long num2 = 123; // long  == long int
    
    1. 说明符号位的
    • unsigned 无符号的:
    • 注意点:
      1. 不把二进制的第一位当做符号位来使用,所以只能存储零和正数,不能存储负数
      2. 如果变量被unsigned修饰了,那么取出的时候必须使用%u,%u就代表用无符号的方式取出
      3. 应用场景:存储银行存款,学生的分数等不能出现负数的情况
    • signed 有符号的:
      • 默认int就是有符号的,就可以保存负数,零,正数,所以signed一般用不上

    注意点:

    1. c语言的rand函数是一个伪随机数.(生成随机数)例:
    //先导入:#include();
    srand(time(NULL));//种一个种子
    int res = rand();
    
    1. 三目是一个运算符,所以必须有结果(结果A和结果B的位置放的必须是变量,常量, 表达式)(如果放的是一个函数, 那么这个函数必须有返回值)
    2. 企业开发中,尽量不要写数字
    3. %p是专门用于输出变量地址的
    4. &是专门用于取出变量地址
    5. C语言的规则:不看怎么存只看怎么取

    相关文章

      网友评论

        本文标题:C语言基础

        本文链接:https://www.haomeiwen.com/subject/tanwsqtx.html