C语言结构体指针与结构体变量作形参的区别

区别

结构体变量

  • 结构体变量作为形参,传递的是结构体变量本身,是一种值传递
  • 形参结构体变量成员值的改变不影响对应的实参构体变量成员值的改变

结构体指针

  • 结构体指针作为函数参数,传递的是指向结构体变量的本身
  • 结构体指针指向的变量成员值的改变影响对应的实参构体变量成员值的改变

代码

直接说有些抽象难懂,敲代码演示一遍就很清楚了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct stru{
int num;
};

//形参为结构体变量
void addNum(struct stru p, int num2)
{
p.num += num2;
}

//形参为结构体指针
void addNum2(struct stru *p, int num2)
{
if(!p) return; //确保指针不为空指针
p->num += num2;
}

int main(){

struct stru t;
t.num = 50;

addNum(t,5000);
printf("形参为结构体变量得到的结果为: %d\n", t.num);

addNum2(&t,5000);
printf("形参为结构体指针得到的结果为: %d\n", t.num);

return 0;

}

输出结果

1
2
形参为结构体变量得到的结果为: 50
形参为结构体指针得到的结果为: 5050

C++ 限定符Const和指针

指向常量的指针

指向常量的指针不能用于其所指对象的值。若想存放常量对象的地址,只能使用指向常量的指针。

1
2
3
4
const int a =  3;	//a是个常量,其值不能改变
int *b = &a; //错误:b是个普通指针
const int *c = &a; //正确
*c = 8; //错误:c不能给a赋值

允许一个指向常量的指针指向一个非常量,但不能通过该指针修改这个非常量的值(但该非常量可以通过其他途径修改)。

1
2
int d = 0;	//一个整型变量
c = &d; //正确,但不能通过指针c修改d的值

const指针

常量指针必须初始化,而且一旦初始化完成其值(也就是放在指针的那个地址)就不能改变了。把*放在const前说明不变的是指针的值而不是所指的那个值。

1
2
3
4
5
6
7
8
9
int a = 0;
int b = 1;
const int *c = &a;
int *const d = &a;


c = &b; //正确:但不能通过c改变b的值
*d = 5; //正确:可以通过d改变a的值
d = &b; //错误:d是一个常量指针,其本身的值不能改变

顶层const与底层const

基本概念

指针本身是不是常量指针所指对象是不是常量是两个相互独立的问题。
用名词 顶层 const 表示本身是个常量。
用名词 底层 const 表示所指对象是个常量。

  • 一般的,顶层const可以表示任意的对象。底层cosnt则与指针和引用等复合类型的基本类型有关。
  • 特殊的,指针可以同时是顶层const底层const;声明引用的const都是底层cosnt
1
2
3
4
int a = 0;
int *const p1 = &i; //顶层const
const int b = 42; //顶层const
const int *p2 = &b; //底层const

拷贝操作

  • 顶层const在进行拷贝操作时不受什么影响
    1
    2
    const int a = 0;
    int b = a; //正确:二者类型相同且顶层const不受影响
  • 底层const的限制不能忽视!拷入和烤出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换。一般来说非常量能转换成常量,反之则不行。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    const int a = 0;
    const int *const p = &a; //具有顶层和底层const的指针p,靠右边的是顶层,靠左边的是底层
    const int &b = a; //声明引用的const都是底层const
    int b = a; //正确:a包含顶层const,无影响


    int *p1 = p; //错误:p包含底层const,p1没有
    const int *p2 = p; //正确:二者都包含底层const,p的顶层const无影响

    int i = 1;
    p2 = &i; //正确:int*能转换成const int*