Day10

指针

  • 指针与函数
#include <stdio.h>
void test();
int main()
{
    /*
     * 指向函数的指针
     *   计算机也会给函数分配存储空间,所以函数也有自己的地址,所以指针
     * 变量也可以保存函数的地址
     *
     * 数组名保存的就是数组的地址,函数名中保存的也是函数的地址
     *
     * 如何定义函数指针变量
     * 1. 将需要函数拷贝
     * 2. 在函数返回值和函数名之间加*
     * 3. 修改函数名称
     * 4. 需要将*和变量名称用括号括起来
     *
     * 注意点:
     * 如果是数组,我们可以直接将数组名称赋值给一个指针变量
     * 如果是函数,我们可以直接将函数名称赋值给一个指针变量
     */

    //定义函数指针变量
    void (*funcp)();
    //将函数的地址赋值给函数指针
//    funcp = &test;
    funcp = test; //因为函数名称保存的是地址,所以这种写法也可以



    //test();  //调用函数的第一种方式
    //(*funcp)(); //调用函数的第二种方式
    funcp();  //调用函数的第三种方式
    return 0;
}

void test(){
    printf("打印点东西");
}
  • 练习
    回调函数
#include <stdio.h>
int sum(int, int);
int minus(int, int);
int main()
{
    /*
     * 需求: 要求一个函数既可以计算两个变量的和也可以计算两个变量的差
     */
    int res = test(10, 20, minus);
    printf("%i\n", res);
    return 0;
}
/*
 * 注意点: 指向函数的指针,作为函数的形参的时候,指针变量的名称,就是形参名称
 * 如果指向函数的指针作为函数的形参,那么这个函数可以称之为回调函数
 */
int test(int a, int b, int (*funcp)(int ,int)){
    return funcp(a, b);

}

int sum(int a,int b){
    return a + b;
}

int minus(int a, int b){
    return a - b;
}

结构体

  • 基本概念
    /*
     * 结构体
     *   结构体是构造类型的一种,数组也是构造类型,数组的作用是存储一组相同
     * 类型的数据,结构体的作用是存储一组不同类型的数据
     *
     * 如何定义结构体变量
     * 1. 先定义结构体的类型
     * 2. 通过结构体的类型定义结构体的变量
     *
     * 定义结构体的类型
     * struct 结构体类型名称{
     *      数据类型 属性名称;
     *      数据类型 属性名称;
     *      .
     *      .
     * }
     *
     * 定义结构体变量
     * struct 结构体类型名称 变量名称;
     *
     * 访问结构体属性
     * 结构体变量名称.结构体属性名称;
     */
    //定义结构体的类型
    struct Person{
        char *name;
        int age;
        double height;
    };
    //定义结构体变量
    struct Person p;
    //使用结构体变量
    p.name = "niuzi";
    p.age = 18;
    p.height = 1.6;
    printf("%s\n", p.name);
    printf("%i\n", p.age);
    printf("%lf\n", p.height);
  • 结构体变量初始化
/*
     * 结构体的初始化
     * 1. 定义的同时初始化
     * 2. 先定义后初始化
     * 3. 先定义结构体变量,后再完全初始化,但是不建议这样写
     */
    
    struct Dog
    {
       char *name;
       int age;
    };
    //1. 先定义后初始化
//    struct Dog p;
//    p.name = "ww";
//    p.age = 10;
    
    //2. 定义的同时初始化
    //注意点: 定义的同时初始化,那么初始化顺序必须和结构体类型中的顺序一致
//    struct Dog p ={"ww", 10};
    struct Dog p ={.name = "ww", .age = 10}; //这种顺序可以变
  • 定义结构体变量
/*
     * 定义结构体变量的几种方式
     * 1. 先定义结构体类型,再定义结构体变量
     * 2. 定义结构体类型的同时定义结构体变量
     * 3. 定义结构体类型的同时省略结构体名称,同时定义结构体变量
     */
    //1.先定义结构体类型,再定义结构体变量
