暑期培训总结日记#NO.6

C continue

复习:

进制转换:

十进制转二进制:对2求余,直到商为0,过程中余数的逆序

二进制转十进制:2^(n-1)每位结果相加

二进制转八进制:三位二进制对应一位八进制

二进制转十六进制:四位二进制对应一位十六进制

代码中0开头的是八进制,0x开头的是十六进制

%o 八进制   %x十六进制

原反补码:

正数/无符号数的原反补一致

负数先转换为二进制,除符号位外各位取反得到反码,反码+1得到补码(反之亦然)

补码转数据:无符号直接转,有符号看最高位,0直接转,1为负数

位运算符:

~取反在位运算符中优先级最高  

单目、算术、、关系、逻辑、三目、赋值 (大部分时候优先级)

int num =40;num =num>>2+1;printf(“%d”,num);

^按位异或  >>左边补符号位   <<右边补0

注意:只要表达式中出现了位运算符,一定要先转换成二进制进行计算

自定义函数:

函数声明、函数定义、函数调用  三步GO

函数定义在调用之前,声明可以省略;声明的内容要与定义完全一致;如果不需要返回值或者参数则一定要写void;在函数调用前,没有声明、定义则会产生隐式声明的警告

一、函数传参:

  1. 形参变量、函数内定义的变量,都只属于它所在函数,出了该函数就不能再用
  2. 普通实参与形参之间是通过赋值的方式传递数据的(单向值传递)
  3. return其实是把数据存放到一个公共区域(函数之间都可以访问的区域),如果不写return语句,就会去公共区域读取原本已经存在的数据,就得到一个垃圾数据
  4. 当数组作为函数的参数时,[]中的长度就会丢失,传数组时需要额外增加一个变量传递数组的长度
  5. 数组作为函数参数传递时,传递的是数组的首地址,称“址传递”(传递地址),函数和函数调用者可以共享同一个数组

练习1:实现函数,找出数组中的最大值(调用者提供数组通过函数返回最大值)

#include <stdio.h>
int findmax(int arr[],int len);
int findmax(int arr[],int len)
{
    int temp=arr[0];
    for(int i=1;i<len;i++)
    {   
        if(arr[i]>temp)
            temp=arr[i];
    }   
    return temp;

}
int main(int argc,const char* argv[])
{
    int arr[10]={14,13,25,85,4,54,69,91,20,10};
    printf("%d",findmax(arr,10));
}

练习2:实现函数,对数组进行升序排序(同上)

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void uparr(int arr[],int len);
void uparr(int arr[],int len)
{
    int temp=0,min=0;
    for(int i=0;i<len-1;i++)
    {   
        min=i;
        for(int j=i;j<len;j++)
        {
            if(arr[j]<arr[min])
            {
                temp=arr[j];
                arr[j]=arr[min];
                arr[min]=temp;
            }
        }
    }   
}
int main(int argc,const char* argv[])
{
    srand(time(NULL));
    int arr[10]={};
    for(int i=0;i<10;i++)
    {   
        arr[i]=rand()%100;
    }   
    uparr(arr,10);  //万能公式在心中 sizeof(arr)/sizeof(arr[0])
    for(int i=0;i<10;i++)
    {   
        printf("%d ",arr[i]);
    }   
}

练习3:实现函数,查找数组中是否存在某个值(由调用者提供),如果存在则返回该值的下标

#include <stdio.h>
int find(int arr[],int len,int key);
int find(int arr[],int len,int key)
{

    /*  
    // 对分查找(要求有序)
    int left=0,right=len-1;
    while(l<=r)
    {
        int p=(l+r)/2;
        if(key==arr[p]) return p;
        if(key<arr[p]) r=p-1;
        else l=p+1;
    }
    return -1;
    */
    int i=0;
    for(i=0;i<len;i++)
    {   
        if(arr[i]==key)
        {
            return i;
        }
    }   
    return -1; 
}
int main(int argc,const char* argv[])
{
    int arr[10]={1,2,3,4,5,6,7,8,9,10};
    if(find(arr,10,5)==-1)
        printf("no\n");
    else
        printf("%d",find(arr,10,5));

}

