C语言学习记录_持续更新

2024.04.16

1、*****system函数

  需要头文件#include <stdlib.h>
  作用是在一个子进程中运行shell命令

2、*****gcc编译过程:预处理,编译,汇编,链接

第一步预处理:宏定义展开,头文件展开,条件编译,删除注释。不做语法检查。(详见main.i)
第二步编译:检查语法,将预处理后的文件编译成汇编文件
第三步汇编:将汇编文件生成目标文件(二进制文件)
第四步链接:把库链接到可执行程序中去,生成可执行文件

gcc -E main.c -o main.i
gcc -S main.i -o main.s
gcc -c main.s -o main.o
gcc main.o -o main.out

3、寄存器、缓存、内存三者的关系

从远近看:cpu《--》寄存器《--》缓存《--》内存 ----硬件

4、数据类型

作用:编译器预算对象分配的内存空间大小

2024.04.17

*****变量 与 常量

const修饰的变量称为 常变量 

常量:

    是只读的固定值,在程序运行期间不会改变,不能被程序修改的量,可以是任意类型
    一般出现在表达式货赋值语句中
    分为整型常量、实型常量、字符型常量、字符串常量
    
    两种定义常量的方式:
                  ----使用 #define 宏定义:#define 常量名 值
                  ----使用const关键字:const 数据类型 常量名 = 值
    分类:
    ----字面常量:
              直接出现在代码中的数值,例如整数、浮点数、字符或字符串,不需要声明,如 42、3.14、‘A’、“Hello”。
    ----使用const关键字的常量:
              通过 const 关键字声明的具有常量特性的变量,使其值不可修改,如 const int MAX_VALUE = 100。
    ----符号常量:
              通过 #define 预处理指令定义的标识符,用于表示一个固定值,提高代码的可读性和可维护性
    ----枚举常量:
              通过 enum 关键字定义的一组常量,它们通常表示相关的命名值。              

2024.04.19

变量:

    在程序运行期间可以改变
    数据类型:可以理解为创建变量的模具: 固定大小内存的别名;
            ----基本类型----整型:short、int、long、long long(占用空间大小:short<=int<=long<long long)
                            字符型:char
                            实型(浮点型):float、double

sizeof:

    		不是函数,不需要包含任何头文件,功能是计算一个数据类型的大小,单位是字节,
            返回的占用空间大小是为这个变量开辟的大小
            返回类型是unsigned int/ unsigned long
            
            数组名只有在
                  *sizeof 运算符
                  *取址 & 运算符
                  *字符串常量初始化的数组 Str[]=“abcdef”
                  这三种情况下不会发生退化(array decay)
                  其余情况下调用数组名,都会退化成指向数组首地址的指针
                  在c语言中,数组名在函数的调用中退化成了一个指针,对函数的参数使用Sizeof,sizeof获取的结果就是指针的大小,而不是数组本身的大小
                  
            指针的sizeof
                  指针是用来记录另一个对象的地址,所以指针的内存大小就等于计算机内部地址总线的宽度。
                  对一个地址来取大小呢,如果是32位系统的话即为4,如果是64位系统的话为8,
                  所以呢,在函数中sizeof获取的是指针的长度而不是数组的长度
                  指针变量的sizeof值与指针所指的对象没有任何关系

整型:

      有符号和无符号整型取值范围:                       
                              数据类型           占用空间     取值范围
                                  short                 2 字节       -32768 到 32767 (-2^15 ~ 2^15-1)
                                  int                     4 字节       -2147483648 到 2147483647 (-2^31 ~ 2^31-1)
                                  long                  4/8 字节       -2147483648 到 2147483647 (-2^31 ~ 2^31-1)
                                  unsigned short   2 字节       0 到 65535 (0 ~ 2^16-1)
                                  unsigned int     4 字节       0 到 4294967295 (0 ~ 2^32-1)
                                  unsigned long    4 字节       0 到 4294967295 (0 ~ 2^32-1)                       

字符型:

        char:
        本质就是一个 1 字节大小的整型
        在给字符型变量赋值时,需要用一对英文半角格式的单引号(' ')把字符括起来
        字符变量实际上并不是把该字符本身放到变量的内存单元中去,而是将该字符对应的 ASCII 编码放到变量的存储单元中
        重点记住:32(空格)开始,可以从键盘上找到。
                ascii  ’0‘对应48,’A‘对应65,’a‘对应97,大小写字母相差32
                  转义字符

