结构体详解(待补充)

基本概念

结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
结构体是一种自定义类型

结构体的声明

struct tag 
{   
     member-list; 
  }variable-list; //分号不能丢

不完全声明—— 匿名结构体

//匿名结构体类型 
struct 
{    
int a;    
char b;    
float c; 
}x; 
struct 
{    
int a;    
char b;    
float c; 
} a[20], *p;

p = &x;

上面的结构在声明的时候省略掉了结构体标签(tag)。

是否可行?
不可行

更改为如下可以使用

struct 
{    
int a;    
char b;    
float c; 
}x,*p; 
p = &x;

结论如下:
结构体的类型是否一致,取决于是否是同一个结构体定义的变量,哪怕两个结构体的成员完全一致,也是两种类型。

结构体自引用

struct Node 
{    
int data;    
struct Node next; //空间不确定
}; //可行否? 如果可以,那sizeof(struct Node)是多少? 

在这里插入图片描述类似于递归没有出口的状态

正确的自引用如下所示:

struct Node 
{    
int data;    
struct Node* next;//它的类似是struct Node*  它的空间是可以定义出来的
 };

对结构体进行重命名必须要保证结构体本身的类型是确定的,

typedef struct 
{    
int data;   
 Node* next; //此处的Node 的类型不明确  程序到这行代码的时候 还没有Node 这样的类型
 //就好像是只知道 这是一个指针,但是是 int *?double *?  还是结构体的指针是不确定的。
 }Node; //真正是到这里才明确的,所以不可行

//解决方案: 
typedef struct node
 {    
 int data;    
 struct node* next; //而这里事实上是明确了 是一个结构体的指针
 }Node;

定义结构体类型

struct stu
{
	char name[20];
	int age;
	char sex[10];
};
```、

//以下定义结构体指针的写法不太推荐,但需要了解。

```c
typedef struct stu
{
	char name[20];
	int age;
	char sex[5];
	char id[20];
}stu, *stu_p, stu_arr[10];//
//定义结构体类型
//定义了一个指针类型  类似于int *
//定义了一个数组类型  类似于int arr

int main()
{
	stu a = { "zhangsan",18, "man", "001" };
	stu_p p = &a;   //p 是指针的名字
	stu_arr arr1;   //arr1 是数组的名字  是有十个结构体变量的集合

在这里插入图片描述
下面的写法就一目了然,能够很容易知道是个什么变量,(与上面的是等效的)

stu student1 = { "zhangsan", 29, "man" };
stu *p = &student1;
stu arr[10]; 


结构体成员可以是标量(int \float\double…),嵌套数组,指针,甚至是其他结构体。

结构体的内存对齐(重要理解)

重命名

 typedef struct stu
{
	char name[20];
	int age;
	char sex[10];
}stu_t;

struct stu 叫做结构体类型
就类似于 int float double 这个意思
有的时候觉得写起来太复杂就重命名stu_t,此时struct stu 等于stu_t。

结构体赋值

struct stu student1 = { "zhangsan", 29, "man" };
struct stu student2 = { "lisi",18, "felman" };

student1 、 student2 就相当于变量名。
举个例子 int a=10; a 就相当于这里的student1 、 student2。 花括号里面就是赋值。
强调

结构体和数组一样都是一个聚合类型。聚合类型除了在初始化的时候可以整体赋值,其余时候都不能整体赋值
对于数组,循环赋值。
对于结构体,用. 操作符赋值。

//以下为错误用法

int arr[5];
arr={1,2,3,4,5};

stu a;
a={ "zhangsan",18, "man", "001" };
struct stu s
{
 char name[20];
 int age;
}
int main()
{
struct stu s;
strcpy(s.name,"zahngsan"); // 错的   name 是一个数组,不能直接赋值 s.name="zhangsan"
s.age=20;
return 0;
}

成员访问

printf("%s %d %s", student1.name, student1.age, student1.sex)

对于一个变量必须提到的三个问题:空间,内容,地址。
下面主要介绍关于地址。

既然是一个变量自然可以取地址

	stu_t student1 = { "zhangsan", 29, "man" };
	stu_t *p = &student1;//与上面的定义一个指针类型是一样的效果

	printf("%s %d %s\n", (*p).name, (*p).age, (*p).sex);//优先级问题
	
	printf("%s %d %s\n", p->name, p->age, p->sex);

->主要是对结构体指针 来引用成员名字。
printf("%s %d %s\n", (*p).name, (*p).age, (*p).sex)

这种写法实在太过于复杂,因而有了-> .
以下报错: 注意优先级问题
事实上 . 的优先级比*高,会先和p 结合,故而报错。
printf("%s %d %s\n", *p.name, *p.age,*p.sex);

结构体传参数,传值 ,拷贝

结论
结构体不谈“退化、降维”问题,结构体要发生对应的硬拷贝(注意:结构体内部的数组也是硬拷贝)
但数组传递参数本身就发生降维问题。
建议
结构体传参的时候,要传结构体的指针

void show(stu_t s)
 {

	 printf("%s %d %s", s.name, s.age,s.sex);
	 printf("show:%p\n", &s);
 }
int main()
{


	stu_t student1 = { "zhangsan", 29, "man" };
	stu_t *p = &student1;

  show(student1);
  printf("main:%p\n", &student1)
  
  system("pause");
  return 0;
}

//区分以下有什么区别。


 void show(stu_t *p)
{
	 printf("%s %d %s\n", p->name, p->age, p->sex);
	 printf("show:&*p:%p\n", p);//用的是指针变量p 的内容
	 printf("show:&p:%p\n", &p);  

}
int main()
{

	show(&student1);

	printf("main:%p\n", &student1);


	system("pause");
	return 0;
}

//如果是指针其实打印出来的两个地址是一样的

结构体内存对齐

复盘

很重要的一个点就是,学习的过程是由厚到薄。抓住核心,归纳总结。
如果觉得自己越学越难,越学越多,越复杂,可能需要重新找一下方法。理解内在逻辑关系。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值