设计函数的建议:

  1. 一个函数最好就解决一个问题,降低错误率,提高可读性
  2. 尽量减少函数之间的依赖层数(降低耦合度)
  3. 数据由调用者提供,结果返回给调用者(提高函数的通用性)
  4. 考虑函数的非法参数,可以通过返回值的方式告诉调用者你的参数有误,也可以通过注释的方式写明情况(提高函数的健壮性)。

二、进程映像:

程序:存储在磁盘上的可执行文件(二进制文件、脚本文件)

进程:在系统中运行中的程序

进程映像:进程内存的分布情况(要背☆★

text 代码段(权限只读,强制修改就会产生段错误--非法访问内存) 存储二进制指令(每条代码换成二进制后)、常量数据、初始化过的全局变量、初始化过的静态局部变量

data 数据段  初始化过的全局变量、初始化过的静态局部变量

bss 静态数据段 未初始化过的全局变量,进程运行前,该段内存会自动清理为零(不初始化会变0)、未初始化过的静态局部变量(不初始化同样变0)

stack 栈 局部变量、块变量,由操作系统管理的,会自动申请、释放,在进程运行过程中自动申请、释放内存。但是所占内存小

heap 堆 由程序员手动管理,内存足够大

三、局部变量和全局变量:

全局变量:定义在函数外的变量。1.存储位置:data(初始化)或者bss(未初始化)2.生命周期:程序开始到程序结束3.作用范围:在程序的任意位置

局部变量:定义在函数内的变量。1.存储位置:stack栈内存2.生命周期:从函数调用定义开始到函数结束3.作用范围:只能在函数内使用

块变量:定义在语句块内的变量 if/for/while1.存储位置:stack栈内存2.生命周期:从函数调用定义开始到函数结束3.作用范围:只能在语句块内使用(与局部差别)

当全局变量和局部变量同名时,在函数内会屏蔽掉全局变量,同名变量在块变量中也会屏蔽全局变量和局部变量。因此建议全局变量首字母大写

四、类型限定符:

auto :用于定义自动分配内存、释放内存的变量(局部变量),不加auto就代表了加。注意:全局变量是不能用auto修饰的!C11中auto变成了自动识别类型:auto num=10;自动定义类型

extern :声明变量,告诉编译器此变量已经在别处定义过了请放心使用,extern+变量声明(变量不能+等于 extern 类型名 变量名),但是只能临时让编译通过,在链接时如果找不到该变量的定义依然会报错,不能在声明变量时赋值。

在多文件编程中,假设a.c中定义了全局变量N,想要在b.c中使用N时就需要在使用前声明该变量;

static(很关键) :1.会改变变量存储位置:改变局部变量的存储位置(静态局部变量),从stack改为data或者bss(根据是否初始化);2.延长生命周期:延长了局部变量的生命周期直到进程结束为止;3.限制作用范围:限制全局变量、函数的作用范围,只能在本文件内使用----可以防止全局变量或函数的命名冲突、也可以防止被别的文件使用(必答三句话)

const (常数):“保护”变量值不能被显示地修改,但是可以通过访问内存的方式来修改值;但是如果修饰的是初始化过的全局变量、初始化过的静态局部变量,则该变量会从data转到text变成了“常量”,不能够强制修改

volatile(易变的不稳定的) :如果变量的值没有被显示修改,那么在使用该变量时不会从内存中读取,而是继续使用上次读取的结果,这个过程叫做编译器的取值优化,一般变量都会进行。如果变量被volatile修饰之后,编译器不会对该变量进行取值优化,每次都会从内存中重新读取,读取之间值就可能发生改变volatile num;(num==num)可能为假。一般硬件编程时、多线程编程时会使用到

register :(存储介质:硬盘-->内存-->高级缓存-->寄存器)申请把变量的存储介质由内存改为寄存器,由于寄存器数量有限,不一定能够申请成功。注意:寄存器变量不能取地址

typedef :类型重定义,定义变量时,如果在类型前面加typedef,那么变量名就变成了这个类型的新名字:int num;-->typedef int num;int a;num b  注意:typedef不是替换关系

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

河马天上飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值