美文网首页
再温C语言小记

再温C语言小记

作者: 那个人一定不是我 | 来源:发表于2019-04-24 14:37 被阅读0次
    char* stackValue(void){
        char str[20] = {'A'};
        return str;
    }
    
    void stackChange(void){
        char str[20] = {'B'};
    }
    
    
    int main(int argc, char * argv[]) {
        
        int  result_i = 0;
        unsigned long result_ul = 0;
        
        int num_i = 0;
        
        /*- ','逗号运算符 -*/
        //赋值运算符的优先级别高于逗号运算符,逗号运算符是所有运算符中级别最低的
        result_ul = 2, 3;   //值为2
        result_ul = (2, 3); //值为3
        
        /*- 符号的贪婪操作,从左往右匹配到最多的符号,后置运算与编译器相关 -*/
        num_i = 3;
        result_ul = num_i+++num_i;
        //num_i值为3; result_ul值为7 编译器相关
        num_i = 3;
        result_ul = (++num_i) * (++num_i) * (++num_i);
        //num_i值为6; result_ul值为120 = 4*5*6
        num_i = 3;
        result_ul = (num_i++) * (num_i++) * (num_i++);
        //num_i值为6; result_ul值为60 = 3*4*5 编译器相关
        
        /*- 返回栈地址 危险操作-*/
        char* stackRet = stackValue();
        char old_c = stackRet[0]; //'A'
        stackChange();
        char change_c = stackRet[0]; //'B'
        //数据由‘A’变为‘B’,地址对应的栈空间数据被修改
        
        /* '*' 和 '[]'的优先级, 数组指针, 指针数组 */
        int * ary[10] = {}; //'[]'的优先级高,这里是数组,存在的是‘int *’
        int (*ary_p) [10] = NULL; //指针,指向储存’Int‘的数组
        
        /* 指针加一 数组变量加一 首元素加一 */
        char num_ary[5]={'A','B','C','D','E'};
        
        //&num_ary值为数组的地址,类型为'char (*) [5]',
        //加一地址为数组结束后的地址
        char* c_p = (char*)(&num_ary + 1);
        char c_1 = *(c_p - 1); //值为'E'
        //指针类型强转为'char *',减一变为数组最后一个元素的地址
        
        //num_ary与&num_ary[0]值相等为第一个元素地址且类型一致为’char*‘
        char c_2 = *(num_ary + 1); //值为'B'
        char c_3 = *(&num_ary[0] + 1); //值为'B'
        
        /* 数组初始化指定位置 */
        int new_ary[] = {
            ['A'] = 9,
        };
        //将创建储存66个Int的数组,由于‘A’的char值为65,new_ary[65] = 9;
    
        /* sizeof 为关键字不是函数 */
        int test[10];
        result_ul = sizeof(test);      //sizeof(int) * 100
        result_ul = sizeof(test[11]);
        result_ul = sizeof(&test);
        result_ul = sizeof(&test[11]);
        //sizeof在编译阶段进行处理获取值,运行阶段是不会执行‘test[11]’越界访问
        
        /* const 修饰,去掉类型观看*/
        int const * con_p1 = &num_i;  //修饰指针对应的内容
        int * const con_p2 = &num_i;  //修饰指针
        const int * con_p3 = &num_i;  //去掉类型‘int’观看,同con_p1;
        //*con_p1 = 7;     //编译失败
        //con_p2 = &result_i; //编译失败
        
        /* 预处理的 #define #undef */
    #define X  1
    #define Y   X*2
    #undef  X
        //result_i = Y; //编译失败:‘X’未定义
        
        /* volatile 关键字: 易失的;易变的*/
        //http://www.cnblogs.com/god-of-death/p/7852394.html
        /* register 关键字 */
        register int num_reg = 1;
        //int* num_reg_p = &num_reg; //编译错误,寄存器无法获取地址
    
        
        /* enum 内存大小 */
       /*enum变量占用的空间与编译器相关。
        C标准:“枚举型尺寸是能够容纳最大枚举子值的整数尺寸”,
        “枚举类型中枚举子的值必须要能用一个int型表述”。
        也就是说,枚举型的尺寸不能超过int型,但不必等于int型,
        只要能容纳最大枚举子就行。
        gcc也有类似选项-fshort-enums,设置后就选用节省内存的enum长度。*/
        enum Color{
            Color_a = CHAR_MAX,
            Color_b = CHAR_MIN,
        } Color;
        
        result_ul = sizeof(Color);
        result_ul = sizeof(Color_a);
        
        /* union 内存大小 */
        /*1.联合就是一个结构;
          2.它的所有成员相对于基地址的偏移量都为0;
          3.此结构空间要大到足够容纳最“宽”的成员;
          4.其对齐方式要适合于联合中所有类型的成员。 */
        union U1{
            char s[9];
            char n;
        };
        
        union U2{
            char s[9];
            int n;
        };
        
        union U3{
            char s[9];
            double n;
        };
    
        result_ul = sizeof(union U1);  //9
        result_ul = sizeof(union U2);  //12
        result_ul = sizeof(union U3);  //16
        
        
        /* struct 内存大小 */
        /*1.结构体的对齐最大单位:使用了‘pack’宏则用指定的值,
            没有指定则使用结构体成员类型的最大值
           (成员为数组取存储元素的类型大小用于判断,
            成员为结构体取它的对齐最大单元用于判断),
        
          2.成员的偏移量:如果其类型大小小于对齐最大单位,
            那么前面占用空间必须为其类型大小的整数倍;
            如果其类型大于对齐最大单位,
            那么前面占用空间必须为对齐最大单位的整数倍。
            (所以‘pack’宏的值只能是基础类型对应值:‘0,1,2,4,8,16’)*/
        struct empty_struct {
        }empty_struct;
        result_ul = sizeof(empty_struct); //0
        
    #pragma pack(2)
        typedef struct{
            char c1[3];  //0
            char*  c2;  //4
        }T_U1;
    #pragma pack(0)
    
        
    #pragma pack(4)// -> pack(1)
        typedef struct{   //默认对齐大小最大值为4(i成员类型值最大4,uu为2)
            char  c1;  //0 -> 0
            short s;   //2 -> 1
            char  c2;  //4 -> 3
            int   i;   //8 -> 4
            char cc[20]; //12 -> 8
            T_U1 uu;  //32 -> 28
        }T_Struct;
    #pragma pack()
    
        
        T_Struct one;
        
        result_ul = sizeof(one); //44 -> 40
        
        unsigned int start_addr = (unsigned int)(void*)&one;
        result_ul = (unsigned int)(void*)&one.c1 - start_addr;
        result_ul = (unsigned int)(void*)&one.s  - start_addr;
        result_ul = (unsigned int)(void*)&one.c2  - start_addr;
        result_ul = (unsigned int)(void*)&one.i  - start_addr;
        result_ul = (unsigned int)(void*)&one.uu  - start_addr;
    
    }
    
    
    

    Demo覆盖的内容:

    1. 返回栈地址
    2. ‘,’号运算符
    3. struct大小 设置对齐大小 空结构图
    4. enum大小 空 有值
    5. 符号的贪婪操作
    6. ‘*’‘[]’的优先级 数组指针 指正数组
    7. 指针加一 数组变量加一 首元素加一
    8. 预处理的 define undefine
    9. volatile 关键字
    10. 数组初始化指定位置
    11. sizeof 关键字不是函数
    12. const 修饰
    13. union 大小

    看下面的Refs比上面的好看多了^_^
    Refs:
    《C语言深度剖析》

    相关文章

      网友评论

          本文标题:再温C语言小记

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