TongxinV/oneBook

正确使用指针(指针作为输出型参数)与结构体指针作为函数参数

TongxinV opened this issue · 0 comments

如何正确使用指针(指针作为输出型参数)与结构体指针作为函数参数

通俗的讲,指针作为某一函数的实参,在函数内部发生改变后,外部的值也能跟着发生变化

以下内容是小项目开发随笔:(与标题相关内容在错误3)

错误1

built-in.o: In function `main':
/root/winshare/ImagePlayer/main.c:17: undefined reference to `fb_open'

但是明明有定义啊?不是这个原因,而是文件没添加到工程中来

Makefile:

#添加顶层目录下的子文件夹(注意目录名后面加一个/)
obj-y += display/

然后子文件夹下添加相应规则
(子)Makefile

obj-y += framebuffer.o

错误2:

...

###错误3

编译通过,但执行发生段错误,指针出错。通过这一错误进一步加深了对指针的使用

类比外部的int a作为函数形参并能够传出来,要用指针形式

外部的指针作为函数形参并能够传出来,要使用指针的指针作为形参类型

如下案例:

<textarea cols="80" rows="5" name="code" class="javascript"> 程序1: void myMalloc(char *s) //在函数中分配内存,再返回 { s=(char *) malloc(100); } void main() { char *p=NULL; myMalloc(p); //这里的p实际还是NULL,p的值没有改变 if(p) free(p); } 程序2: void myMalloc(char **s) //指针的指针,双重指针类型 { *s=(char *) malloc(100); } void main() { char *p=NULL; myMalloc(&p); //这里的p可以得到正确的值 if(p) free(p); } </textarea>

###附.重要

实际开发中,更喜欢利用结构体指针。因为如果不使用结构体指针,那么函数里面将会有一堆的解引用

结构体指针作为函数参数

void fb_open(struct framebuffer *fb)//指针
{
    ...
}

void main()
{
    struct framebuffer fb0;
    fb_open(&fb0);//取地址符&
    
	struct framebuffer* fb1;//需要给这个指针分配实体
	fb1 = (struct framebuffer*)malloc();
    fb_open(fb1);//这时就不用取地址符,fb1中的成员的值在fb_open中被改变会影响
}

###详细例子说明

#include <stdio.h>
#include <stdlib.h>

struct test_t{
    int *p;
    
    int a;
    int b;
    int c;
    int d;
};

//函数外部使用malloc测试函数 (函数形参为结构体类型)
void func1(struct test_t * test)
{
    test->a += 1;
    printf("test->a = %d.\n", test->a); 
}

/* 以下为函数内部使用malloc测试函数 (函数形参为结构体类型) */
void func2(struct test_t * test)
{   
    test = (struct test_t *)malloc(sizeof(struct test_t));
    test->b = 1;
    printf("test->b = %d.\n", test->b);
}

//...func3...


void func4(struct test_t **test)
{
    *test = (struct test_t *)malloc(sizeof(struct test_t));
    (*test)->d = 1;
    printf("test->d = %d.\n", (*test)->d);
}


void func_p(struct test_t * test)
{
    test->p = (int *)malloc(sizeof(struct test_t));
}

int main(void)
{
    //使用案例1:函数外malloc
    struct test_t * t1;
    t1 = (struct test_t *)malloc(sizeof(struct test_t));
    t1->a = 1;
    func1(t1);//这样使用,t1->a的值就会改变,和func4(struct test_t **test)区分
    printf("test->a = %d.\n", t1->a);
    free(t1);
    
    
    //有时候需要在函数里面malloc,如下:
#if 0
    //使用案例2:错误使用,编译通过,运行触发段错误
    struct test_t * t2;
    func2(t2);
    printf("test->b = %d.\n", t2->b);
    free(t2);
#endif

#if 1    
    //但是可以在结构体里声明一个指针成员,然后如下使用
    //(实际上原理和案例1是一样的,外部需要有实体,但是这里还提出来,是因为想说一下free的问题)
    //为结构体内部的指针分配内存还是经常遇到的,包含该指针的结构体也是malloc而来的,但是有时只记得free最外层的指针
    struct test_t * t0;
    t0 = (struct test_t *)malloc(sizeof(struct test_t));
    func_p(t0);
    printf("test->p = %p.\n", t0->p);
    free(t0->p);//不会触发段错误,注意free这个指针,还要注意先free这个指针,再free t0
    free(t0);
#endif
    
    
#if 0
    //使用案例3:
    struct test_t * t3;
    
    t3 = 返回值为struct test_t *的func3函数;
    ...
#endif     
    
    //使用案例4:(func4形参使用双重指针类型)
    struct test_t * t4;
    func4(&t4);
    printf("test->d = %d.\n", t1->d);
    free(t4);
    
    //个人常用的就上面几种,当然还有这里没列出来的使用方式
    
    //总结,(返回值,双重指针)多多编程多多体会
    return 0;
}


打印内容test->a = 2.
test->a = 2.
test->p = 0x81ed020.
test->d = 1.
test->d = 1.

另外:在C语言中,使用结构体的时候 "->" 和 “." 有什么区别?

定义的结构体如果是指针,访问成员时就用->
如果定义的是结构体变量,访问成员时就用.
例如:
struct AAA {
    int a;
    char b;
};
struct AAA q; 访问成员就用:q.a;
struct AAA *p; 访问成员就用:p->a;