打印
[应用相关]

STM32 之C语言零碎

[复制链接]
1241|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hanzhen654|  楼主 | 2018-7-4 20:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1.结构体

结构体变量定义如下:
structbook {
charname[30];
charauthor[20];
};
structbook a[2]= { { "Nature","Lina"},{ "Animals","Nick"} };


沙发
hanzhen654|  楼主 | 2018-7-4 20:35 | 只看该作者
以上代码定义了一个名为book的结构体,然后a作为带有这个结构体的变量的一个内含两本书的列表(结构体数组)。也可以定义为如下:
struct book {
char name[30];
char author[20];
} a[2] = { { "Nature","Lina" },{ "Animals","Nick" } };
所完成的功能是完全一样的。第二种方法用得更多因为写法更简练。

使用特权

评论回复
板凳
hanzhen654|  楼主 | 2018-7-4 20:35 | 只看该作者
在main函数里print出来,完整代码如下:
#include<stdio.h>
int main() {
struct book {
char name[30];
char author[20];
}a[2] = { {"Nature","Lina" },{ "Animals","Nick" } };

int i;
for (i = 0; i < 2; i++) {
printf("book name: %s author: %s\n", a[i].name, a[i].author);
};
}
运行后的输出值为:
book name: Nature    author: Lina
book name: Animals    author: Nick

使用特权

评论回复
地板
hanzhen654|  楼主 | 2018-7-4 20:38 | 只看该作者
定义一个指向结构体(book)变量的指针函数p:struct book *p
现在就可以用结构体指针完成上述同样的功能了(结构体定义在main函数里外均可):
#include<stdio.h>
struct book {
char name[30];
char author[20];
}a[2] = { {"Nature","Lina" },{ "Animals","Nick" } };
int main() {
struct book*p;
for (p = a; p < a+2; p++) {
printf("book name: %s author: %s\n", p->name, p->author);
};
}
输出值和之前的程序一样。 在C语言中,为了方便和直观,往往(*p).number改写为p->number。两种写法都是可以的。

使用特权

评论回复
5
hanzhen654|  楼主 | 2018-7-4 20:38 | 只看该作者
以下例子为使用&地址符号给结构体指针赋值:
#include<stdio.h>
struct book {
char name[30];
char author[20];
};
int main() {
struct book*p;
struct book a[2] = { { "Nature","Lina" },{ "Animals","Nick" } };
p = &a[0];
printf("book name: %s author: %s\n", p->name, p->author);
}

输出结果为存入的a[0]的信息:
book name: Nature    author: Lina

使用特权

评论回复
6
hanzhen654|  楼主 | 2018-7-4 20:39 | 只看该作者
另外在许多大型软件的开发中,经常会定义结构体变量为宏变量以简化结构体的引用。例如:typedef struct book{...}BOOK, 引用的时候就直接定义BOOK a。简而言之,就是把struct book替换为BOOK。
#include<stdio.h>
typedef struct book {
char name[30];
char author[20];
}BOOK;
int main() {
BOOK*p;
BOOK a[2] = { { "Nature","Lina" },{ "Animals","Nick" } };
p = &a[0];
printf("book name: %s author: %s\n", p->name, p->author);
}
运行效果是一样的。

使用特权

评论回复
7
hanzhen654|  楼主 | 2018-7-4 20:40 | 只看该作者
2.结构体的嵌套
结构体定义中,结构体的成员又是另外一个结构体的变量
    注意:
        1)结构体定义中可以嵌套其他结构体类型的变量,不可以嵌套自己这个类型的变量
        2)可以嵌套自己类型的指针

使用特权