浮点型:

           double比float更精准,打印格式:%lf,%f
           
           float的指数部分有8bit,有符号型最高位代表正负,对应的指数范围为-128~128,所以取值范围为:
                                                              -2^128到2^128,约等于-3.4E38 — +3.4E38
                                                              
           double占用8个字节(64位系统),的指数范围是-1023到1024,其取值范围为±1.7E+308到±1.7E-308
           
           大小范围主要取决于指数所占的bit位数。精度取决于尾数位数
           
           类型          符号位  指数位   尾数    有效位数
           float          1bit    8bit    23bit    log2(23)=7.22
           double          1bit  11bit    52bit    log2(52)=15.65
           long double      1bit  15bit    64bit   log2(63)=18.96

数组:指针加法

          int a[5] = {1,2,3,4,5};
          &a[0] = &a
          &a[0]+1 = &a[1]             
          &a+1 = &a + 5*4

printf输出格式总结

              数据类型                  输出格式
              int                          %d(有符号十进制整型)
              short int                    %hd
              long                         %ld
              long long                    %lld
              
              unsigned int                 %u,%o(八进制整型),%x/%X(十六进制大小写整形),
              unsigned short               %hu
              unsigned long                %lu
              unsigned long long           %llu
              
              float                        %f
              double                       &lf,%e、%E (科学计数法表示的数,输出时用e的大小写)
              
              char                         %c,(字符型,可以把输出的数字按照ascii码相应转换为对应字符)
              char*                        %s,(字符串 ,输出字符串中的字符,直至遇到'\0')
              void*                        %p,(以十六进制形式输出指针)
              %                            %%,(输出一个百分号)

printf附加格式

              字符    含义
              l        加在d,u,x,o,前面表示长整型
              
              m        数据最小宽度,
              
              -        左对齐
              
              0        将输出的前面补0,直到占满指定列宽,不可与-搭配使用
              
              m.n      m指域宽,对应的输出项在输出设备上所占的字符数,例:3.14的域宽是4,小数点也算
                       n指精度,用于说明输出的实型数的小数位数,未指定n时,默认精度n = 6

2024.04.20

补码:

    在计算机系统中,数值一律用补码来存储
    特点:正数的原码、反码、补码相同
          **负数的补码为它的反码加1**
          ***补码符号位不动,其他位求反,最后整个数加1,得到原码
          
          例如 -15的原码为:10001111 (8+4+2+1)
                    反码为:11110000 (符号位不变,其他位取反)
                    补码为:11110001 (反码+1)

类型限制符:

      extern:声明一个变量,extern 声明的变量没有建立存储空间
      const:定义一个常量,常量的值不能修改
      Volatile:防止编译器优化代码
      register:定义寄存器变量,提高效率。register 是建议型的指令,而不是命令型的指令,如 CPU 有空闲寄存器,那么 register就生效,如果没有空闲寄存器,那么 register 无效。

2024.04.21

内存分区:

参考 内存管理
在这里插入图片描述

    运行前:
        代码区:共享的、只读的
        数据区:   
              data:已初始化的全局变量、静态变量、常量
              bss: 未初始化的全局变量、静态变量
              
    运行后:
        额外增加了下面两个
        栈区:
            属于先进后出的数据结构
            由编译器管理开辟和释放
            变量的生命周期在该函数结束后自动释放
            
        堆区:
            容量远远大于栈
            没有先进后出的数据结构
            由程序员管理开辟和管理释放:malloc,free
                 
        类型	             作用域      	生命周期	      存储位置
      auto变量(局部变量)	一对{}内  	  当前函数          	栈区
      全局变量            项目可用     整个程序运行期     	初始化在data段,未初始化在BSS段
      
      static局部变量	  一对{}内	    整个程序运行期      	初始化在data段,未初始化在BSS段
      extern变量	      整个程序	  整个程序运行期      	初始化在data段,未初始化在BSS段
      static全局变量	  当前文件	  整个程序运行期      	初始化在data段,未初始化在BSS段
      
      extern函数	      整个程序	  整个程序运行期      	代码区
      static函数	      当前文件	  整个程序运行期      	代码区
      register变量	    一对{}内  	  当前函数	          运行时存储在CPU寄存器
      字符串常量        当前文件    	整个程序运行期      	data段
  
      数据区包括:堆,栈,全局/静态存储区。
		        全局/静态存储区包括:常量区,全局区、静态区。
		        常量区包括:字符串常量区、常变量区。
		        代码区:存放程序编译后的二进制代码,不可寻址区。

