精华内容
下载资源
问答
  • c语言

    2019-06-01 09:30:17
    文章目录C语言笔记访问此博客linux常用命令:文件夹权限说明:vi编辑器:C语言编译过程:预处理-----编译-----汇编-----链接寄存器是CPU内部最小的存储单位原码反码补码:break作用:数组数组名求三个数最大值求数组...

    C语言笔记

    程序员除了素质一无所有

    纯手工打造

    独具匠心

    Mr_zhang

    • 访问此博客

    • 好评
    • 非常好评
    • 极度好评

    文章目录

    • linux目录结构:
      /:根目录
      /bin: /usr/bin:可执行二进制文件的目录
      /lib: /usr/local/lib:系统使用的函数库的目录
      /home:系统默认的用户家目录
      /usr/include:头文件所在的目录

    • 文件分类:普通文件,目录文件,设备文件,管道文件,链接文件
      文件权限:访问用户,访问权限
      访问用户:文件所有者,用户组,其他用户
      访问权限:读权限(r),写权限(w),可执行权限(x)

    linux常用命令:

    1. 查看帮助文档:* --help , man * 手册
    2. 查看文件信息:ls -a所有 -l详细 -h人性化
    3. 输出重定向命令:>
    4. 分屏显示:more
    5. 管道:|
    6. 清屏:clear
    7. 切换工作目录:cd
    8. 显示当前路径:pwd
    9. 创建目录:mkdir
    10. 创建文件 :touch
    11. 删除文件 :rm
    12. 建立链接文件:ln -s软链接
    13. 查看文件内容:cat
    14. 文本搜索:grep
    15. 查找文件:find
    16. 拷贝文件:cp -r文件夹
    17. 移动文件:mv
    18. 获取文件类型:file
    19. 归档管理:tar
    20. 文件压缩解压:gzip -cvf 压缩 -xvf 解压
    21. 文件压缩解压:bzip2
    22. 查看命令位置:which

    • 软链接:
      1.类似于windows的快捷方式,软链接依赖于源文件存在
      2.如果源文件删除,软链接没有意义

    • tar只负责打包,解包,不进行压缩
      打包:tar -cvf xxx.tar 需要打包的文件
      解包:tar -xvf xxx.tar 需要解包的文件
      指定目录解包:tar -xvf xxx.tar -C 指定路径目录

    • 如何查看某个目录的大小:
      du ./目录 -h

    • gzip压缩tar包
      压缩:gzip [-r] xxx.tar 自动在当前目录生成:xxx.tar.gz
      解压:gzip [-d] xxx.tar
      压缩打包:
      tar -czvf xxx.tar.gz 所需文件
      bzip2压缩tar包
      压缩:bzip2 [-r] xxx.tar 自动在当前目录生成:xxx.tar.bz2
      解压:bzip2 [-d] xxx.tar
      bzip2压缩打包:
      tar -cjvf xxx.tar.dz2
      解压解包:tar -xjvf xxx.tar.dz2

    • 创建新用户:
      useradd -d /home/名称 用户名 -m
      更改密码:passwd 用户名

    • 曾登陆用户时间历史:last


    创建一个用户(系统默认创建一个用户组,这个用户组的名字和用户的名字是一样的)
    查看用户信息:cat /zhang/passwd
    zhang:x:1000:1000:zhang,:home/zhang:/bin/bash
    第一个1000代表是用户id
    第二个1000代表是这个用户属于哪个组,组id


    更改权限:chmod
    chmod 777(4 2 1)文件名 可读可写可执行 r 4 w 2 x 1
    u 所有者 g 用户 o 其他用户
    chmod u+w 文件名

    文件夹权限说明:

    x:没有此权限,不允许用户进入
    r:没有这个权限,无法查看文件夹的内容
    w: 没有这个权限,无法新建和删除文件
    查看当前日历:cal
    显示或者设置时间:date
    查看进程信息:ps -a显示终端的所有进程,包括其他用户的进程 -u显示进程的详细状态
    -x 显示没有控制终端的进程
    ps -aux | grep xxx 利用管道查询进程
    杀死进程:kill -9强制杀死进程
    动态进程:top
    重启:reboot , init 6i
    关机:shutdown now , init 0
    查看或配置网卡信息:ifconfig


    vi编辑器:

    进入插入模式:i
    退出插入模式:Esc
    :wq 保存并退出
    :q!强制退出
    :x给文件加密码
    :!命令 暂时离开vi,执行命令
    i 光标位置当前处插入文字
    o光标位置下方开启新行
    O光标位置上方开启新行
    I光标所在行首插入文字
    A光标所在行尾插入文字
    dd 从当前行剪切(删除)
    yy 从当前行复制
    p粘贴
    u 撤销
    gg去第一行句首
    G去最后一行句首
    xgg去指定一行句首
    /xxx 在vi中查找xxx
    n下一个
    N上一个
    :set nu 设定行号
    :set nonu 取消行号

    在linux下,指向用户编译的可执行程序,如果没有配置环境,在当前路径前面必须加 ./
    system:
    功能:在已经运行的程序中执行另外一个外部程序
    参数:外部可执行程序的名字
    返回值:不同系统返回值不一样
    字符编码:
    window默认支持的中文编码为gbk,gb2312,ANSI
    linux默认支持的中文编码为 UTF-8

    只在windows有效:我们使用的是windows命令
    calc 计算器
    mspaint 画图板
    notepad 记事本
    windows图形界面只有两个:Qt,MFC(微软vs)
    vs中C语言可以嵌套汇编代码

    C语言编译过程:预处理-----编译-----汇编-----链接
    1. 预处理:宏定义展开,头文件展开,条件编译等,同时将代码的注释删除,这里并不会检查语法
    2. 编译:检查语法,将预处理后文件生成汇编文件
    3. 汇编:将汇编文件生成目标文件(二进制文件)
    4. 链接:C语言写的程序是需要依赖各种库的,所以编译之后还需要把库链接到最终的可执行程序中去
      分布编译:
      预处理:gcc -E hello.c -o hello.i
      编 译 :gcc -S hello.i -o hello.s
      汇编 :gcc -c hello.s -o hello.o
      链接 :gcc hello.o -o hello_elf

    交换文件说明:
    1.vi写文件,没有保存就关闭,自动生成一个后缀为.swp交换文件,保存了前面写的内容
    2.先恢复,再删除

    寄存器是CPU内部最小的存储单位
    1. 如果需要运算,不能在内存中直接运算
    2. 如果需要运算,把内存中的数据加载到寄存器,在运算
    3. 把运算结果从寄存器移回内存中

    数据类型的作用:告诉编译器定义这么一个类型的变量需要分配多大的空间
    变量在使用前必须先定义,定义变量前必须有相应的数据类型
    标识符命名规则:
    标识符不能是关键字
    标识符只能由字母,数字,下划线组成
    第一个字符必须为字母或下划线
    标识符中字母区分大小写
    1Byte=8bit
    %d : 以10进制的方式打印
    %o :以8进制的方式打印
    %x :以16进制的方式打印
    int a=123 //以十进制方式赋值
    int a=0123 //以八进制的方式赋值
    int a=0xABC //以十六进制方式赋值


    原码反码补码:

    (1)存储1字节(8位)大小的数字(char)
    原码(用户角度):原始的二进制
    1.用户的数字分为正负数,符号位的存储
    2.最高位为符号位:0代表为正数,1代表为负数
    3.1000 0001 左边是最高位,右边是低位

    +1 :0000 0001
    -1 :1000 0001
    +0 :0000 0000
    -0 :1000 0000

    原码存储导致2个问题:
    1.0有两种存储方式
    2.正数和负数相加,结果不正确(计算机只会加不会减)

    以原码的方式来算:

    反码(为了算补码)
    0.正数的原码和反码是一样的
    1.求原码
    2.在原码的基础上,符号位不变,其他位取反(0为1,1为0)
    +1 :0000 0001
    -1 :1111 1110
    +0 :0111 1111
    -0 :1111 1111
    反码存储导致1个问题:
    1.0有两种存储方式(0不分正负,只有一种存储方式)

    以反码的方式计算:
    1 - 1 = 1 + (-1)
    1 : 0000 0001
    -1 : 1111 1110
    1111 1111 = -0
    计算机存储数字以补码方式存储(为了解决负数的存储)

    补码:
    1.正数的原码,反码,补码都一样
    2.补码为其反码+1

    +1 :0000 0001
    -1 :1111 1111
    +0 :0111 1111
    -0 :1 0000 0000(因为8位,所以最高为丢弃) =0000 0000

    以补码的方式来算:
    1-1 = 1 + (-1)
    1: 0000 0001
    -1: 1111 1111
    1 0000 0000 = 0
    //0x81转化为二进制1000 0001,最高位为1,说明是负数

    char a = 0x81;
    printf("%d\n",a);
    

    结果是 -127
    补码:1000 0001
    反码:1111 1110
    原码:1111 1111 = -127

    char类型为1字节(8位)范围:有符号: -128~127 无符号:0~255
    -0系统当成 -128
    %x,系统默认以4字节(32位)大小打印
    %d,以有符号来打印
    %u,以无符号来打印
    赋值或运算,不能越界

    sizeof的功能是计算一个数据类型的大小,单位为字节
    int占4个字节 short占2个字节
    字符型(char)
    1.内存中没有字符,只有数字
    2.一个数字,对应的一个字符,这种规则叫做ASCII
    3.使用字符或数字给字符变量赋值是等价的

    4.字符类型本质上就是1个字节大小的整形
    逻辑运算符
    !(逻辑非) :如果a为假,则!a为真,如果a为真,则!a为假
    &&(逻辑与) :如果a和b都为真,则结果为真,否则为假
    ||(逻辑或) :如果a和b有一个为真,则结果为真,二者都为假时,结果为假

    运算符和表达式
    1.相除得到小数问题
    a)两个整数相除,只是取整数,不会带小数

    int a=1/2; // a=0

    b)要想得到小数的结果,分子分母至少有一个是小数

     double a
     a=1.0/2;// a=0.5
     a=1/(double)2;
    

    死循环
    //{ }可以不写,不写只有第一个语句属于循环

    while1{
    
    }
    

    //{ }必须写,语法

    do
    {
    
    }while(1)
    

    //{ }可以不写,不写只有第一个语句属于循环

    for(;;)
    {
    
    }
    

    循环的嵌套:任何一个循环的内部可以调用其他的循环

    while()
    {
      while()
      {
        do
         {
           for()
             {
              while()
                {
     
                }
              }    
          }while();
      }
    }
    

    int i=0;
    int j=0;
    int num=0;

    /*
    1.i=0;
    2.判断i<10的条件,条件为真,执行for(j=0;j<10;j++){}内容,条件为假,跳出循环
    3.执行{}内部

    */

    for(i=0;i<10;i++)
    {
    for(j=0;j<10;j++)
    {
    num++;
    }

    }

    break作用:

    1.跳出switch语句
    2.跳出循环
    3.如果有多个循环,跳出最近的内循环
    continue:属于循环,跳出本次循环,下次继续
    goto:任意地方都可以使用,无条件跳转,勿滥用

    数组

    #include<stdio.h>
    int main()
    {
    int a;//定义一个普通变量
    //1.同一个{}内部,数组名不能和其他变量,其他数组名同名
    //2.定义数组,[]最好是常量
    int n=10;
    int b[n];
    //3.使用数组时,[]里 可以是变量,可以是常量,也可以是表达式
    }
    
    
    int main01()
    {
    //1.定义一个数组,数组内部有10个int类型的元素(变量)
    //2.定义数组和定义变量的区别,名字后面加[],[]里面写元素个数
    //3.数组在内存中是连续存储的
    //4.通过下标访问数组的元素,下标从0开始,从0到9,没有a[10]这个元素
    //5.有多少个[]就是多少维
    int array[10];
    array[0]=0;
    array[1]=1;
    array[2]=2;
    }
    
    1. 编译器不是我们想象中那么智能,有些错误不能立马呈现
      错误:
    2. 编译错误(语法出错)
    3. 运行时错误(运行时异常),有些错误不能立马呈现

    [ ]内部的变量或数组,不初始化,它的值为随机数

    数组名

    # include <stdio.h>
    int main()
    {
    int a[10];
    /*1.数组名是常量,不能修改*/
    /*2.数组名的地址是数组首元素的地址*/
    printf("a=%p,&a[0]=%p",a,&a[0]);
    /*3.sizeof(数组名)测数组总大小 :10(元素)*4(一个元素4个字节)=40*/
    printf("sizeof(a)=%lu\n",sizeof(a));
    };
    

    求三个数最大值

    #include<stdio.h>
    int main()
    {
     int a=10;
     int b=20;
     int c=30;
     int max;
     max=a>b?a:b;
     printf("max=%d\n",max);
     max=(a>b?a:b)>c?(a>b?a:b):c;
    printf("max=%d\n",max);
     return 0;
    }
    
    int main01()
    {
     int a=10;
     int b=20;
     int c=30;
     int max;
     if(a>b)
    {
     max=a;
    }else if
    {
     max=b;
    }
    if(max>c)
    {
     printf("最大值为%d\n",max);
    }else
    {
     printf("最大值为%d\n",c); 
    }
    }
    

    求数组最大值

    #include<stdio.h>
    int main()
    {
     int a[]={10,-1,20,3,5,9,1,6,50,6};
     int n=sizeof(a)/sizeof(a[0]);
     int max=a[0];
     int i=0;
     for(i=1;i<n;i++)
     {
      if(a[i]>max)
    {
     max=a[i];
    }
    }
    printf("数组最大值为%d\n",max);
    return 0;
    
    }
    

    数组翻转

    Alt text

    #include<stdio.h>
    int main()
    {
     int a[]={1,2,3,4,5,6,7,8,9};
     int n=sizeof(a)/sizeof(a[0]);  /*元素个数*/
     int i=0;     /*首元素下标*/
     int j=n-1;  /*尾元素下标*/
     int tmp;
     while(i<j)
     {
     /*交换a[i]和a[j]*/
      tmp=a[i];
      a[i]=a[j];
      a[j]=tmp;
      i++;   /*从左往右*/
      j--;   /*从右忘左*/
     
    }
    for(i=0;i<n;i++)
    {
     printf("%d",a[i]);
    }
    printf("\n");
    }
    

    冒泡排序

    ![Alt text](./Image 1.png)

    #include <stdio.h>
    int main()
    {
     int a[]={1,-1,2,-2,3,-3,4,-4,5,-5};
     int n=sizeof(a)/sizeof(a[0]);
     int i=0;
     int j=0;
     int tmp;
    printf("排序前");
     for(i=0;i<n;i++)
    {
     printf("%d",a[i]);
    }
     printf("\n");
    
     for(i=0;i<n-1;i++)
     {
     for(j=0;j<n-1-i;j++)
     {
     if(a[j]>a[j+1])
     {
      tmp=a[j];
      a[j]=a[j+1];
      a[j+1]=tmp;
    }
    }
    }
    printf("排序后");
    for(i=1;i<n;i++)
    {
     printf("排序后:%d",a[i]);
    }
    printf("\n");
    
    }
    

    多维数组

    #include<stdio.h>
    int main()
    {
     /*
     1、有多少[]就有多少维
     2、内存中没有多维,都只有一维,多维数组是特殊的一维数组
     3、定义了一个一维数组a[3],这个一位数组有3个元素,每个元素int[4]
     4、a[0],a[1],a[2]就是第0,1,2,元素的数组名
     5、二维数组用户可以理解为m行n列
    */
    int a[3][4];
    int i=0;
    int j=0;
    int num=0;
    for(i=0;i<3;i++)
    {
     for(j=0;j<4;j++)
    {
     a[i][j]=num;
     num++;
    }
    }
     for(i=0;i<3;i++)
    {
     for(j=0;j<4;j++)
     {
      printf("%d ,",a[i][j]);
     }
    printf("\n");
    }
    
    }
    

    二维数组数组名

    #include<stdio.h>
    int main()
    {
     int a[5][10];
    //1.数组名是常量,不能修改
    //2.sizeof(数组名),测数组的总大小:5*int[10]=5*4*10=200
    printf("sizeof(a)=%lu\n",sizeof(a));
    //3.sizeof(a[0]),测的是第0个元素的大小:int [10]=4*10=40
    printf("sizeof(a[0])=%lu\n",sizeof(a[0]));
    
    //求行数(元素个数):总大小/每个元素的大小
    int n=sizeof(a)/sizeof(a[0]);
    printf("n1=%d\n");
    //求列数
    n=sizeof(a[0])/sizeof(int);
    printf("n2=%d\n",n);
    //行*列
    n=sizeof(a)/sizeof(a[0])*sizeof(a[0])/sizeof(int)=sizeof(a)/sizeof(int);
     printf("n3=%d\n",n);
    
    }
    

    二维数组平均分

    #include<stdio.h>
    int main()
    {
     int a[5][3]=
    {
     {30,60,80,},
     {60,60,60},
      {77,88,99,},
     {88,66,77},
     {12,22,8}
    };
     int i=0;
     int j=0;
     int sum =0;
     for(i=0;i<3;i++)
     {
      sum=0;
     for(j=0;j<5;j++)
     {
       sum+=a[j][i];
     }
    }
    printf("平均分:%lf\n",sum/5.0);
    }
    

    字符数组

    #include <stdio.h>
    int main ()
    {
     /*
      1、C语言没有字符串类型,用字符数组模拟
      2、字符串一定是字符数组,字符数组不一定是字符串
      3、如果字符数组以字符'\0'('\0'等价于0)结尾,那么这个字符数组就是字符串
     */
      char a[10];
      char b[]={'a','b','c'};/*字符数组*/
      char c[10]={'a','b','c','\0'};/*字符串*/
    return 0;
    
    }
    

    字符数组初始化

    #include <stdio.h>
    int main()
    {
     char a1[]={'a','b','c'};/*字符数组*/
     printf("a1=%s\n",a1);/*乱码,因为没有结束符*/
    
    char a2[]={'a','b','c',0};/*字符串*/
     printf("a2=%s\n",a2);
    
    char a3[]={'a','b','c','\0'};
    printf("a3=%s\n",a3);
    
    char a4[]={'a','b','c','\0','h','e'};
    printf("a4=%s\n",a4);/*abc*/
    
    char a5[10]={'a','b','c'};/*前3个字符赋值为a,b,c,后面自动赋值为0*/
    printf("a5=%s\n",a5);
    
    /*常用初始化,使用字符串初始化,在字符串结尾自动加数字0*/
    char a7[10]="abc";
    printf("a7=%s\n",a7");
    
    char a8[10]="abc";
    printf("sizeof(a8)=%lu\n",sizeof(a8));/*字符串自动隐藏一个字符*/
    
    char a9[10]="\0abc";
    printf("a9=%s\n",a9);
    
    /*\0后面最好别跟数字,有可能组成一个转义字符,'012'就是'\n'*/
    char a10[10]="\012abc";
    printf("a10=%s\n",a10);
    
    }
    sizeof()测数据类型大小,不会因为结束符提前结束
    
    char a[100];
    scanf("%s",a);
    //a没有&,原因数组名是首元素地址,本来就是地址
    printf("a=%s\n",a);
    

    随机数产生

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    int main ()
    {
     /*
       先设置种子,种子设置一次即可
       如果srand()参数一样,随机数就一样
       srand(100);
       time(NULL)功能获取系统当前时间,由于时间会变,srand()也会改变
    */
     srand(        (unsigned int) time(NULL)     );
     int i=0;
     int num;
     for(i=0;i<100;i++)
     {
      num=rand();
      printf("num=%d\n",num);
     
     }
    return 0;
    }
    

    scanf_字符串输入

    ![Alt text](./Image 2.png)

    
    #include<stdio.h>
    int main()
    {
       char buf[100]={0};
       printf("请输入字符串buf:");
       scanf("%s", buf);/*不需要&,默认以空格分开*/
       printf("buf=%s\n",buf);
    
       char tmp[100]={0};
       printf("请输入字符串tmp:");
       scanf("%s", tmp);/*不需要&,默认以空格分开*/
       printf("tmp=%s\n",tmp);
    
       /*scanf()的缺陷,不做越界检查,此函数不安全*/
       char str[100]={0};
       printf("请输入字符串str:");
       scanf("%s", str);/*不需要&,默认以空格分开*/
       printf("str=%s\n",str);
    
    
    }
    

    gets

    #include <stdio.h>
    int main()
    {
      char buf[100];
      /*
      gets()从键盘读取字符串,放在指定数组
      gets()允许有空格,不做越界检查,此函数不安全
     */
      gets(buf);
      printf("buf=%s\n",buf);
       return 0}
    

    fgets

    #include<stdio.h>
    int main()
    {
      char buf[100];
     /*
     从stdin(代表标准输入,键盘),读取内容
     如果输入内容如果大于sizeof(buf)-1,只取sizeof(buf)-1,放在buf所在的数组
     会把换行符也读进去
    
    */
     
      fgets(buf,sizeof(buf), stdin);
     printf("buf=%s\n",buf);
    
     return 0; 
    }
    

    puts

    #include <stdio.h>
    int main()
    {
     char buf[]="hello";
    /*把buf内容输出到屏幕,自动在屏幕加换行,是在屏幕加,字符串本身没有变量*/
     puts(buf);
     printf("%s",buf);
    }
    

    fputs

    #include <stdio.h>
    int main()
    {
     char buf[]="hello";
    /*往stdout(代表屏幕,标准输出)输出buf内容*/
     fputs(buf,stdout);
    
    
    }
    

    strlen

    #include <stdio.h>
    #include <string.h>
    int main()
    {
     char buf[]="hello";
     /*
      strlen需要使用返回值,返回值就是字符串长度
      从首元素开始,到结束符为止的长度,结束符不算(遇到'\0'结束)
    */
     int len=strlen(buf);
     printf("len=%d\n",len);
    /*多了一个结束符\0*/
     printf("sizeof(buf)=%lu\n",sizeof(buf));
    
     char buf2="\0hello";
     len=strlen(buf2);
     printf("len2=%d\n",len);
     /*sizeof()测数据类型的长度,不会因为结束符提前结束*/
     printf("sizeof(buf2)=%lu\n",sizeof(buf2));
    
     char str[100]="mike";
     printf("strlen(str)=%lu\n",strlen(str));
     printf("sizeof(str)=%lu\n",sizeof(str));
    
     return 0;
    }
    

    字符串拷贝

    #include<stdio.h>
    #include<string.h>
    int main()
    {
     char src[100]="hello\0 mike";
     char dst[100]="aaaaaaaaaaa";
     /*功能:把src字符数组前12个字符的内容拷贝给dst所代表的数组*/
    strncpy(dst,src,sizeof(src));
     printf("dst=%s\n",dst);
    printf("dst=%s\n",dst+strlen("hello")+1);
     
    return 0;
    }
    int main02()
    {
      char src[100]="hello\0 mike";
      char dst[100];
     /*
     功能:把str字符数组前8个字符的内容拷贝给dst所代表的数组
    */
    strncpy(dst,src,8);
     printf("dst=%s\n",dst);
    printf("dst=%s\n",dst+7);
     return 0;
    }
    int main01()
    {
     char src[100]="hello mike";
     char dst[100];
     /*功能:把src字符数组的内容拷贝给dst所代表的数组
      拷贝原理,从首元素开始,遇到结束符'\0'结束
    */
     strcpy(dst,src);
     printf("dst=%s\n",dst);
     
     char src2[100]="hello\0 mike";
     char dst2[100]strcpy(dst2,src2);
     printf("dst2=%s\n",dst);
     return 0;
    }
    

    字符串比较

    #include<stdio.h>
    int main()
    {
     char s1[]="abc";
     char s2[]="abcd";
     int flag=strcmp(s1,s2);
    /*
     指定比较前3个字符
     首先比较第一个字符,只要第一个字符大于对方,就已经比对方大
     int flag=strncmp(s1,s2,3);
    */
     if(flag>0)
    {
     printf("[%s]>[%s]\n",s1,s2);
    }
    else if(flag<0)
    {
     printf("[%s]<[%s]\n",s1,s2);
    }
    else
    {
     printf("[%s]==[%s]\n",s1,s2);
    }
    }
    

    sprintf

    #include <stdio.h>
    int main()
    {
     int a=10;
     char ch='b';
     char buf[]="hello";
    /*格式化一个字符串,把这个字符串输出到屏幕*/
     printf("a=%d,ch=%c,buf=%s\n",a,ch,buf);
     /*格式化一个字符串,把这个字符输出(保存)指定的数组*/
     char dst[100];
     sprintf(dst,"a=%d,ch=%c,buf=%s\n"a,ch,buf);
     printf(@@%s@@,dst);
    }
    

    ssanf

    #include <stdio.h>
    int main()
    {
    char buf[]="1 2 3";
     int a,b,c;
    /*从buf中以指定的格式提取内容*/
     sscanf(buf,"%d %d %d",&a,&b,&c);
     printf("a=%d,b=%d,c=%d\n",a,b,c);
    
     /*提取整形最方便*/
     char str[]="a=1,b=2,c=3";
     a=0;b=0;c=0;
     sscanf(str,"a=%d,b=%d,c=%d",&a,&b,&c);
     printf("a1=%d,b1=%d,c1=%d\n",a,b,c);
    
    char str2[]="1,2,3";
    a=0;b=0;c=0;
    sscanf(str2,"a=%d,b=%d,c=%d",&a,&b,&c);
    printf("a2=%d,b2=%d,c3=%d\n",a,b,c);
    
    /*提取字符串,默认以空格分隔,可以提取*/
    char tmp[]="abc mike 250";
    char m[10],n[10];k[10];
    /*不用&,数组名就是首元素地址*/
     sscanf(tmp,"%s %s %s",m,n,k);
    printf("m=%s, n=%s, k=%s\n",m,n,k);
    
    char tmp1[]="abc,mike,250";
    char m1[10],n1[10];k1[10];
    /*不用&,数组名就是首元素地址*/
    sscanf(tmp1,"%s,%s,%s",m1,n1,k1);
    printf("m1=%s, n1=%s, k1=%s\n",m1,n1,k1);
     return 0;
    
    }
    int main01 ()
    {
     int a ,b c ;
     printf("请输入三个数");
     scanf("%d %d %d",&a,&b,&c);
     printf("a=%d,b=$d,c=%d\n",a,b,c);
     return 0;
    }
    

    字符串查询

    #include<stdio.h>
    #include <string.h>
    int main()
    {
    char buf[]="abcdefg"
    /*
      在buf中查询字符d,如果找到,返回d所在位置的地址
      如果查询失败,返回NULL
    
    */
     char *p=strchr(buf,'b');
    if(p==NULL)
    {
     printf("查询失败\n");
    }
    else
    {
    printf("p=%s\n",p);
    }
    
    }
    

    字符串切割

    #include<stdio.h>
    #include<string.h>
    int main()
    {
     char buf[]="abc,mike,250";
     char tmo[];
     strcpy(tmp,buf);
     char *p=strtok(tmp,",");
     while(p!=NULL)
    {
      printf("p=%s\n",p);
     p=strtop(NULL,",");
    }
    }
    int main01()
    {
      char buf[]="abc,mike,250";
     char tmp[];
     strcpy(tmp,buf);
     /*
      第一次调用
     第一次参数写源字符串,第二次参数写切割字符
     返回值就是切割后的字符串
     在匹配切割字符的地方,换成结束符
     使用strtok()会破坏原来字符串的结构
     如果没有切割成功,返回NULL
    */
    printf("before,buf[3]=%d\n",buf[3]);
    char *p=strtok(tmp,",");
    /*第二次调用,第一个参数需要写NULL*/
    p=strtok(NULL,",");
    printf("p2=%s\n",p);
    
    
    printf("p=%s\n",p);
     printf("buf=%s\n",buf);
     printf("buf[3]=%d\n",buf[3]);
    return 0;
    }
    
    • 无参无返回值函数

    #include <stdio.h>
    void fun ()/*等价于void fun(void)*/
    {
     /*
     无参无返回值函数的定义
     1、没有返回值,用void关键字修饰
     2、没有参数,也可以用void,或者为空
     3、第一个void代表返回值,fun代表函数名字,()内部代表参数,空就是无参,{}就是函数体
     4、同一个文件不能出现同名函数
     5、不同的函数,内部的变量是没有关系的
     函数内部,包括()内部的变量,只有在调用时分配空间,调用完毕自动释放
    */
    printf("我是无参无返回值函数的定义\n");
     int a=10;
     int b=20;
     printf("a+b=%d\n",a+b);
    }
    int main()
    {
     /*
      1、除了main函数外,其他函数只有调用了才起作用
      2、函数的调用不可能出现void关键字
      3、无参无返回值函数的调用格式:函数名字()
    */
       fun();
    return 0}
    
    • 有参无返回值

    #include <stdio.h>
    /*
    有参无返回值函数的定义
     1、定义函数的参数就做形参,形参的格式必须为:类型+变量,不能赋值
     2、函数没有调用,形参变量不会分配空间,函数调用完毕,形参变量自动释放
    */
     void fun1(int a)
    {
     printf("a=%d\n",a);
    }
    /*如果形参有多个,用逗号","隔开*/
     void fun2(int a,char ch,char buf[100])
    {
     printf("a=%d,ch=%c,buf=%s\n",a,ch,buf);
    }
    
    int main()
    {
     int a =10;
    /*
    有参无返回值函数的调用
     1、如果函数定义室友参数,调用时必须传参
     2、有参函数调用形式:函数名(匹配类型参数)
     3、匹配类型参数可以是变量,常量,表达式
     4、函数调用时传的参数,叫做实参
     5、只能把实参的值传递给形参,不能反过来,单向传递
    */
    
     fun1(10);
     int i=11;
     fun1=(i);
     fun1(1>2);
    
     /*6、函数的形参有多个,传参也用逗号","隔开*/
     fun2(10,'a',"hello");
    
    }
    
    • 无参有返回值

    #include<stdio.h>
    /*
    无参有返回值函数的定义
     1、第一个int代表函数的返回类型,函数内部通过return返回
     2、return作用终止当前的函数
     3、返回值可以是常量,变量,表达式
    */
    int fun()
    {
     return 10;   /*返回常量*/
    }
    
    int fun1()
    {
       int a=11;
      return a;   /*返回变量*/
    }
    
    int fun2()
    {
     int a=10int b=20;
     return a>b?a:b;   /*返回表达式*/
    }
    /*
    4、函数返回值只能返回一个,不能返回多个
    5、如果return的类型和函数返回类型不一致,以函数返回类型为准
    */
    int fun3()
    {
      return 9.5555;
    }
    int main()
    {
    /*
    1、如果函数有返回值,这个返回值可以不用
     2、如果使用返回值,最好要定义匹配类型的变量来接收/
    */
     fun(); 
    
    int a=fun();
    printf("a=%d\n",a);
    
     int b;
     b=fun();
     printf("b=%d\n",b);
    
     printf("tmp=%d\n",fun());
    
     printf("fun1=%d\n",fun1());
     
     printf("fun2=%d\n",fun2());
    
     printf("fun3=%d\n",fun3);
    
     return 0;
    }
    

    return 和 exit

    #include <stdio.h>
    #include <stdlib.h>
    int fun()
    {
      printf("fun\n");
     exit(250;  /*结束整个程序,结束进程*/
    }
    /*
     return主函数(main),程序结束
     return其他函数,程序不结束
    */
    int main()
    {
     while(1)
     {
    
    }
    return 0;  /*return作用:中断函数,中断main,程序就结束*/
    printf("main\n");
    }
    

    声明和定义的区别

    #include <stdio.h>
    /*
     1. 编译器很笨,在main函数调用其他函数,只会往前找函数的定义
     2. 如果找不到函数的定义,就找函数的声明,如果没有声明,c编译器会警告,c++会出错
     3. 如果没有定义,直接调用一个不存在的函数,会报错
     4. 如果定义没有放在main函数前面,那么在调用前需要声明,声明加不加extern是一样的
     5. 一个函数只能定义一次,可以声明多次
     6. 声明的形参变量名和定义的形参变量名可以不一样
     7. 可以只声明,不定义函数(无意义),此函数不能调用
    */
    /*函数的声明,告诉编译器,这个函数是有意义的,只是放在别的地方*/
     int my_strlen(char buf[]);
    /*8、声明时,形参变量名可以不写,可以只写类型,定义时,形参变量名一定要写*/
     void fun(int a,int, int);
    
     int main()
    {
      printf("len=%d\n",my_strlen("0123456789"));
     return 0;
    }
    int my_strlen(char str[])
    {
      int i=0;
     while(str[i]!='\0')
    {
     i++;
    }
    return i;
    }
    

    指针

    ![Alt text](./Image 3.png)

    ![Alt text](./Image 4.png)

    #include <stdio.h>
    int main()
    {
    /*
    1、指针也是一个变量
     2、p是一个变量,p的类型是int *
    */ 
     int *p;
    p=123;
    printf("%d\n",p);
    
    /*2、指针指向谁,就把谁的地址赋值给指针*/
    int a=10;
    p=&a;  /*p保存了a的地址*/
    /*%p打印地址,是以16进制方式来打印*/
    printf("%p, %p\n",p,&a);
    
    /*
    3、直接操作指针变量本身没有意义
    4、需要操作*p,操作指针所指向的内存
    */
    *p=100;   /**p相当于a*/
    printf("%d, %d\n",*p,a);
     return 0;
    
    }
    
    

    ![Alt text](./Image [5].png)

    #include<stdio.h>
    int main()
    {
     int a=10;
     int *p=&a;
     *p=111;
     
     int *q;
     q=p;
     *q=222;
     printf("&a=%p,p=%p,q=%p\n",&a,p,q);
     printf("a=%d,*p=%d,*q=%d\n",a,*p,*q);
     return 0;
    }
    

    野指针:这个指针变量保存了一个没有意义(非法)的地址

    ![Alt text](./Image [6].png)

    #include <stdio.h>
    int main()
    {
     int *p;
     p=0x1234;
     printf("p=%d\n",p);
    /*
      *p=100;错误
     1、只有定义后的变量,此变量的地址才是合法地址
     2、野指针就是保存没有意义地址的指针变量
     3、操作野指针变量本身不会有任何问题
     4、操作野指针所指向的内存才导致段错误
    
     p=0x1234;没有定义0x1234;
     可能有一个叫0x1234的变量,*p=100就是操作这个0x1234变量,无法操作,所以出现段错误
    
    */
     *p=100;
     
     return 0;
     
    }
    

    空指

    #include <stdio.h>
    int main()
    {
      /*
      1、空指针,就给指针变量赋值为NULL
      2、NULL就是数字0
    */
     
     int *p=NULL;
     
     int a=11;
     p=&a;
     if(p!=NULL)
    {
     *p=100;
    }
     return 0;
    }
    

    指针大小

    #include <stdio.h>
    int main()
    {
     /*
     1、32位编译器用32位大小(4字节)保存地址
     2、64位编译器用64位大小(8字节)保存地址
    */
     int a=sizeof(int *);
     int b=sizeof(int *);
    
     double *p;
     int c=sizeof(p);
     printf("a=%d,b=%d,c=%d\n",a,b,c);
     return 0;
    }
    

    多级指针

    ![Alt text](./Image [7].png)

    ![Alt text](./Image [8].png)

    [ ]不是数组专属
    #include <stdio.h>
    int main()
    {
     int a=10;
     int *p=&a;
     /*通过指针简洁操作a的内存*/
     *p=111;
     
     printf("a=%d\n",a);
     printf("*p=%d\n",*p);
    /* *p等价于*(p+0),同时等价于p[0]*/
     printf("p[0]=%d\n",p[0]);
    /* *p等价于p[0],操作的是指针所指向的内存*/
     p[0]=250;
     printf("a2=%d\n",a);
     return 0;
    }
    

    万能指针

    ![Alt text](./Image [9].png)

    #include <stdio.h>
    int main()
    {
      /*
      1、不可以定义void类型的普通变量,不能确定类型
      2、可以定义void *变量,void *指针也叫万能指针
      3、void *可以指向任何类型的变量
    */
     void *p=NULL;
     
     int a=10;
     p=&a;
     *((int *)p)=222;  /*只保存了a的首地址*/
     printf("*p=%d\n",*((int *)p));
    
    }
    

    指针步长

    #include <stdio.h>
    int main()
    {
     /*
     1、指针的加法,不是传统的加法
     2、步长由指针指向的数据类型决定
    */
     int a;
     int *p=&a;
     printf("p=%d,p+1=%d\n",p,p+1);
    
     char b;
     char *q=&b;
     printf("q=%d,q+1=%a\n",q,q+1);
    }
    

    const修饰的指针

    #include <stdio.h>
    int main()
    {
     /*
     1、指针变量
     2、指针所指向的空间
    */
     int a =10;
     int *p1=&a;
     *p1=100;
      p1=NULL;
    
     /*const 修饰* ,代表指针所指向的内存是只读的*/
     const int *p2=&a;
     /* *p2=100;不能操作*/
     p2=NULL;
     
    /*const 修饰* ,代表指针所指向的内存是只读的*/
     int const *p3=&a;
     p3=NULL;
    
     /*const 修饰指针变量,代表指针变量的值为只读*/
     int * const p4=&a;
     *p4=100;
      /* p4=NULL; 不能操作*/ 
    
     const int * const p4=&a;
    
     return 0;
    
    }
    

    指向数组首元素的指针

    ![Alt text](./Image [10].png)

    #include <stdio.h>
    int main()
    {
     int a[10]={1,2,3,4,5,6,7,8,9,10};
     
     int *p=NULL;
    /*p指针变量指向首元素*/
     p=&a;
     p=a;
      
     int i=0;
     for (i=0;i<10;i++)
     {
     printf("%d,",*(p+i));
     /*
     等价于
      printf("%d",a[i]);
      printf("%d",p[i]);
      p[i]等价于 *(p+i),操作都是指针所指向的内存
    */
    
    } 
     printf("\n");
    }
    

    通过指针加法访问指针元素

    #include <stdio.h>
    int main()
    {
     int a[10]={1,2,3,4,5,6,7,8,9,10};
    /*定义一个指针,指向首元素*/
     int *p=&a[0];
    
     int n=sizeof(a)/sizeof(*a);
     int i=0;
     for(i=0;i<n;i++)
     {
     printf("%d, ",*p);
     p++;
    }
     printf("\n")/*定义一个指针,指向尾元素*/
     int *q=&a[n-1];
     q=a+n-1;
     for(i=0;i<n;i++)
    {
     printf("%d, "*q);
     q--;
    }
    printf("\n");
    }
    
    • ####指针数组,它是数组,每个元素都是指针
    • ####数组指针,它是指针,指向数组的指针

    指针数组

    ![Alt text](./Image [11].png)

    #include <stdio.h>
    int main()
    {
     int a[3]={0,1,2};
     /*指针数组,它是数组,每个元素都是指针*/
      int *p[3];
     p[0]=&a[0];
     p[0]=a;
     
     p[1]=&a[1];
     p[2]=&a[2];
    
     int n=sizeof(p)/sizeof(p[0]);
     int i=0;
     for(i=0;i<n;i++)
     {
       p[i]=&a[i];
    }
     for(i=0;i<n;i++)
     {
     printf("%d\n",*p[i]);
    }
     return 0;
    }
    
    
    int main01()
    {
     int a =10;
     int b =20;
     int c =30;
     
     int *p1=&a;
     int *p2=&b;
     int *p3=&c;
     
     return 0;
    }
    

    值传递

    ![Alt text](./Image [14].png)

    #include <stdio.h>
    void swap(int m,int n)
    {
     int tmp;
     tmp=m;
     m=n;
     n=tmp;
     printf("m=%d,n=%d\n",m,n);
    }
    int main()
    {
      int a=11;
     int b=22;
     swap(a,b);  /*值传递,形参的修改不会影响到实参*/
     printf("a=%d,b=%d\n",a,b);
     return 0;
    }
    

    地址传递

    ![Alt text](./Image [13].png)

    #include <stdio.h>
    void swap(int *m,int *n)
    {
    int tmp;
    tmp=*m;
    *m=*n;
    *n=tmp;
    printf("m=%d,n=%d\n",m,n);
    }
    int main()
    {
      int a=11;
    int b=22;
    swap(&a,&b);  /*地址传递,变量的地址*/
    printf("a=%d,b=%d\n",a,b);
    return 0;
    }
    

    形参中的数组

    #include <stdio.h>
    
    /*
     1、形参中的数组,不是数组,他是普通指针变量
     2、形参数组:int a[100000],int a[],int *a对编译器而已,没有任何区别
     3、编译器都是当作int *处理
      4、形参中的数组和非形参数组的区别:形参的数组是指针变量,非形参就是数组
     void printf_array(int a[100000])
     void printf_array(int *a)
    */
    
    void printf_array(int a[])
    {
     int i=0;
    /*
     64位系统,sizeof(a),a是指针变量,结果为8
     sizeof(a[0])第0个元素,是int类型,结果为4
    */
     int n=sizeof(a)/sizeof(a[0]);
     printf("sizeof(a):%d\n",sizeof(a));
     printf("sizeof(a[0]):%d\n",sizeof(a[0]));
    for(i=0;i<n;i++)
    {
    printf("%d, ",a[i]);
    }
    printf("\n");
     a=NULL; /*形参中的数组,不是数组,它是普通指针变量*/
    }
    
    int printf_array2(int a[0],int n)
     {
       int i=0;
       for(i=0;i<n;i++)
       {
       printf("%d, \n",a[i]);
    }
     printf("\n");
    
    }
    
    int main()
    {
     int a[]={1,-2,3,-4,5,-6,7,-8,9};
     int i=0;
     int n=sizeof(a)/sizeof(a[0]);
     printf_array2  (a,n);
    
     printf("排序前\n");
     
     /*冒泡排序*/
     int j=0;
     int tmp;
     for(i=0;i<n-1;i++)
     {
     for(j=0;j<n-1-i;j++)
      {
      if(a[j]>a[j+1]) 
      {
         tmp=a[j];
         a[j]=a[j+1];
         a[j+1]=tmp;
    }
    }
    }
     printf("排序后\n");
      for(i=0;i<n;i++)
      {
     printf("%d, "a[i]); 
    }
     printf("\n");
     return 0;
    }
    

    返回局部变量地址

    ![Alt text](./Image [14].png)

    返回全局变量的地址

    #include <stdio.h>
    /*
     1、在{}外面定义的变量,就是全局变量,全局变量任何地方都能使用
     2、全局变量只有在整个程序结束后,才释放
    */
    int a;
    int *fun()
    {
     return &a; /*fun()调用完毕,a不释放*/
    }
    int main()
    {
     int *p=NULL;
     p=fun();
     
     *p=100;
     printf("*p=%d\n",*p);
     printf("a=%d\n",a);
    
     * ( fun() )=111;
     printf("a=%d\n",a);
    }
    

    字符串打印

    #include <stdio.h>
    int main()
    {
     char str[]="hello mike";
    /*
     1、%s,从首元素开始打印,直到结束符位置
     2、%s,操作的是指针所指向的内容
      printf("str=%s\n",str);
    */
     /*
      2、str是首元素地址,如果想打印str本身的值,%p,%x,%d,%o
    */
     printf("str=%p\n",str);
     /*
    3、*str代表第0个元素,它是char
    */
     printf("str3=%c\n",*str);
    
     int i=0;
     while( str[i]!='\0')
     {
     printf("%c",str[i]);
     i++;
    }
    printf("\n");
    }
    

    字符指针

    ![Alt text](./Image [15].png)

    #include <stdio.h>
    int main()
    {
      char str[]="hello";
     str[0]='1';
     *(str+1)='2';
     printf("str=%s\n",str);   /*  12llo;*/
     
     /*定义一个指针,指向首元素*/
     char *p=NULL;
     p=str[0];
     p=str;
     
     *p='a';
     p++;
     *p='b';
     printf("str=%s\n",str);  /* abllo*/
     printf("p=%s\n",p);   /*  bllo*/
     printf("p=%s\n",p-1);  /*abllo*/
     return 0;
    }
    

    字符串拷贝

    #include <stdio.h>
    int main()
    {
     char buf[100];
     char *p=buf;
     /*
     p指向buf的首元素
     strcpy()是给p所指向的内存拷贝内容,字符串拷贝给了buf
    */ 
     strcpy(p,"hello mike abc");
     printf("p=%s\n,buf=%s\n",p,buf);
     return 0;
    }
    
    int main01()
    {
     char p;
     /*
     错误
     1、不是给p变量拷贝内容
     2、给p所指向的内存拷贝内容
     3、p是野指针,给野指针所指向的内存拷贝内容,结果导致段错误
    */
     strcpy(p,"hello mike abc");
    }
    

    字符串拷贝函数

    #include <stdio.h>
    void my_strcpy(char *dst,char *src)
    {
      int i=0;
      while(*(src+i)!='\0')
     {
      *(dst+i)=*(str+i);
       i++;
    }
     /*结束符*/
     *(dst+i)=0;
    
    }
    int main()
    {
      char src[]="hello mike";
      char dst[100];
      
       my_strcpy(dst,src);
       printf("dst=%s\n",dst);
    }
    

    文字常量去不能修改

    ![Alt text](./Image [16].png)

    #include <stdio.h>
    int main()
    {
      /*1、字符串常量就是此字符串的首元素地址*/
      printf("s1=%p\n","hello mike");
     
      char *p1="hello mike";
      printf("p=%p\n",p1);
     
      char *p2="hello mike";
      printf("p2=%p\n",p2);
     /*2、字符串常量,文字常量区的字符串,只读,不能修改*/
      printf("*p1=%c\n",*p1);
       /*
     字符串常量,文字常量区的字符串,只读,不能修改
     *p1='a';  err
    */
    /*
     char *p3="hello ";
     p3指文字常量区,不能修改
     strcpy(p3,"abc");
    */
     main01();
    
    }
    void fun()
    {
     printf("fun s2=%p\n","hello mike");
    }
    int main01()
    {
     /*
     1、每个字符串都是一个地址,这个地址是指字符串首元素地址
     2、字符串常量放在data区,文字常量区
    */
      printf("s1=%s\n","hello mike");
      printf("s1=%p\n","hello mike");
      printf("s3=%s\n","hello mike"+1);
      printf("s4=%c\n",*("hello mike"));
       fun();
    }
    

    字符串赋值和常量

    ![Alt text](./Image [17].png)

    #include <stdio.h>
    int main()
    {
     /*
      1、p指针保存了"hello"的地址
      2、指针所指向的内存不能修改
    */
     char *p="hello";
     /*
      1、把"hello"一个一个字符放在buf数组中
      2、数组的元素可以修改
    */
     char buf[]="hello";
     return 0;
    }
    

    main函数形参使用说明

    #include<stdio.h>
    /*
     argc[]:它是数组,数组每个元素都是char*,每个元素都是字符地址
     argc:argc[]元素个数
     main()函数参数,需要用户传递
    */
    int main(int argc,char *argc[])
    {
     int i=0;
     for(i=0;i<argc;i++)
    {
     printf("test=%s\n",argc[i])
    }
      return 0;
    }
    

    查找匹配字符串出现次数

    #include <stdio.h>
    #include <string.h>
    int main()
    {
     char *p="11abcd11111122222abcd12666333abcd552652qqq";
     char i=0;
     char *tmp=NULL;
     
     while(1)
     {
      /*查找匹配字符串,如果找到,返回匹配字符串的地址,没有返回空*/
       tmp=strstr(p,"abcd");
       if(tmp==NULL)  /*没有找到*/
      {
       break;  /*跳出循环*/
    }
     else   /*找到*/
      {
        i++;   /*累加*/
      /*重新设置寻找的起点*/
       p=tmp+strlen("abcd");
    }
    }
       printf("%s出现abcd的次数为:%d\n");
      return 0;
    }
    

    两头堵模型

    #include <stdio.h>
    #include <sr>
    int main()
    {
      char *p="      123456789     ";
      char *start=p;
      char *end=p+strlen(p)-1;
    
      while(*start==' '&&start!='\0')
      {
       start++;
    }
      while(*end==' '&&end!=p)
     {
      end--;
    }
      int n=end-start+1;
      printf("n=%d\n",n);
     int buf[100]="aaaaaaaaaaa";
     buf[n]=0;  /*结束符*/
     strncpy(buf,start,n);
     printf("buf=%s\n",buf);
    }
    
    • 普通局部变量

    1. 在{}内部定义的变量就是局部变量
    2. 只有执行到定义变量的这个语句,系统才会给这个变量分配空间
    3. 当离开{},这个非static局部自动释放
    4. 局部变量的作用域在当前的{},离开{},无法使用此变量
    5. {}的普通局部变量。加不加auto关键字等价,普通局部变量也叫自动变量
    6. 不同的{}中,变量名字可以一样
    7. 如果static局部变量不初始化,它的值默认为随机数
    • static局部变量

    1. 在{}内部定义的变量就是局部变量
    2. static局部变量,是在编译阶段就已经分配空间,函数没有调用前,它就已经存在
    3. 当离开{},这个非static局部自动释放
    4. 局部变量的作用域在当前的{},离开{},无法使用此变量
    5. {}的普通局部变量。加不加auto关键字等价,普通局部变量也叫自动变量
    6. 如果static局部变量不初始化,它的值默认为0
    7. static局部变量初始化语句,只会执行一次,但是可以赋值多次
    8. static变量只能用常量初始化
    • 普通局部变量和static局部变量区别:

    1. 内存分配和释放
      a)普通局部变量只有执行到定义变量的语句才分配空间
      b)static局部变量在编译阶段(函数还没有执行),变量的空间已经分配
      c)普通局部变量离开作用域{},自动释放
      d)static局部变量只有在整个程序结束才自动释放
    2. 初始化
      a)普通局部变量不初始化,值为随机数
      b)static局部变量不初始化,值为0
      c)static局部变量初始化语句只有第一次执行时有效
      d)static局部变量只能用常量初始化
    • 普通全局变量(外部链接)

    1. 在{}外面(函数外面)定义的变量为全局变量
    2. 只有定义了全局变量,任何地方都能使用此变量
    3. 如果使用变量时,在前面找不到此全局变量的定义,需要声明才能使用
    4. 全局变量不初始化,默认赋值为0
    5. 声明只是针对全局变量,不是针对局部变量=
    6. 全局变量只能定义一次,可以声明多次
    7. 全局变量在编译阶段已经分配空间(函数没有执行前),只有在整个程序结束,
      才自动释放
    8. 分文件中不同文件,普通全局变量只能定义一次,可以声明多次
    9. 不同文件,普通全局变量只能定义一次,可以声明多次
    • 普通全局变量的定义和声明:

    1. 定义一个全局变量,建议初始化
      int a=10;
    2. -如果声明一个全局变量,建议加extern
      extern int a;
    • static全局变量(内部链接)

    a)static全局变量和普通全局变量的区别就是作用域不一样(文件作用域)
    b)extern关键字只适用于普通全局变量
    c)普通全局变量,所有文件都能使用,前提需要声明
    d)static全局变量只能本文件使用,别的文件不能使用
    c)不同文件只能出现一个普通全局变量的定义
    d)一个文件只能有一个static全局变量的定义,不同文件间的static全局变量,就算名字相同,也是没有关系的两个变量

    • 普通函数和static函数的区别

    a)所有文件只能有一次普通函数的定义
    b)一个文件可以有一个static函数的定义
    c)普通函数所有文件都能调用,前提是使用前声明
    d)static函数只能在定义所在的文件中使用

    • 普通局部变量

    #include <stdio.h>
    int main()
    {
      int a=10;
     if(1)
     {
       int a=11;
       /*就近原则*/
       printf("a=%d\n",a);   /*a=11*/
     }
      /*
      1、if()的a只能在if{}中使用
      2、离开if{},if中的啊已经释放
    */
     printf("a=%d\n",a);
    }
    int main01()
    {
     /*
      1、在{}内部定义的变量就是局部变量
      2、只有执行到定义变量的这个语句,系统才会给这个变量分配空间
      3、当离开{},这个非static局部自动释放
      4、局部变量的作用域在当前的{},离开{},无法使用此变量
      5、{}的普通局部变量。加不加auto关键字等价,普通局部变量也叫自动变量
      6、不同的{}中,变量名字可以一样
      7、如果static局部变量不初始化,它的值默认为随机数
    */
      int tmp=11;
      {
        int a=10;
        {
         a=11;  /*ok;还在作用域范围内*/
        }
      }
      /*a=11;  err; 离开作用域*/
       
      if(1)
       {
          int b=10;
       }
    
      for(int i=0;i<10;i++)
      {
       /*i只属于for语句,离开佛如就不能使用*/
       i=11;
       }
       /*
      printf("i=%d\n",i);
    */
    
    }
    

    static局部变量

    #include <stdio.h>
    void fun()
    {
     int i=0;
     i++;
     printf("fun i=%d\n",i);
    }
    void static_fun()
    {
    /*
      1、在{}内部定义的变量就是局部变量
      2、static局部变量,是在编译阶段就已经分配空间,函数没有调用前,它就已经存在
      3、当离开{},这个非static局部自动释放
      4、局部变量的作用域在当前的{},离开{},无法使用此变量
      5、{}的普通局部变量。加不加auto关键字等价,普通局部变量也叫自动变量
      6、如果static局部变量不初始化,它的值默认为0
      7、static局部变量初始化语句,只会执行一次,但是可以赋值多次
      8、static变量只能用常量初始化
    */
      static int i=0;
     i++;
     printf("static_fun i=%d\n",i);
    }
     int main()
     {
     fun();
     fun();
     fun();
      static_fun();
      static_fun();
      static_fun();
    }
    

    普通全局变量

    #include<stdio.h>
    /*
    1、在{}外面(函数外面)定义的变量为全局变量
    2、只有定义了全局变量,任何地方都能使用此变量
    3、如果使用变量时,在前面找不到此全局变量的定义,需要声明才能使用
    4、全局变量不初始化,默认赋值为0
    5、声明只是针对全局变量,不是针对局部变量
    6、全局变量只能定义一次,可以声明多次
    7、全局变量在编译阶段已经分配空间(函数没有执行前),只有在整个程序结束,
         才自动释放
    8、不同文件,普通全局变量只能定义一次,可以声明多次
    */
    void fun2()
    {
      extern int a;     /*声明时,不要赋值*/
      extern int a;
      extern int a;
    
     printf("fun2 a=%d\n",a);
    }
    
    int a=10;
    void fun()
    {
      a=11;
    }
    int main()
    {
       fun();
      printf("a=%d\n",a);
      fun2();
    
    }
    

    c语言全局变量缺陷

    #include<stdio.h>
    int a;
    int a;
    int a=0;/*定义,其他是声明*/ 
    int a;
    int a;
    
    /*有一次是定义,有三次是声明*/
    int b;
    int b;
    int b;
    int b;
    
    /*
    1、如果定义一个全局变量,没有赋值(初始化),无法确定是定义,还是声明
    2、如果定义一个全局变量,同时初始化,这个肯定是定义
    */
    
    int main()
    {
      /*
     只有声明,没有定义,无法给变量赋值
     extern int b=10;
    */
     b=10;
     printf("b=%d\n",b);
    return 0;
    }
    

    全局变量分文件

    • main.c

    #include "test.h"
    int main()
    {
    /*
    使用函数前,声明函数
    声明函数,extern可有可无
    声明可以多次
    */
     test();
     a=111;
     b=222;
     return 0;
    }
    
    • test.c

    int a=0;
    int b=0;
    void test()
    {
     a=10;
     b=20;
    }
    
    • test.h

    /*各种声明*/
    extern int a;
    extern int b;
    void test();
    

    ![Alt text](./Image [18].png)

    内存加载

    在程序没有执行前,有几个内存分区已经确定,虽然分区确定,但是没有加载内存,程序只有运行时才加载内存:
    text(代码区):只读,函数
    data:初始化的数据,全局变量,static变量,文字常量区去(只读)
    bss:没有初始化的数据,全局变量,static变量

    当运行程序,加载内存,首先根据前面确定的内存分区(text,data,bss)先加载,然后额外加载两个区
    text(代码区):只读,函数
    data:初始化的数据,全局变量,static变量,文字常量区去(只读)
    bss:没有初始化的数据,全局变量,static变量
    stack:(栈区):普通局部变量,自动管理内存,先进后出的特点
    heap: (堆区):手动申请空间,手动释放,整个程序结束,系统也会自动 回收,如果没有手动释放,程序也没有结束,这个堆区空 间不会自动释放

    ![Alt text](./Image [19].png)

    • ulimit -a : linux查看栈空间

    栈越界

    #include<stdio.h>
    int main()
    {
      /*语法上没有问题,栈区分配很大的内存,ulimit -a可以看到系统设置栈的上限是8M,越界了,导致段错误
        int a[1000000]={0};
    */
      int *p=(int *)malloc(10000000000000*sizeof(int));
       if(p==NULL)
    {
    printf("分配失败\n");
    }
    return 0;
    }
    

    内存操作函数 memset()使用

    #include <stdio.h>
    #include <string.h>
    int main()
    {
     int b[10]={0};
     /*处理一些代码,把b内部的元素改了*/
      /*b[10]={0};  err */
      int i=0;
      int n=sizeof(b)/sizeof(b[0]);
      for(i=0;i<n;i++)
       {
      b[i]=0;
    }
      memset(b,0,sizeof(b));
    
     char str[10];
     memset(str,'a',sizeof(str));
     for(i=0;i<10;i++)
     {
     printf("%c, ",str[i]);
    }
    printf("\n");
    return 0;
    
    }
    int main01()
    {
      int a;
      memset(&a,0,sizeof(a));
      printf("a=%d\n",a);
     /*中间参数虽然是整形,但是以字符处理*/
      memset(&a,97,sizeof(a));
      printf("a1=%c\n",a);
    
     int b[10];
     memset(b,0,sizeof(b));
     memset(b,0,10 * sizeof(int));
     return 0;
    }
    

    memcpy

    #include <stdio.h>
    #include <string.h>
    int main()
    {
      char p[]="hello\0mike"; /*以字符串初始化,自动在默认隐藏一个结束符'\0';*/
      char buf[100]; 
      printf("sizeof(p)=%lu\n",sizeof(p));
      strncpy(buf,p,sizeof(p));
      printf("buf1=%s\n",buf);
      printf("buf2=%s\n",buf+strlen("hello")+1);
    
      memset(buf,0,sizeof(buf));
      memcpy(buf,p,sizeof(p));
      printf("buf3=%s\n",buf);
      printf("buf4=%s\n",buf+strlen("hello")+1);
      return 0;
    }
    

    内存重叠

    ![Alt text](./Image [20].png)

    #include <stdio.h>
    #include <string.h>
    int main()
    {
      int a[10]={1,2,3,4,5,6,7,8,9,10};
      int b[10];
      
      /*第三个参数是指拷贝内存的总大小*/
      memcpy(b,a,10 * sizeof(int));
     memcpy(b,a,sizeof(a));
     /*使用memcpy()最好别出现内存重叠*/
    /*如果出现内存重叠,最好使用memmove*/
     /*memcpy(&a[2],a,sizeof(int));   err*/
      memmove(&a[2],a,5*sizeof(int));
    }
    

    比较memcmp

    #include <stdio.h>
    #include <string.h>
    int main()
    {
     int a[10]={1,2,3,4,5,6,7,8,9,10};
     int b[10]={10,2,3,4,5,6,7,8,9,0};
     if(flag < 0)
    {
     printf("a<b\n");
    }
     else if(flag>0)
     {
     printf("a>b\n");
    }
    else
    {
     printf("a==b\n");
    }
    }
    ```## 标题
    
    你好! 这是你第一次使用 **Markdown编辑器** 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
    
    ## 新的改变
    
    我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
    
     1. **全新的界面设计** ,将会带来全新的写作体验;
     2. 在创作中心设置你喜爱的代码高亮样式,Markdown **将代码片显示选择的高亮样式** 进行展示;
     3. 增加了 **图片拖拽** 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
     4. 全新的 **KaTeX数学公式** 语法;
     5. 增加了支持**甘特图的mermaid语法[^1]** 功能;
     6. 增加了 **多屏幕编辑** Markdown文章功能;
     7. 增加了 **焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置** 等功能,功能按钮位于编辑区域与预览区域中间;
     8. 增加了 **检查列表** 功能。
     [^1]: [mermaid语法说明](https://mermaidjs.github.io/)
    
    ## 功能快捷键
    
    撤销:<kbd>Ctrl/Command</kbd> + <kbd>Z</kbd>
    重做:<kbd>Ctrl/Command</kbd> + <kbd>Y</kbd>
    加粗:<kbd>Ctrl/Command</kbd> + <kbd>B</kbd>
    斜体:<kbd>Ctrl/Command</kbd> + <kbd>I</kbd>
    标题:<kbd>Ctrl/Command</kbd> + <kbd>Shift</kbd> + <kbd>H</kbd>
    无序列表:<kbd>Ctrl/Command</kbd> + <kbd>Shift</kbd> + <kbd>U</kbd>
    有序列表:<kbd>Ctrl/Command</kbd> + <kbd>Shift</kbd> + <kbd>O</kbd>
    检查列表:<kbd>Ctrl/Command</kbd> + <kbd>Shift</kbd> + <kbd>C</kbd>
    插入代码:<kbd>Ctrl/Command</kbd> + <kbd>Shift</kbd> + <kbd>K</kbd>
    插入链接:<kbd>Ctrl/Command</kbd> + <kbd>Shift</kbd> + <kbd>L</kbd>
    插入图片:<kbd>Ctrl/Command</kbd> + <kbd>Shift</kbd> + <kbd>G</kbd>
    
    
    ## 合理的创建标题,有助于目录的生成
    
    直接输入1<kbd>#</kbd>,并按下<kbd>space</kbd>后,将生成1级标题。
    输入2<kbd>#</kbd>,并按下<kbd>space</kbd>后,将生成2级标题。
    以此类推,我们支持6级标题。有助于使用`TOC`语法后生成一个完美的目录。
    
    
    
    ## 如何改变文本的样式
    
    *强调文本* _强调文本_
    
    **加粗文本** __加粗文本__
    
    ==标记文本==
    
    ~~删除文本~~
    
    > 引用文本
    
    H~2~O is是液体。
    
    2^10^ 运算结果是 1024.
    
    
    
    ## 插入链接与图片
    
    链接: [link](https://mp.csdn.net).
    
    图片: ![Alt](https://avatar.csdn.net/7/7/B/1_ralf_hx163com.jpg)
    
    带尺寸的图片: ![Alt](https://avatar.csdn.net/7/7/B/1_ralf_hx163com.jpg =30x30)
    
    居中的图片: ![Alt](https://avatar.csdn.net/7/7/B/1_ralf_hx163com.jpg#pic_center)
    
    居中并且带尺寸的图片: ![Alt](https://avatar.csdn.net/7/7/B/1_ralf_hx163com.jpg#pic_center =30x30)
    
    当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。
    
    
    ## 如何插入一段漂亮的代码片
    
    去[博客设置](https://mp.csdn.net/configure)页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 `代码片`.
    ```javascript
    // An highlighted block
    var foo = 'bar';
    

    生成一个适合你的列表

    • 项目
      • 项目
        • 项目
    1. 项目1
    2. 项目2
    3. 项目3
    • 计划任务
    • 完成任务

    创建一个表格

    一个简单的表格是这么创建的:

    项目 Value
    电脑 $1600
    手机 $12
    导管 $1

    设定内容居中、居左、居右

    使用:---------:居中
    使用:----------居左
    使用----------:居右

    第一列 第二列 第三列
    第一列文本居中 第二列文本居右 第三列文本居左

    SmartyPants

    SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:

    TYPE ASCII HTML
    Single backticks 'Isn't this fun?' ‘Isn’t this fun?’
    Quotes "Isn't this fun?" “Isn’t this fun?”
    Dashes -- is en-dash, --- is em-dash – is en-dash, — is em-dash

    创建一个自定义列表

    Markdown
    Text-to-HTML conversion tool
    Authors
    John
    Luke

    如何创建一个注脚

    一个具有注脚的文本。1

    注释也是必不可少的

    Markdown将文本转换为 HTML

    KaTeX数学公式

    您可以使用渲染LaTeX数学表达式 KaTeX:

    Gamma公式展示 Γ(n)=(n1)!nN\Gamma(n) = (n-1)!\quad\forall n\in\mathbb N 是通过欧拉积分

    Γ(z)=0tz1etdt&ThinSpace;. \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,.

    你可以找到更多关于的信息 LaTeX 数学表达式here.

    新的甘特图功能,丰富你的文章

    Mon 06Mon 13Mon 20已完成 进行中 计划一 计划二 现有任务Adding GANTT diagram functionality to mermaid
    • 关于 甘特图 语法,参考 这儿,

    UML 图表

    可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图::

    张三李四王五你好!李四, 最近怎么样?你最近怎么样,王五?我很好,谢谢!我很好,谢谢!李四想了很长时间,文字太长了不适合放在一行.打量着王五...很好... 王五, 你怎么样?张三李四王五

    这将产生一个流程图。:

    链接
    长方形
    圆角长方形
    菱形
    • 关于 Mermaid 语法,参考 这儿,

    FLowchart流程图

    我们依旧会支持flowchart的流程图:

    Created with Raphaël 2.2.0开始我的操作确认?结束yesno
    • 关于 Flowchart流程图 语法,参考 这儿.

    导出与导入

    导出

    如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。

    导入

    如果你想加载一篇你写过的.md文件或者.html文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
    继续你的创作。


    1. 注脚的解释 ↩︎

    展开全文
  • 10011001我想求取二进制中的每位?即比特
  • 计算机最小单位 bit(比特) 存储0或者是1 byte(字节)基本单位 1字节=8比特位 更大的单位 1KB=2^10B 1MB=2^20B 1GB=2^30B 1TB=2^40B

    计算机最小的单位 bit(比特)

    存储0或者是1

    byte(字节)基本单位

    1字节=8比特位

    更大的单位

    1KB=2^10B
    1MB=2^20B
    1GB=2^30B
    1TB=2^40B

    展开全文
  • C语言指针

    2020-04-27 02:01:59
    一切都是地址 ...学习C语言最小单位就是字节,要了解C语言,就需要了解字节。内存中字节的编号就是地址,或者可以是指针。 就可以知道,指针就代表着最小单位。熟练使用指针,就可以掌握C语言的精髓。...

    一切都是地址

    我们将内存中字节的编号称为地址(Address)或指针(Pointer)。地址从 0 开始依次增加,对于 32 位环境,程序能够使用的内存为 4GB,最小的地址为 0,最大的地址为 0XFFFFFFFF。

    学习C语言,最小的单位就是字节,要了解C语言,就需要了解字节。内存中字节的编号就是地址,或者可以是指针。

    就可以知道,指针就代表着最小的单位。熟练使用指针,就可以掌握C语言的精髓。因为指针就是C语言最小的单位,连最小的都掌握了,其他的都是由字节组合而成的。

    C语言指针变量的定义和使用

    数据在内存中的地址也称为指针,如果一个变量存储了一份数据的指针,我们就称它为指针变量
    这样的一份数据可以是数组、字符串、函数,也可以是另外的一个普通变量或指针变量。

    在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。指针变量的值就是某份数据的地址,这样的一份数据可以是数组、字符串、函数,也可以是另外的一个普通变量或指针变量。
    现在假设有一个 char 类型的变量 c,它存储了字符 ‘K’(ASCII码为十进制数 75),并占用了地址为 0X11A 的内存(地址通常用十六进制表示)。另外有一个指针变量 p,它的值为 0X11A,正好等于变量 c 的地址,这种情况我们就称 p 指向了 c,或者说 p 是指向变量 c 的指针。
    在这里插入图片描述

    这样子,就把本身可能很大的数据变成只需要一个地址就可以了。

    那么来看看怎么定义指针变量。

    datatype *name;
    

    *表示这是一个指针变量,datatype表示该指针变量所指向的数据的类型。
    例如:

    int *p1;
    

    p1 是一个指向 int 类型数据的指针变量,至于 p1 究竟指向哪一份数据,应该由赋予它的值决定。再如:

    int a = 100;
    int *p = &a;
    

    &是取地址符,p是一个指针,它需要的是一个地址,a是一个变量,&a就是a的地址。

    我们可以和普通变量一样改变指针变量的值。

    
    //定义普通变量
    float a = 99.5, b = 10.6;
    char c = '@', d = '#';
    //定义指针变量
    float *p1 = &a;
    char *p2 = &c;
    //修改指针变量的值
    p1 = &b;
    p2 = &d;
    
    • 是一个特殊符号,表明一个变量是指针变量,定义 p1、p2 时必须带 。而给 p1、p2 赋值时,因为已经知道了它是一个指针变量,就没必要多此一举再带上 ,后边可以像使用普通变量一样来使用指针变量。也就是说,
      ** * 定义指针变量时必须带
      ,给指针变量赋值时不能带

    这里有个问题,
    p1 = &b;
    p2 = &d;
    那么可不可以这样呢?
    *p1 = b;
    p2 = d;
    当然是可以的,这只是反过来了而已。
    p1是指针,那么
    p1就是指针指向的值得意思。

    来讲讲指针变量怎么取得数据。

    通过指针变量取得数据

    指针变量存储了数据的地址,通过指针变量能够获得该地址上的数据,格式为:
    *pointer;
    这里的 * 称为指针运算符,用来取得某个地址上的数据,请看下面的例子:

    #include <stdio.h>
    int main(){
    int a = 15;
    int *p = &a;
    printf("%d, %d\n", a, *p); //两种方式都可以输出a的值
    return 0;
    }
    

    运行结果:
    15, 15

    假设 a 的地址是 0X1000,p 指向 a 后,p 本身的值也会变为 0X1000,*p 表示获取地址 0X1000 上的数据,也即变量 a 的值。从运行结果看,*p 和 a 是等价的。

    CPU 读写数据必须要知道数据在内存中的地址,普通变量和指针变量都是地址的助记符,虽然通过 *p 和 a 获取到的数据一样,但它们的运行过程稍有不同:a 只需要一次运算就能够取得数据,而 *p 要经过两次运算,多了一层“间接”。
    假设变量 a、p 的地址分别为 0X1000、0XF0A0,它们的指向关系如下图所示:
    在这里插入图片描述
    程序被编译和链接后,a、p 被替换成相应的地址。使用 *p 的话,要先通过地址 0XF0A0 取得变量 p 本身的值,这个值是变量 a 的地址,然后再通过这个值取得变量 a 的数据,前后共有两次运算;而使用 a 的话,可以通过地址 0X1000 直接取得它的数据,只需要一步运算。
    使用指针是间接获取数据,使用变量名是直接获取数据,前者比后者的代价要高。

    指针除了可以获取内存上的数据,也可以修改内存上的数据

     #include <stdio.h>
    int main(){
    	int a = 15, b = 99, c = 222;
    	int *p = &a; //定义指针变量
    	*p = b; //通过指针变量修改内存上的数据
    	c = *p; //通过指针变量获取内存上的数据
    	printf("%d, %d, %d, %d\n", a, b, c, *p);
    	return 0;
    }
    
    
    

    运行结果:
    99, 99, 99, 99
    *p 代表的是 a 中的数据,它等价于 a,可以将另外的一份数据赋值给它,也可以将它赋值给另外的一个变量。

    • 在不同的场景下有不同的作用:
      在定义的时候,* 表明这是一个指针变量,以和普通变量区分开;
      使用指针变量时在前面加 * 表示获取指针指向的数据,或者说表示的是指针指向的数据本身。

    就是说定义指针变量时的和使用指针变量时的意义完全不同。
    例子

     int *p = &a;
    *p = 100;
    

    第1行代码中用来指明 p 是一个指针变量,第2行代码中用来获取指针指向的数据。
    需要注意的是,给指针变量本身赋值时不能加*。修改上面的语句:

    int *p;
    p = &a;
    *p = 100;
    

    第2行代码中的 p 前面就不能加*。
    指针变量也可以出现在普通变量能出现的任何表达式中,例如:

    int x, y, *px = &x, *py = &y;
    y = *px + 5;  //表示把x的内容加5并赋给y,*px+5相当于(*px)+5
    y = ++*px;  //px的内容加上1之后赋给y,++*px相当于++(*px)
    y = *px++;  //相当于y=(*px)++
    py = px;  //把一个指针的值赋给另一个指针
    

    【示例】通过指针交换两个变量的值。
    这个知识点经常出现在面试题里面。

     #include <stdio.h>
    int main(){
    int a = 100, b = 999, temp;
    int *pa = &a, *pb = &b;
    printf("a=%d, b=%d\n", a, b);
    /*****开始交换*****/
    temp = *pa; //将a的值先保存起来
    *pa = *pb; //将b的值交给a
    *pb = temp; //再将保存起来的a的值交给b
    /*****结束交换*****/
    printf("a=%d, b=%d\n", a, b);
    return 0;
    }
    
    

    运行结果:
    a=100, b=999
    a=999, b=100
    从运行结果可以看出,a、b 的值已经发生了交换。需要注意的是临时变量 temp,它的作用特别重要,因为执行*pa = *pb;语句后 a 的值会被 b 的值覆盖,如果不先将 a 的值保存起来以后就找不到了。

    最后来总结一下 和&,这个是指针容易犯浑地方。
    设有一个 int 类型的变量 a,pa 是指向它的指针,那么
    &a和&pa分别是什么意思呢?
    &a可以理解为(&a),&a表示取变量 a 的地址(等价于 pa),
    (&a)表示取这个地址上的数据(等价于 pa),绕来绕去,又回到了原点,&a仍然等价于 a。
    &*pa可以理解为&(*pa),*pa表示取得 pa 指向的数据(等价于 a),&(*pa)表示数据的地址(等价于 &a),所以&*pa等价于 pa。

    对于*的总结
    表示定义一个指针变量,以和普通变量区分开,例如int a = 100; int *p = &a;。

    表示获取指针指向的数据,是一种间接操作,例如int a, b, *p = &a; *p = 100; b = *p;。

    说完了定义和使用,再来说说指针如何进行运算。

    指针变量的运算

    指针变量保存的是地址,而地址本质上是一个整数,所以指针变量可以进行部分运算,例如加法、减法、比较等。

    要记住比较重要的两点是,
    1.指针每次加1的时候,他们的地址加多少是看它的指针类型的长度的。就是说指针变量加减运算的结果跟数据类型的长度有关
    int 类型是4,char类型是1,double类型是8.

    #include <stdio.h>
    int main(){
    int a = 10, *pa = &a, *paa = &a;
    double b = 99.9, *pb = &b;
    char c = '@', *pc = &c;
    //最初的值
    printf("&a=%#X, &b=%#X, &c=%#X\n", &a, &b, &c);
    printf("pa=%#X, pb=%#X, pc=%#X\n", pa, pb, pc);
    //加法运算
    pa++; pb++; pc++;
    printf("pa=%#X, pb=%#X, pc=%#X\n", pa, pb, pc);
    //减法运算
    pa -= 2; pb -= 2; pc -= 2;
    printf("pa=%#X, pb=%#X, pc=%#X\n", pa, pb, pc);
    //比较运算
    if(pa == paa){
    printf("%d\n", *paa);
    }else{
    printf("%d\n", *pa);
    }
    return 0;
    }
    

    结果是:
    &a=0X28FF44, &b=0X28FF30, &c=0X28FF2B
    pa=0X28FF44, pb=0X28FF30, pc=0X28FF2B
    pa=0X28FF48, pb=0X28FF38, pc=0X28FF2C
    pa=0X28FF40, pb=0X28FF28, pc=0X28FF2A
    2686784

    文章参考:http://c.biancheng.net/view/1990.html

    展开全文
  • C语言源程序

    2019-08-23 17:56:24
    C语言源程序的最小单位是:字符 C语言源程序的最小执行单元是:函数

    函数、语句、程序行都由字符组成

    所以:

    C语言源程序的最小单位是:字符

    C语言源程序的最小执行单元是:函数

    展开全文
  • C语言概述

    2019-01-16 16:45:00
    字符是高级语言中的最小单位,是构成语法单位的基础。 C语言中规定可以使用的合法字符的集合为C字符集 C字符集采用ASCII码字符集 C语言字符集由下列字符组成 (1)字母和数字字符。(小写字母a~z、大写字母A~Z、...
  • C语言函数

    2020-10-27 19:16:36
    一段具有某项功能的代码的集合,是C语言管理代码的最小单位。 把代码封装成一个个函数,可以方便管理、调用代码。 函数的分类: 标题标准库函数: ​ C语言标准委员会为C语言以函数的形式提供的一些基础功能,被...
  • 指令是对计算机进行程序控制的最小单位; 所有的指令的集合称为计算机的指令系统; 程序是为完成一项特定任务而用某种语言编写的一组指令序列。 70年代初,贝尔实验室正式发表了C语言。 1983年发表了C语言...
  • 弧旁数字为(其中b为单位费用函数,c为容量函数,下同); 图1 给出一种算法求解最小费用最大流问题。 下面给出该算法的C语言实现。 #include int matrix[100][100],b[100][100],b_bf[100][100],s
  • C语言复习

    2017-10-08 17:22:34
    1字节=8位 位是计算机的最小存储单位,字节是计算机最小存储单元。 进制转换:十进制转换为其他进制时,连除取余;其他进制转换为十进制,按权求和。2、数据类型 ①基本类型: 整型(短short:2字节;整型:2字节...
  • C语言计时

    2019-06-16 16:44:00
    1.time(NULL) 计时最小单位为s 2.time.h int main() { clock_t start, end; start = clock(); end = clock(); printf("%f",(float)(end-start)/CLK_TCK); } 3.windows.h 显示ms数 DWORDsta...
  • C语言 线程

    2019-04-24 20:56:17
    线程除了内存中的栈区不共享,其他的都共享(因为线程本质就是...线程:最小的执行单位,有PCB,但没有地址空间(共享进程的) 进程:最小分配资源单位,可看成是只有一个线程的进程。有PCB,有独立的地址空间 ps –Lf pid ...
  • C语言关键字速记 必考 enumcharcaseconstunsigneddodefaultdoubleelse externfloatforgotoifintlongregistershort signedstructswitchtypedefunionvoidvolatilewhilebreakreturncontinueauto C语言最小单位是函数
  • C语言计时函数

    千次阅读 2017-07-28 15:57:28
    计算机纪元时间:C语言和Unix创造并诞生于...C语言标准并没有指定time_t类型的编码方式,但大多数遵循POSIX标准系统的time_t一般是32位有符号整数实现,以秒为最小单位,从1970年1月1日开始计数,所以能表示到2038年。
  • C语言基础

    2018-11-28 16:03:24
    1、定义类型和标识符时不...3、函数是可运行的最小单位,不能在函数中定义函数,函数构成:返回类型、函数名称和形参列表。 4、凡是在函数中定义的变量,在栈中分配空间;凡是在函数外定义的变量,在数据区分配空间...
  • C语言重点

    2019-03-13 19:54:05
    位,最小的存储单位,可以存储0或者1 字节,常用的计算机存储单位,一个字节等于8位(我是你8,哈哈) 字,设计计算机时给定的自然存储单位,对于8位的微型计算机(如,最初的苹果机),一个字长只有8位。从那以后...
  • 请你计算访问所有这些点需要的最小时间(以秒为单位)。 你可以按照下面的规则在平面上移动: 每一秒沿水平或者竖直方向移动一个单位长度,或者跨过对角线(可以看作在一秒内向水平和竖直方向各移动一个单位长度)。...
  • 7-1 找最小的字符串 (15分) 本题要求编写程序,针对输入的N个字符串,输出其中最小的字符串。 输入格式: 输入第一行给出正整数N;...单位 浙大城市学院 代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB #inclu.
  • C语言基础知识

    2019-03-16 14:29:40
    bit:比特是表示信息的最小单位,是二进制数的一位包含的信息或2个选项中特别指定1个的需要信息量。只有2种状态即0和1。 byte:计量存储容量的一种计量单位,通常情况下一字节等于8 bit 常用数据类型所占bit数 ...
  • 对计算机进行程序控制的最小单位 指令系统 所有指令的集合 程序 为了完成某项特定任务使用某种语言编写的一组指令序列 机器语言 一组由0 1 组成的指令码(计算机唯一识别的语言)(1001) 汇编语言
  • C语言位操作

    2014-04-15 17:10:46
    在计算机程序中,数据的位是可以操作的最小数据单位,理论上可以用“位运算”来完成所有的运算和操作。一般的位操作是用来控制硬件的,或者做数据变换使用,但是,灵活的位操作可以有效地提高程序运行的效率。C语言...
  • C语言与数据结构

    2015-09-26 10:06:39
    简单型数据元素由一个数据项组成,所谓数据项就是数据中不可再分割的最小单位;复杂型数据元素由多个数据项组成,它通常携带着一个概念的多方面信息。 3)数据对象:是性质相同的数据元素的集合,是数据的一个子集。...
  • c语言位操作

    2013-01-25 02:06:22
    在计算机程序中,数据的位是可以操作的最小数据单位,理论上可以用“位运算”来完成所有的运算和操作。一般的位操作是用来控制硬件的,或者做数据变换使用,但是,灵活的位操作可以有效地提高程序运行的效率。C语言...
  • ====================================================...指令是对计算机进行程序控制的最小单位。所有的指令的集合称为计算机的指令系统。 程序是为完成一项特定任务而用某种语言编写的一组指令序列。============...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 582
精华内容 232
关键字:

c语言最小单位

c语言 订阅