评论回复
8
hanzhen654|  楼主 | 2018-7-4 20:40 | 只看该作者
void demo(){
    //定义一个Date的结构体
    struct Time{
        int hour;
        int min;
        int sec;
    };
    struct Date{
        int year;
        int month;
        int day;
        struct Time time;
    };
    //定义一个学生的结构体
    struct Student{
        char *name;
        int age;
        float score;
        struct Date birthday;
        //struct Student stu;  //错误的
        //struct Student *stu; //这是正确的
    };

使用特权

评论回复
9
hanzhen654|  楼主 | 2018-7-4 20:41 | 只看该作者
本帖最后由 hanzhen654 于 2018-7-4 20:43 编辑

嵌套的结构体进行初始化
struct Student stu1 = {"huguozhang胡",19,88.5f,{1986,2,18,{10,50,12}}};

使用特权

评论回复
10
hanzhen654|  楼主 | 2018-7-4 20:43 | 只看该作者
嵌套的结构体访问
printf("姓名:%s,年龄:%d(生日:%d-%02d-%02d),成绩:%.2f\n",stu1.name,stu1.age,stu1.birthday.year,stu1.birthday.month,stu1.birthday.day,stu1.score);
printf("姓名:%s,年龄:%d(生日:%d-%02d-%02d %02d:%02d:%02d),成绩:%.2f\n",stu1.name,stu1.age,stu1.birthday.year,stu1.birthday.month,stu1.birthday.day,stu1.birthday.time.hour,stu1.birthday.time.min,stu1.birthday.time.sec, stu1.score);

使用特权

评论回复
11
hanzhen654|  楼主 | 2018-7-4 21:16 | 只看该作者
结构体嵌套自身的指针
    struct Person{
char *name;
     int age;
    //嵌套自己类型的指针
    struct Person *child;
    };
    struct Person kim = {"kim",8,NULL};
    struct Person p1 = {"林志颖",35,&kim};
    //结构体嵌套自身指针的,访问
    printf("%s的儿子是:%s,儿子的年龄:%d\n",p1.name,(*p1.child).name,(*p1.child).age);
printf("%s的儿子是:%s,儿子的年龄:%d\n",p1.name,p1.child->name,p1.child->age);

使用特权

评论回复
12
hanzhen654|  楼主 | 2018-7-4 21:17 | 只看该作者
3.回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

使用特权

评论回复
13
hanzhen654|  楼主 | 2018-7-4 21:17 | 只看该作者
#include <stdio.h>
void print();
int main(void)
{
        void (*fuc)();
        fuc = print ;
        fuc();        
}
void print()
{
        printf("hello world!\n");
}
从这个例子可以看到,我们首先定义了一个函数指针fuc ,这个函数指针的返回值为void型,然后我们给函数指针赋值,赋值为print,也就是print函数的首地址,此时fuc获得了print的地址,fuc的地址等于print的地址,所以最终调用fuc();也就相当于调用了print();

使用特权

评论回复
14
hanzhen654|  楼主 | 2018-7-4 21:18 | 只看该作者
那 么我写的这个例子明显和百度解释的不符合啊?定义是如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数,确实,有所不同,但道理是一样的,我们接下来再来看一个例子。
#include <stdio.h>
int add_ret() ;
int add(int a , int b , int (*add_value)())
{
return (*add_value)(a,b);
}
int main(void)
{
        int sum = add(3,4,add_ret);
        printf("sum:%d\n",sum);
        return 0 ;
}
int add_ret(int a , int b)
{
        return a+b ;
}

使用特权

评论回复
15
hanzhen654|  楼主 | 2018-7-4 21:36 | 只看该作者
从这个例子里,我们看到:
这样子不就符合我们的定义了嘛?我们把函数的指针(地址),这里也就是add_ret,作为参数int add(int a , int b , int (*add_value)()) , 这里的参数就是int(*add_value)() , 这个名字可以随便取,但是要符合C语言的命名规范。当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。我们看到add函数内部,return (*add_value)(a,b) ; 这个(*add_value)(a,b)相当于对指针进行了简引用,我们在main函数中,传入具体要实现功能的函数,add_ret,这个函数很简单,就是实现两数相加并返回,这里刚刚好,简引用,相当于取出指针返回地址里的值,这个值就是return a+b,也就是我们传入a和b两数相加的结果。
那么,回调函数究竟有什么作用呢?

使用特权

评论回复
16
hanzhen654|  楼主 | 2018-7-4 21:37 | 只看该作者
说到这里,就有了用户和开发者之间的概念,假设,用户是实现add_ret这个函数,而开发者是实现add这个函数,现在的需求是,用户将add_ret这个函数以参数的形式传入开发者实现的add函数,add函数就会返回一个数字给用户,开发者没必要告诉用户他实现了什么东西,用户也并不知道开发者是怎么实现的,用户只需要传入自己写的函数,便可以得到开发者实现的函数的返回值,开发者可以将内容封装起来,将头文件以及库文件提供给用户。

使用特权

评论回复
17
hanzhen654|  楼主 | 2018-7-4 21:37 | 只看该作者
接下来,我们用Linux来演示下这个结果,我们在目录下创建三个文件main.c,vendor.c,vendor.h
main.c是用户开发的。
vendor.c和vendor.h是开发者实现的。
在main.c中,代码如下:
#include <stdio.h>
#include "vendor.h"

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

int main(void)
{
    int sum = add(3,4,add_ret);
    printf("sum:%d\n",sum);
    return 0 ;
}


vendor.c,代码如下:
#include "vendor.h"
int add(int a , int b , int (*add_value)())
{
        return (*add_value)(a,b);
}


vendor.h,代码如下:
#ifndef __VENDOR_H
#define __VENDOR_H

int add(int a , int b , int (*add_value)());

#endif

使用特权

评论回复
18
hanzhen654|  楼主 | 2018-7-4 21:37 | 只看该作者
接下来,我们制作一个动态链接库,最终开发者把vendor.c的内容封起来,把vendor.h提供给用户使用。
#include <stdio.h>
#include "vendor.h"

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

int main(void)
{
    int sum = add(3,4,add_ret);
    printf("sum:%d\n",sum);
    return 0 ;
}

使用特权

评论回复
19
stm32jy| | 2018-7-4 21:43 | 只看该作者
总结的不错,我感觉自己C还是没入门。

使用特权

评论回复
20
stm32jy| | 2018-7-4 21:44 | 只看该作者
STM32里面的底层代码还是没搞懂,好多看不懂。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

73

主题

1766

帖子

2

粉丝