typedef的使用:

              简化结构体关键字struct
              给类型起别名
              区分数据类型
              提高代码可移植性

void的使用:

            无类型是不可以创建变量的
            可以限定函数返回值
            限定函数参数列表
            void*万能指针

2024.04.22

栈区

      不要返回局部变量。局部变量只在函数内有效,调完函数后内存会被释放,没权限去操作这块内存。

堆区

      在函数内开辟堆区内存,调用函数后,内存不会释放,可以使用。
      记得手动开辟手动释放。
      如果主调函数中没有给指针分配内存,被调函数用同级指针是修饰不到主调函数中的指针的。

数据区

        放入的是静态变量,全局变量,常量
        
        static
              修饰静态变量
              只初始化一次,在编译阶段就分配内存,运行阶段直接使用属于内部链接属性,只在本文件使用
        
        extern
              extern全局变量
              c语言下,默认的全局变量前都隐藏的加了关键字extern
        
        const
              修饰常量
              const修饰的全局变量:分配在常量区,受到保护,不允许修改
                                  直接修改,间接修改,都不成功,即使语法通过,运行也会出错
                                  
              const修饰的局部变量:分配在栈区,直接修改失败,间接修改成功
                                  伪常量,不可初始化数组。
  
        字符串常量
              ANSI C 中规定修改字符串常量,结果是未定义的,每个编译器不同。
              vs中把相同的字符串常量看作同一个。
              
              字符串是内存中一段连续的char空间,以'\0'(数字0)结尾
              字符串常量是由双引号括起来的字符序列,如“hello”
              
              字符串常量 与 字符常量 的不同
              'a':字符常量,内存块为:'a'
              "a":字符串常量,内存块为:'a' '\0'
              
              占位符%s:表示输出一个字符串,遇到'\0'结束

2024.04.23

printf 和 putchar (printf详细内容见4.19笔记)

        putchar():()内可以放变量、数字、转义字符                              

scanf 和 getchar

        scanf可以一次输入多个,接收空格和换行表示结束
        getchar只接收一个字符,后面加getchar();//任意键,暂时停留界面,如果不加这个,ch2就会取走回车

2024.04.24

运算符

  优先级:1、[] () . ->
          2、单目 从右到左:- ~ ++ -- * & ! (类型) sizeof
          3、双目 从左到右:算术运算符:/ * %
          4、+ -
          5、<<  >>
          6、比较运算符:> >= < <= 
          7、== !=
          8、按位与:&
          9、按位异或:^
          10、按位或:|
          11、逻辑与:&&
          12、逻辑或:||
          13、三目 从左到右:?=
          14、赋值运算符:= /= *= %= += -= <<= >>= &= |=
          15、逗号:,

  注意:*0不能做除数
        *a++是先进行表达式计算,后进行加加;++a是先进行加加,后进行表达式计算           
        *单目运算符优先级高于双目
        *所有非0的值都是真值
        *&&同真为真,||同假为假 
        *(数据类型) 强制进行数据类型转换,不会进行四舍五入

2024.04.25

运算符

  按位取反:~
          1变0,0变1
  左移右移:<< >>
        
  
  按位与:& 
          都为1才为1
  
  按位异或:^
          两者相异为1,两者相同为0
          
          
  按位或:|
          都为0才为0
  
  打开位:a|~a
        
  关闭位:a&~a
  
  转置位: 将某位置1/0,

  
  交换两个数:
        a = a^b;
        b = a^b;
        a = a^b;      

2024.04.26