//    struct Person
//    {
//        char *name;
//        int age;
//    };
//    struct Person p;

    //2. 定义结构体类型的同时定义结构体变量
    struct Person
    {
        char *name;
        int age;
    } p2;

    p2.age = 18;
    p2.name = "ll";
    printf("%i\n", p2.age);

    //3. 定义结构体类型的同时省略结构体名称,同时定义结构体变量
    //匿名结构体,结构体类型只能使用一次
    struct
    {
        char *name;
        int age;
    } p3;
  • 结构体变量作用域
    结论; 和变量的作用域一样,在代码块中只能在该代码块中使用,外界无法访问的到

  • 结构体数组
    定义一个数组保存结构体变量

    /*
     * 结构体数组
     * 结构体类型 数组名称[元素个数];
     */
    struct Person
    {
        char *name;
        int age;
    };
    struct Person p1 = {"ww", 16};
    struct Person p2 = {"jj", 18};
    struct Person p3 = {"nn", 20};
    //结构体数组第一种方式
    struct Person ps[3] = {p1, p2, p3};
    //结构体数组第二种方式
    struct Person ps[3] = {
        {"ww", 16},
        {"jj", 18},
        {"nn", 20}    
    };
  • 结构体内存分析


    /*
     * 结构体内存分析
     */

    /*
     * 结构体在分配内存的时候,会做一个内存对齐操作
     * 会先获取所有属性中内存最大的属性的字节,然后在开辟最大属性字节的内存给第一个属性
     * 之后再分配给第二个属性,如果分配的内存存储第一个属性后,不够第二个属性存储
     * 那么会再次开辟最大属性字节的内存,再往后分配
     * 
     */
    
    struct Person
    {
        char *name;
        int score;
    };
    
    //结构体在分配内存的时候,会做一个内存对齐的操作,会按照结构体属性当中
    // 占用内存最大的那个字节属性的字节倍数来分配
    
    struct Person p;
    printf("sizeof = %i\n", sizeof(p)); //8
    //结构体变量名称没有保存结构体首属性的地址
    printf("p = %p\n", p); //00000054
    printf("&p = %p\n", &p); //0028FEB8
    printf("p.name = %p\n", &p.name); //0028FEB8
    printf("p.score = %p\n", &p.score); //0028FEBC
  • 结构体指针
/*
     * 结构体指针
     * 定义指向结构体变量的指针的套路和过去定义指向普通变量一样
     * 
     * 如果指针指向了一个结构体变量,那么访问结构体属性就有三种方式
     * 1. 结构体变量名称.属性名称
     * 2. (*结构体指针变量名称).属性名称
     * 3. 结构体指针变量->属性名称
     */

    struct Person
    {
       char *name;
       int age;
    };
    struct Person per = {"niuzi", 18};
    //定义结构体指针
    struct Person *p;
    p = &per;
    //指针两种访问属性方式
    printf("%s\n", (*p).name);
    printf("%i\n", p->age);
  • 结构体嵌套
    /*
     * 结构体嵌套
     * 可以提高代码的复用率
     */

    //1. 定义一个日期的结构体
    struct Date
    {
       int year;
       int month;
       int day;
    };
    //2. 定义一个人的结构体
    struct Person
    {
       char *name;
       int age;
       struct Date birthday;  //结构体嵌套
    };
    //结构体嵌套初始化
    struct Person per = {"ww", 18, {2008,10,23}};
    printf("%i\n", per.birthday.year); //访问嵌套属性
    printf("%i\n", per.birthday.month);
    printf("%i\n", per.birthday.day);
  • 结构体和函数
    注意点: 结构体变量之间是值传递,和普通变量一样
 /*
     * 结构体和函数
     * 结构体是构造类型,但是结构体变量之间是值传递,和普通变量一样
     *
     * 注意点: 定义结构体类型的时候不会分配存储空间,只有定义结构体变量
     * 的时候才会分配存储空间
     */

    struct Person
    {
        char *name;
    };
    struct Person p1 = {"nn"};
    struct Person p2;
    p2 = p1; //值传递
    p2.name = "haha";
    printf("p1 = %s\n", p1.name); //nn
    printf("p2 = %s\n", p2.name); //haha
#include <stdio.h>
struct Person
{
    char *name;
};
void test(struct Person per);

int main()
{
    /*
     * 结构体和函数
     * 结构体是构造类型,但是结构体变量之间是值传递,和普通变量一样
     *
     * 注意点: 定义结构体类型的时候不会分配存储空间,只有定义结构体变量
     * 的时候才会分配存储空间
     */

//    struct Person
//    {
//        char *name;
//    };
//    struct Person p1 = {"nn"};
//    struct Person p2;
//    p2 = p1; //值传递
//    p2.name = "haha";
//    printf("p1 = %s\n", p1.name); //nn
//    printf("p2 = %s\n", p2.name); //haha

    struct Person p1 = {"nn"};
    test(p1);
    printf("p1 = %s\n", p1.name);


    return 0;
}
/*
 * 在main函数中结构体是局部,外部函数无法访问所以要放到外面
 * 结构体变量是值传递,不是传递地址,所以函数内部无法改变结构体的属性
 */
void test(struct Person pe){
    pe.name = "zs";
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容