C语言基础篇(一)关键字

导航:

  1. 数据类型 !!!

  2. 自定义类型 !!!!

  3. 逻辑结构

  4. 类型修饰符 !!

  5. 杂项 !!

----->x<------------->x<--------------->x<--------------->x<------------->x<-----
 
char shot int float double long signed unsigned
void struct union enum typedef if else switch
case default while do for goto break continue
auto register static extern const volatile sizeof return
      
 

    
 
 
 
 
  xx------------------------------------------------------------------------------------xx
    x          常量 和 变量 .                                                                   
    |           c语言中 常量有4种基本类型:                                             
    |               -- #define定义的符号常量                                                   
    |                   #define PI 3.14             //定义常量(数值)                                  
    |                   #define NAME "KMIST"     //定义常量(字符串)                                 
    |                                                                                           
    |               -- 字符,字符串常量 和 数值常量                                                  
    |                   cahr ch = 'K';              // 'K'    是 字符   常量                      
    |                   char name[6] = "kmist"    // "kmist"  是 字符串    常量                      
    |                   int a = 780;                 //  780      是  数值       常量                      
    |                                                                                         
    |               -- 常量变量                                                                     
    |                   const int age = 20;     // age 是 定义的整形常量, 值是20 .                    
    |                   const 将一个变量修饰成 常量, 意思是说,我不可以去写这个变量,                 
    |                       但实际上,它还是变量,可以通过指针的内存溢出,来修改它的值 .                 
    |                                                                                           
    |               -- 枚举常量                                                                     
    |                   enum weekday {MON =1, TUE, WED, THU, FRI, SAT, SUN };                       
    |                                                                                               
    |           变量 就是在内存中间中声明一段 可读 可写 的数据空间,  变量 的 内存地址 是唯一的.            
    x                                                                                    x
    xx-------------------------------------------------------------------------------------xx
 
1 数据类型 (限制 占用内存大小 的 关键字)
  -- char
    硬件最小单位:bit; 软件最小单位 char; [ char(B)=8 bit ]
    char [1 byte]= 8bit = 256 种状态.
    进制: 十进制 八进制 十六进制 二进制
    在硬件描述中 一个char _ _ _ _ _ _ _ _ 8bit 的内存 空间
    如果我这样写:
    char a = 0x1a;
    转换成2进制就是 0001 1010 这样就是对这8个空间为进行赋值.

  -- int 编译器能处理的最优处理单位.
    32位系统   一个周期能走满 32bit == 4B 就是int 的大小.
    16位系统   一个周期能读取 16bit == 2B 就是 shot (int) 的大小.
    64位系统   一个周期能读取 64bit == 8B 就是int 的大小.
    #所以, int的大小不是固定的,是根据操作系统和编译器所决定 .
                
    什么时候用int?   什么时候用char?
    如果用来 描述 数据, 就用int. a.容量大; b.能达到系统的最优处理大小.
    如果用来 描述 硬件, 一般使用char.   
 
  -- long 至少4B 大小的数据长度.
    long的长度最少是4byte.什么意思呢?意义体现在16位的操作系统中. 在16位的系统中,int的大小只有2byte,
    2b == 65353 种状态.如果超过了,就要使用 bouble 或者 long .因为long至少保证 4byte的大小.

  -- unsigned 和 signed 区别 最高字节 是 符号位 还是 普通的数据
    unsigned 无符号 一般用来采集数据
    signed   有符号    就是用来定义用于计算的数值

    二者在位移运算中体现差异.因为有符号数的第一位是符号位正0 负1.
    char a = -1 (0xff) a 在不断左移的过程中, 并不会变成0, 因为 符号位 一直在占位.
    unsigned char b = 0xff b 在不断右移过后,会变成 0x00.

  -- float 和 double 浮点运算
    浮点数 在 内存中的表现形式 跟 整数 是完全不一样的 .
    float 4byte
    double 8byte 非常浪费内存空间,但是精确.

  -- void 这是最神奇的一种数据类型.
    因为它可以转换成 任何数据类型,它更多的意义是 声明 标志,而不是 使用 标志 .
    void a; a = (int)b;
 
 
 
2 自定义数据类型
----->x<------------->x<--------------->x<--------------->x<------------->x<-----
  -- struct !!! 结构体 重点掌握,内存空间的灵魂.
    组合的概念.将不同的数据类型,组合在一起.

    struct student{     //定义
    char name[20];
    unsigned int age;
    unsigned int id;
    };
    struct student liming; //申请内存空间.
    结构体的顺序是有要求的.因为在内存空间位置不一样.

  -- union 共用体 共用同一个起始地址的组合.
    结构体的话,每一个 变量的地址 是 接在 上一个变量地址 后面的.
    共用体则是不同的变量共同享用同一个起始地址.后一个变量将前一个变量覆盖.
  -- enum
    略 . 就是一堆数字集合 ?? 反正就是不重要 .
  -- typedef
    typedef实在在工程中是必须用到的, 也是无时不刻在使用的. 那它存在的意义是什么呢? 它本身的意义又是什么呢?
    假设定义 int a = 170; 我们可以知道 a 是 int 类型的 .然后呢?
    那如果我们这样写:
      typedef int long_t;
      long_t a = 170;
    这样我们就知道 ,原来 a 指的是长度 .所以 这个关键字的用法就是帮助我们摆脱没有意义的阅读 .
    给变量带上有意义的描述, 这就是这个关键字的核心所在 .
    在大工程的代码阅读中, 我碰到了无数的变量定义, 全靠这个关键字啊, 不然谁知道你的a b c 是什么东东 .
    另外, 自定义的名称一般都是xx_t 这样你一看就知道, 这是一个 typedef. 追溯一下就会知道, 它原本的类型 .
    常见的有 uint8_t uint16_t time_t 等等...
