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

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

指针作为输出型参数

  1. 指针作为输出型参数,通俗的理解,指针作为某一函数的实参,在函数内部发生改变后,外部的值也能跟着发生变化
  2. 类比外部的int a作为函数形参并能够传出来,要用指针形式,外部的指针作为函数形参并能够传出来,要使用指针的指针作为形参类型,其实它们的本质原理是一样的,都是传了变量的内存地址给函数
程序1:
void myMalloc(char *s) //在函数中分配内存,再返回 
{ 
	s=(char *) malloc(100); 
} 
void main() 
{ 
	char *p=NULL; 
	myMalloc(p); //这里的p实际还是NULL,p的值没有改变
	if(p) free(p); 
} 
程序2void myMalloc(char **s) //指针的指针,双重指针类型
{ 
   *s=(char *) malloc(100); 
 } 
void main()     
{ 
	char *p=NULL; 
	myMalloc(&p); //这里的p可以得到正确的值
	if(p) 
		free(p); 
} 

指针作为输出型参数本质

  1. 指针变量就是一普通变量,当定义了一个变量,操作系统会为其分配相应的内存单元,内存里面存放的都是多个0和1组成的二进制数。
  2. 函数参数传递都是值传递
  3. 左值和右值,变量做左值,指向的是变量的内存空间,变量做右值,含义为将变量内存中存放的值取出来
  4. 取地址符&,与解地址符 *

假设有一变量 char *a = null;
假设有一函数 func(char *x) {x = ‘a’;}
调用func(a)之后,a还是为null。

调用中间的处理过程:func 临时定义了一个变量 char *x,函数内部使用的是x,而不是直接使用a,然后做了x=a的动作。函数内部一直都是在对x进行操作,故不会改变到a的值。

将函数换成func(char **x) {*x=‘a’;}
调用func(&a)之后,a的值为字符’a’。

调用中间的处理过程:func 临时定义了一个变量 char **xx,函数内部使用的是x,然后做了x=&a的动作,则x变量存放了a的内存地址,函数内部对x进行解地址,即将x变量对应的内存中的那一串0101组成的二进制拿出来,这一串0101组成的二进制就是a的内存地址,*x=‘a’ 即向该空间写值。

结构体指针就是一普通指针变量

结构体指针作为函数参数

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 = null;
    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);
    
    //个人常用的就上面几种,当然还有这里没列出来的使用方式
    
    /** 总结
     * >> 函数使用指针类型形参以提高效率     
     * (1)外部定义指针变量再malloc分配
     * (2)函数外部的指针在函数内部malloc后能得到分配的内存地址的两种方式:双重指针和返回值
     * 多多编程多多体会
     */
    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;
  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
使用C++中的结构体指针作为结构体参数时,可以通过传递指针来直接操作和修改结构体的内容,而不是传递结构体的副本。这样可以节省内存空间并提高程序的效率。 下面是一个示例,演示了如何使用结构体指针作为结构体参数: ```cpp #include <iostream> struct Person { std::string name; int age; }; void updatePersonInfo(Person* person) { person->name = "Alice"; // 修改结构体成员 person->age = 25; } int main() { Person p; p.name = "Bob"; p.age = 30; std::cout << "Before update: " << p.name << ", " << p.age << std::endl; updatePersonInfo(&p); // 传递结构体指针 std::cout << "After update: " << p.name << ", " << p.age << std::endl; return 0; } ``` 在上面的示例中,我们定义了一个名为Person的结构体,包含了姓名和年龄两个成员变量。然后我们定义了一个updatePersonInfo函数,该函数接受一个Person类指针作为参数,并通过指针来修改结构体的成员变量。 在主函数中,我们创建了一个Person类的变量p,并初始化了其成员变量。然后我们调用updatePersonInfo函数,将p的地址作为参数传递给它。在函数内部,我们通过指针修改了p的成员变量。 最后,我们输出修改后的结果,可以看到结构体的成员变量已经被成功更新。 通过使用结构体指针作为参数,我们可以直接修改结构体的内容,而不需要创建副本或者返回新的结构体对象。这种方式在处理大结构体或需要频繁修改结构体内容的情况下非常有用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值