判断:

      if()
      {...
      }
      ---------------------------
      if()
      {...
      }
      else
      {...
      }
      ---------------------------
      if()
      {...
      }
      else if()
      {...
      }
      else if()
      {...
      }
      else
      {...
      }
      ---------------------------
      三目运算符:c=(a>b)?a:b
            等价于:if(a>b)
                    {c=a;
                    }
                    else
                    {c=b;
                    }
      ---------------------------
      switch(int)//int理解为表达式的结果必须是整型变量
      {
      case 1:...
            break;//没有break会从匹配上的case一直执行到default
      case 2:...
            break;
            .
            .
            .
      default:   //如果以上条件都不满足
            ...
      }
      ---------------------------

循环:

      while()
      {
      }
      ---------------------------
      do
      {
      }while();
      ---------------------------
      for(i = 0;i<=100;i++)
      {
      }
      ---------------------------
      注意:
      
      while循环是先判断条件,再执行语句
      do while是先执行语句,再判断条件
      
      for是先判断条件,再执行,再++,再判断条件
  
      嵌套循环:外层执行一次,内层执行一周
      
      死循环三种样式
      
      gcc头文件有math.h,要gcc main.c -o main.out -lm

产生随机数三步:

              导入头文件<time.h>
              添加随机数种子srand((unsigned int)time()NULL)
              获取随机数rand()

跳转

      break
          switch遇到跳出{}
          循环中遇到,跳出当前内循环,执行后面代码
          嵌套循环中遇到,跳出最近的内循环,执行后面代码
          
      continue
          循环中遇到,结束本次循环,立即执行下一次循环
          
      goto
          无条件跳转到指定位置,不建议用

2024.04.28

数组

      数组就是内存中连续的相同类型的变量空间。
      
  一维数组:
      定义:数据类型 数组名[数组元素]
      
      数组a[n] 的元素下标为0到n-1
      
      数组元素可以重新赋值,也可以参与计算。
      数组名是一个常量,不允许赋值。
      
      数组名是数组首元素地址。%p打印a和&a[0]相等。
      数组内存大小:sizeof(a)
      数组单个元素内存大小:sizeof(a[0])
      数组元素个数:sizeof(a)/sizeof(a[0])
      
      数组定义十个元素:
              a[10] = {1,2,3,4,5,6,7,8,9,10};
              a[] = {1,2,3,4,5,6,7,8,9,10};
              a[10]={1,2,3,4,5};//后面5个是0
              a[10]={0};//10个都是0
              a[10]={1};//后面9个是0
              int a[10];a[0]=1;//未定义的不能打印不能使用
              
      数组元素必须是常量或者常量表达式(这是c89标准)。
      C99标准,支持不定长数组,数组元素可以用变量。
      
      数组下标越界后打印会乱码,可能会报错。a[-1],a[10],可能会报错。
      
      必须会写:
          数组最值:假设max=a[0],依次比较有更大的就修改,遍历完找到最大。
          
          数组逆置:设置临时变量=a[0],a[0]和a[9]交换
          
          冒泡排序:
                  10个元素,第1轮比较9次,确定最大值
                  9个元素,第2轮比较8次,确定第二大值
                  8个元素,第3轮比较7次,确定第三大
                  7个元素,第4轮比较6次,确定
                  
                  2个元素,第9轮比较1次,确定最小

2024.04.30

二维数组

        定义:数据类型 数组名[行][列]
        
        无论多少维数组,在内存中都是连续的      
  
        a[3][4],第一个元素a[0][0],最后一个元素a[2][3]
        
        打印,外行内列
  
        二维数组大小:sizeof(a)
        二维数组一行大小:sizeof(a[0])
        二维数组元素大小:sizeof(a[0][0])
        二维数组行数:sizeof(a) / sizeof(a[0])
        二维数组列数:sizeof(a[0]) / sizeof(a[0][0])
        
        二维数组首地址:%p打印:a,a[0],&a[0][0]
                第二行起始地址:&a[1]
        
        a[0]=100;//错误,a[0]是一整行数据,不是具体的值
  
        初始化:
              a[2][3] = {{1,2,3},{4,5,6}};//最好这样写
              a[2][3] = {1,2,3,4,5,6};
              a[ ][3] = {1,2,3,4,5,6,7};//列必须写!,这样就是三行三列
              a[ ][3] = {0};//一行三列,相当于一维,意义不大