自定义类型到这里就结束了. 没什么语法, 就是多读代码. 去适应它 .
不对, 结构体这么重要, 不多解释一下吗 ?因为结构体很重要, 所以到时候会专门在内存空间那里整理出来.
 
最后吐槽, 真的忙啊. 时间不够怎么办...
 
3 逻辑结构
----->x<------------->x<--------------->x<--------------->x<------------->x<-----
  -- 选择 if-else switch-case-default
            
  -- 循环 while do-while for
    while 其实比for重要, 使用的场景也比for要多很多. 可能刚开始学c语言, 都是用for来循环, 真心觉得这是一个坑 .
    while   常用于 抽象层次的循环 ,
    for     常用于 具体次数上的循环 .
    最后要我选,果然还是while 是比较强大的 .
            
   -- continue break goto
    真不知道这一部分可以总结什么.emm...
 
4 类型修饰符
  
            一个变量 a ,其实应该拥有两种属性. 一个是大小,我们用 int 等来描述,另一个,就是空间.
            我这个变量 拥有int 这么大的空间,但是这段空间在哪里呢? 这就是类型修饰符做的事.

            内存空间有这么一些地方:    堆   栈   寄存器 常量池 等等...

            -- auto
                默认情况 比如 int a ; char b ,其实都是auto int a ,auto char b;
                而auto是默认保存在栈空间的, 这是一段可读可写的空间 .
                (auto)int a;

            -- register
                寄存器修饰符, 将一个变量保存在寄存器中, 这样, cpu读取这个变量的时候, 速度就非常快 .
                所以我们可以将频繁使用的变量用register来描述 .
                当然, 并不是你把所有变量都register来描述之后, 速度都会变快, 因为 硬件的调度能力是有限的
                编译器会尽量地安排 寄存器来存放这些变量, 如果寄存器不够了, 那 变量还是存在在存储器中 .
                !!如果,将 a 描述成 寄存器变量的话, '&' 取地址符号是语法错误的.因为编译器已经不把a当成内存变量了.!!!
                register int a;
                    int main(){
                        register int a;
                        printf("%d",&a);    //语法错误,因为 a是register 字符.无法&.
                    }
            
            -- static
                3种数据:
                (1) 函数内部的变量
                (2) 函数外部的变量
                (3) 函数

            -- extern
                外部扩展修饰字.
 
            -- const
                常量修饰符, 多用来描述只读的变量, 比如字符串. 它的意义是告诉我们,这段数据我不会修改它.
                为什么说是, 不能修改的变量呢, 因为说是不允许修改, 但我们还是可以通过指针的内存泄漏,开获取,或者改变这个值.
                const int a = 100; a是整型常量变量, 它是一种不安全的常量,实际的属性还是可写的, 所以实际上是不可变的变量.

            -- volatile
                不优化. 这个关键字, 我们在嵌入式中, 是经常用到的. !!这个算是比较隐含的,我做如下解释:
                
                ----------------------------->
                int a = 100;
                while(a == 100);
                led_on();
                假设声明一个变量 a 的值是100; 然后其实a的值是跟键盘相关联; 当按下一个按键后, a的值就会发生改变;
                当a一直是100的时候, while就一直循环; 当按键按下后, a的值发生改变. 这样就会跳出循环, 执行led_on()这个函数.
                那么, 编译器会怎么翻译这段代码呢?
                
                ------------------------------>
                f1: ldr r0 , [a]
                f2: cmp r0 , #100
                f3: jmpeq f1
                f4: led_on()
                这是我们本意, 先将a的值赋给r0, 然后和100比较, 如果相等的话, 就跳转到f1, 直到f3不相等, 执行f4.
                但是, f2是在寄存器内操作的, 效率非常快, 相比较, f1要从内存读数据, 是很缓慢的. 而且, 在while这条语句中
                并没有对a的值发生改变, cpu想, a的值根本不可能发生改变. 既然不会发生改变, 那就没必要 从内存缓慢地读取一个数据
                所以, 如果没有使用 volatile的话, 就会变成
                    jmpeq f2;
                这样就会一直处于死循环 .
                所以, volatile 禁止优化修饰符, 常用由硬件触发的变量 .
                volatile char key; 这样cpu就会不停地从内存读取key的变化, 而不会忽略它 .

        1.5 杂项
            -- sizeof 无符号的长类型lu
                用来查看 变量 在 内存空间 的 大小 .
 
            -- return
                函数返回 .
 
posted @ 2018-10-28 23:21  kmist  阅读(472)  评论(0编辑  收藏  举报