美文网首页
第三章、c语言高级阶段

第三章、c语言高级阶段

作者: 冲浪小子 | 来源:发表于2018-02-27 17:07 被阅读0次
    Day9.指针和结构体

    指针补充

    1, 指针+1, 并不是真实的+1, 而是+4
    2, 指针类型的两个用途:
    第一个用途, 取值的时候, 会根据指针类型所占用的字节去取出对应字节的数据
    第二个用途, 用于做加法运算, 指针+1, 其实是加上指针类型所占用的长度 , 如果当前指针类型是int, 那么+1本质上是加上4个字节
    3,只要一个指针指向了数组, 那么访问数组就有3种方式:
    1. : ages[0];
    2. : p[0];
    3. : *(p + 0);
    4,指针字符串

        // 通过数组保存字符串和通过指针保存字符串的区别
        // 如果通过数组来保存字符串, 那么字符串是一个变量 str  可以修改
        // 如果通过指针来保存字符串, 那么字符串是一个常量 str2 不能修该
        // 数组保存的字符串存储在内存的栈中, 而通过指针保存的字符串存储在常量区
        // 存储在栈中的变量有一个特点, 当作用域结束系统会自动释放该变量
        // 存储在常量区中的值有一个特点, 不会被释放, 而且多个相同的值对应的地址相同
    
    // 利用指针保存字符串的应用场景
        for (int i = 0; i < 100; i++) {
            // 意味着会开辟100块存储空间来保存xmg这个字符串
            // 并且会释放100次
    //        char str5[] = "xmg";
            char *str6 = "xmg";
            printf("str5 = %s\n", str6);
        }
    /*
         保存字符串的两种方式:
         char str[] = "lnj";
         存储的位置: 栈
         特点: 相同的字符串会重复的分配存储空间
               字符串可以修改
         
         char *str = "lnj"
         存储的位置: 常量区
         特点: 相同的字符串不会重复的分配存储空间
                字符串不可以修改
         */
    

    5,指向函数的指针

    指向函数的指针的定义格式
         void (*funtionP) ();
         
         *    : 代表是一个指针
         funtionP    : 代表指针变量的名称, 区分
         (*funtionP) : 代表将来指向一个函数
         void : 代表将来指向的函数没有返回值
         ()   : 代表将来指向的函数没有参数
    
    int (*ageP)();
        ageP = getAge;
        printf("age = %i\n", ageP());
        
    //    void (*sumP)(int v1, int v2);
        void (*sumP)(int, int);
        sumP = sum;
        sumP(10, 20);
    
        int (*sumP2)(int , int);
        sumP2 = sum2;
        printf("sum = %i\n", sumP2(10, 20));
    

    结构体

    // 1.定义结构体类型
        struct Person
        {
    //        char name[20];
            char *name;
            int age;
            double height;
        };
        // 2.定义结构体变量
    //    int num;
        struct Person p;
        // 注意: 数组不能先定义再进行一次性的初始化, 所有下面的写法是错误的
    //    p.name = "lnj"; // name = {'l', 'n', 'j', '\0'};
        // 可以使用 结构体变量名称.属性的方式给结构体变量赋值
        p.name = "lnj";
        p.age = 30;
        p.height = 1.75;
    
    /*
        int nums[] = {1, 3, 5};
        
        int nums[3];
        nums[0] = 1;
        nums[1] = 3;
        nums[2] = 5;
         
        int nums[3];
        nums = {1, 3, 5}; // 错误
        
        int nums[3] = {[1] = 2};
         printf("nums[0] = %i\n", nums[0]);
        */
        
        struct Dog
        {
            char *name;
            int age;
            double height;
        };
        // 1.定义的同时初始化
        struct Dog sd = {"wc", 13, 5.0};
        
        // 2.先定义再初始化(逐个初始化)
        struct Dog sd1;
        sd1.name = "ww";
        sd1.age = 5;
        sd1.height = 10.9;
        
        // 3.先定义再初始化(一次性初始化)
        struct Dog sd2;
        // 特别注意: 结构体和数组有一点区别, 数组不能先定义再进行一次性的初始化, 而结构体可以
        // 只不过需要明确的告诉系统{}中是一个结构体
        sd2 = (struct Dog){"xq", 8, 8.8}; // 数组? 结构体?
        
        // 4.指定将数据赋值给指定的属性
        struct Dog sd3 = {.height = 1.77, .name = "ww", .age = 33};
        
        printf("name = %s, age = %i, height = %lf\n", sd3.name, sd3.age, sd3.height);
    

    枚举

        // 1.定义枚举类型
        // 定义枚举类型的规范
        // 枚举类型的取值一般以k开头 后面跟上枚举类型的名称  跟上当前取值的含义
        // 和结构体一样, 枚举类型的名称首字母大写
        enum Season
        {
            kSeasonSpring,
            kSeasonSummer,
            kSeasonAutumn,
            kSeasonWinter
        };
        
        enum Gender
        {
            kGenderMale,
            kGenderFemale
        };
        
        enum Season es;
        es = kSeasonAutumn;
        
        enum Gender eg;
        eg = kGenderFemale;
    

    局部和全局变量

    /*
     局部变量
     概念: 局部变量就是定义在函数, 代码块和函数形参列表中的变量, 我们就称之为局部变量
     作用范围: 从定义的那一行开始一直直到遇到大括号结束或者遇到return为止
     特点: 
        相同作用域范围内不能出现同名的局部变量
        不同作用域范围内出现同名的局部变量, 内部的局部变量会覆盖外部的局部变量
    注意:
        局部变量没有固定的初始化值, 如果没有对局部变量进行初始化, 那么局部变量中是一些随机的值, 所以在开发中千万不要使用未初始化的局部变量
     存储位置:
        局部变量存储在栈中, 当作用域结束系统会自动释放栈中的局部变量
     
     
     全局变量
     概念: 写在函数,代码块,形参列表外的变量, 我们就称之为全局变量
     作用范围: 从定义的那一行开始一直直到文件末尾(暂时这样认为)
     特点:
        全局变量和局部变量可以同名
        如果存在和全局变量同名的局部变量, 那么局部变量会覆盖全局变量
    注意:
        全局变量如果没有进行初始化, 那么系统默认会将全局变量初始化为0
     存储位置:
        全局变量存储在静态区中, 他会随着程序的启动而创建, 随着程序的结束而结束
    int num; // 全局变量  num = 0;
    /*
         static应用场景":
         当某个方法的调用频率非常高, 而该方法中更有些变量的值是固定不变的
         那么这个时候就可以使用static来修饰该变量, 让该变量只开辟一次存储空间
         这样可以提高程序的效率和性能
         */
        static double pi = 3.1415926; // 固定
    

     宏定义在什么时候替换
     源代码 --> 预处理 -->汇编 -->二进制 -->可执行程序
     规范:
     一般情况宏名都大写, 多个单词之间用_隔开, 并且每个单词全部大写
     有得公司又要求宏名以k开头, 多个单词之间用驼峰命名
    #define CLASS_COUNT 100
    #define kClassCount 100
    带参数
    #define PF(v1) ((v1)*(v1))
    // 提前结束宏定义的作用域
    //#undef COUNT
    

    typedef起别名

    /*
     什么是typedef, 它有什么作用
     typedef可以给一个已知的数据类型起别名 (外号)
     
     利用typedef给数据类型起别名的格式:
     
     typedef 原有的数据类型 别名(外号);
     
     注意: 
     1. typedef不仅能给系统原有的数据类型起别名, 也可以给一个自定义的数据类型起别名
     2. 利用typedef给数据类型起别名, 并不会生成一个新的数据类型, 仅仅是给原有的类型起了一个别名而已
     */
    
    int sum(int v1, int v2)
    {
        return v1 + v2;
    }
    
    int minus(int v1, int v2)
    {
        return v1 - v2;
    }
    
    // 注意: 如果是给指向函数的指针起别名, 那么指向函数的指针的指针名称就是它的别名
    // functionPotinter == int(*functionPotinter)(int , int)
    typedef int(*functionPotinter)(int , int);
    int main(int argc, const char * argv[]) {
       
        // 9如何定义变量 :   数据类型 变量名称;
    //    int (*sumP)(int , int ) = sum;
        functionPotinter sumP = sum;
        printf("sum = %i\n", sumP(10 , 20));
        
    //    int (*minusP)(int, int) = minus;
        functionPotinter minusP = minus;
        printf("minus = %i\n", minusP(20, 10));
        return 0;
    }
    
    // ----------------------------给指针起别名----------------------------
    // String == char *
    typedef char * String;
    void test4()
    {
        //    char *name = "lnj";
        // 注意: 如果给指针起别名之后, 那么以后利用别名定义变量就不用再加*了
        String name = "lnj";
        printf("name = %s\n", name);
        
        
    }
    
    // ----------------------------给枚举类型起别名----------------------------
    
    // 1.先定义枚举类型, 再给枚举类型起别名
    /*
     enum Gender
     {
     kGenderMale,
     kGenderFemale
     };
     typedef enum Gender SEX;
     */
    
    // 2.定义枚举类型的同时给枚举类型起别名
    /*
     typedef enum Gender
     {
     kGenderMale,
     kGenderFemale
     } SEX;
     */
    
    // 3.定义枚举类型的同时给枚举类型起别名, 并且省略枚举原有类型名称
    typedef enum
    {
        kGenderMale,
        kGenderFemale
    } SEX;
    
    void test3()
    {
        
        // 给枚举起别名
        //    enum Gender sex;
        SEX sex;
        sex = kGenderMale;
        /*
         定义枚举变量有3种方式
         1.先定义枚举类型, 再定义枚举变量
         2.定义枚举类型的同时定义枚举变量
         3.定义枚举类型的同时定义枚举变量, 并且省略枚举类型名称
         */
        /*
         enum Gender2
         {
         kGenderMale2,
         kGenderFemale2
         } sex2;
         sex2 = kGenderFemale2;
         
         enum
         {
         kGenderMale3,
         kGenderFemale3
         } sex3;
         sex3 = kGenderFemale3;
         */
        
    }
    // ----------------------------给结构体类型起别名----------------------------
    
    
    // 1.先定义结构体类型, 再给类型起别名
    /*
     struct Person
     {
     int age;
     double height;
     char *name;
     };
     // SPerson == struct Person
     typedef struct Person SPerson;
     */
    
    // 2.定义结构体类型的同时, 给结构体类型起别名
    /*
     typedef struct Person
     {
     int age;
     double height;
     char *name;
     } SPerson;
     */
    
    // 3.定义结构体类型的同时, 给结构体类型起别名, 并且省略掉原有类型的名称
    
     typedef struct
     {
     int age;
     double height;
     char *name;
     } SPerson;
    void test2()
    {
        /*
         // 给构造类型起别名
         struct Person
         {
         int age;
         double height;
         char *name;
         };
         */
    //    struct Person sp0;
        SPerson sp;
        SPerson sp1;
        SPerson sp2;
        SPerson sp3;
        SPerson sp4;
        /*
         结构体变量的定义方式
         1.先定义类型再定义变量
         2.定义类型的同时定义变量
         3.定义类型的同时定义变量, 并且省略类型名称
         */
    }
    
    // ----------------------------给基本数据类型起别名----------------------------
    // Integer == int
    typedef int Integer;
    typedef Integer myInt;
    // int float doulbe char
    void test1()
    {
        int num = 10;
        printf("num = %i\n", num);
        
        Integer age = 30;
        printf("age = %i\n", age);
        
        myInt score = 99;
        printf("score = %i\n", score);
    }
    
    // 一般情况下如果要给数据类型起一个名称建议用typedef, 不要用define
    
    
    最后的建议如果想了解透彻c语言还是看看代码比较好。

    相关文章

      网友评论

          本文标题:第三章、c语言高级阶段

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