三维数组

        定义:数据类型 数组名[层][行][列],元素个数:层*行*列
        a[2][3][4]=                            
        {
            {
              {1,2,3,4},
              {5,6,7,8},
              {1,2,3,4}
            },
            {
              {1,2,3,4},
              {5,6,7,8},
              {1,2,3,4}                                
            }  
        };

        打印需要三层循环。
  
        三维数组大小:sizeof(a)
        三维数组一层大小:sizeof(a[0])
        三维数组一行大小:sizeof(a[0][0])
        三维数组元素大小:sizeof(a[0][0][0])
        三维数组层数:sizeof(a) / sizeof(a[0])
        三维数组行数:sizeof(a[0]) / sizeof(a[0][0])
        三维数组列数:sizeof(a[0][0]) / sizeof(a[0][0][0])
  
  ******

字符数组 和 字符串

        字符数组:定义:char a[5] = {'h','e','l','l','o'};//5个
        字符数组大小:sizeof(a) = 5
        
        字符:定义:char a = 'a';;
        字符串:定义:char *a = "hello";//6个
                      char a[] = "hello";//6个,自带‘\0’(空字符) 结尾,字符串的结束标志
                      
                      char a[] = {'h','e','l','l','o','\0'};
                      char a[6] = {'h','e','l','l','o'};//后面的0等价于‘/0’,但不等同于‘0’
  
        **字符串是字符数组的特例。字符串在c语言本质中是字符数组。**
        0和‘/0’结尾的char数组就是一个字符串。
        字符串一定是一个char类型的数组。反过来不一定。
  
  字符串拼接
  
  字符串初始化

字符串输入输出:

          scanf
              scanf("%s",a);//接收空格和换行表示结束
              scanf("%9s",a);//约束只接受9个字符
  
              scanf可以一次输入多个,接收 空格 和 换行 表示结束
              getchar只接收一个字符,后面加getchar();//任意键,暂时停留界面,如果不再加一个,下一个就会取走回车
                            
              scanf("%[^\n]", a);//通过正则表达式,接收除\n之外的内容,可以接收空格
          
          gets():
                #include <stdio.h>
                char* gets(char* s);
                
                功能:从标准输入读入字符,并保存到 s 指定的内存空间,
                      直到出现 换行符 或 读到文件结尾 为止。
                
                可以接收空格
  
              注意:由于 scanf()和 gets()无法知道字符串 s 大小,
                    必须遇到 换行 符或 读到文件结尾 为止才停止接收输入,
                    因此容易导致字符数组越界(缓冲区溢出)的情况。
                
          fgets():
                #include <stdio.h>
                char* fgets(char*s, int size, FILE*stream);

                功能:从 stream 指定的文件内读入字符,
                      保存到 s 所指定的内存空间,
                      直到出现换行字符、读到文件结尾或是已读了 size - 1 个字符为止,
                      最后会自动加上字符 '\0' 作为字符串结束。
                                    
                如果读键盘输入的字符串,stream固定为stdin
                
                可以接收空格
                
                把用户输入的回车也做为字符串的一部分
                通过 scanf 和 gets 输入一个字符串的时候,不包含结尾的“\n”
                输入 “hello”,实际存放“hello\n\0”
                
                获取字符串少于元素个数会有\n,大于等于 没有\n
                
                fgets()函数是安全的,不存在缓冲区溢出的问题。
                
          puts():
                #include <stdio.h>
                int puts(const char* s);
                
                功能:标准设备输出 s 字符串,在输出完成后自动输出一个'\n'。
                
                可以接收空格                    
      
                遇到\0停止,同printf。
                
                puts(“”);//换行操作
                printf("\n");
                
          fputs():
                #include <stdio.h>
                int fputs(const char * str, FILE * stream);

                fputs()是 puts()的文件操作版本,但 fputs()不会自动输出一个'\n'。

字符串长度计算:

          strlen():
                #include <string.h>
                size_t strlen(const char *s);
                
                功能:计算指定指定字符串 s 的长度,不包含字符串结束符‘\0’      
                
                char a[100]="hello world";
                printf("%d,%d",sizeof(a), strlen(a));//100,11
                
                char a[]="hello world";
                printf("%d,%d",sizeof(a), strlen(a));//12,11

4、*****枚举定义
  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值