结构体
1.结构体定义和初始化
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
//定义一个结构体【类型】
//strut 是关键字
//struct Worker合起来才是结构体类型
//结构体内部定义的变量不能直接赋值
//结构体只是一个类型,没有定义变量前,
//是没有分配空间的,不能赋值(C与C++不同,C++可以在定义的时候赋值)
struct Worker {
int age;
char name[5];
int score;
};//必须有分号
int main() {
//定义结构体【变量】
//类型名 变量名
struct Worker wo;
//第一种初始化方式,和数组一样,使用大括号
struct Worker wo2 = {20,"hahah",100};
//第二种初始化方式
struct Worker wo3;
wo3.age = 21;
//name是数组名,数组名是常量,不能直接赋值修改使用strcpy
//wo3.name = "zhangsan";
strcpy(wo3.name, "zhangsan");
wo3.score = 99;
//第三种初始化方式,通过指针,使用->
struct Worker *p;
p = &wo3;
p->age = 22;
p->score = 90;
strcpy(p->name, "lisi");
//任何结构体变量都可以用.或->操作成员
//wo3取地址就是一个指针
(&wo3)->age = 11;
//p加上一个*就是它指向的内存,也就是wo3
(*p).age = 12;
system("pause");
}
2.定义结构体变量的方式
1.先声明结构体类型,再定义变量名
struct Worker {
int age;
char name[5];
int score;
};
struct Worker wo;
2.在声明类型的同时定义变量
struct Worker {
int age;
char name[5];
int score;
}wo,wo2;
3.直接定义结构体类型变量(匿名,无类型名),这种方式定义的结构体,无法在外部定义其他的结构体变量,只能使用已经定义好的
struct {
int age;
char name[5];
int score;
}wo,wo2;
3.结构体数组的定义和赋值
第一种初始化方式
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct Worker {
int age;
char name[10];
int score;
};
int main() {
struct Worker wo;
//定义一个结构体数组
struct Worker a[5];
//给第一个结构体元素赋值
a[0].age = 18;
strcpy(a[0].name, "ren");
a[0].score = 50;
//给第二个结构体元素赋值
(a + 1)->age = 10;
strcpy((a + 1)->name, "zhen");
(a + 1)->score = 30;
//给第三个结构体元素赋值
(*(a + 2)).age = 20;
strcpy((*(a + 2)).name, "ming");
(*(a + 2)).score = 9;
//定义一个指针指向这个结构体数组
struct Worker *p = a;
//给第四个结构体元素赋值
p[3].age = 21;
strcpy(p[3].name, "ying");
p[3].score = 100;
//给第五个结构体元素赋值
(p + 4)->age = 32;
strcpy((p + 4)->name, "zi");
(p + 4)->score = 10;
int i = 0;
int n = sizeof(a) / sizeof(a[0]);
for (i = 0; i < n; i++) {
printf("%d,%s,%d\n", p[i].age, p[i].name, p[i].score);
}
system("pause");
}
第二种初始化方式,下边a a1 a2都是初始化一个结构体数组
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct Worker {
int age;
char name[10];
int score;
};
int main() {
struct Worker a2[5] =
{
{11,"a",12},
{12,"b",13},
{13,"c",14},
{14,"d",15},
{15,"e",16}
};
struct Worker a3[5] = {
11,"a",12 ,
12,"b",13,
13,"c",14,
14,"d",15,
15,"e",16
};
struct Worker a[5] = {
11,"a",12 ,12,"b",13,13,"c",14,14,"d",15,15,"e",16
};
int i = 0;
int n = sizeof(a) / sizeof(a[0]);
for (i = 0; i < n; i++) {
printf("%d,%s,%d\n", a[i].age,a[i].name, a[i].score);
}
system("pause");
}
4.结构体嵌套
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct Manager {
int salary;
int year;
};
struct Worker {
int age;
struct Manager m;
};
int main() {
//定义一个结构体Worker变量
struct Worker w;
//通过结构体变量给这个结构体赋值
w.age = 20;
w.m.salary = 20000;
printf("%d,%d\n", w.age,w.m.salary);
//定义一个结构体指针指向这个结构体,通过指针赋值
struct Worker *p = &w;
p->age = 21;
p->m.salary = 30000;
p->m.year = 2018;
printf("%d,%d,%d\n", w.age, w.m.salary,w.m.year);
//直接在定义的时候初始化赋值,这种赋值形式可读性很差
struct Worker woker = {22,19999,2019};
printf("%d,%d,%d\n", woker.age, woker.m.salary,woker.m.year);
system("pause");
}
5.相同类型的结构体变量可以相互赋值
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct Manager {
int salary;
int year;
};
int main() {
//相同类型的变量可以通过=号赋值
int a = 10;
int b;
b = a;
printf("%d\n",b);
//相同类型的结构体变量也可以相互赋值
struct Manager s1 = {20000,2018};
struct Manager s2;
s2 = s1;
printf("%d,%d\n",s2.salary,s2.year);
system("pause");
}
6.结构体的值传递
结构体值传递和普通数据类型的值传递原理是相同的,把结构体变量m2传递到setManager方法中,相当于把m2的值赋给了形参m(相同类型的结构体变量可以赋值),此时m和m2内存中存储的值是相同的,但是二者没有直接联系,然后在方法setManager中给m中的元素重新赋值,打印结果如下,可以看出,方法执行完成后销毁,原来的m2的内存空间并不受影响
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct Manager {
int salary;
int year;
};
void setManager(struct Manager m) {
m.salary = 1000;
m.year = 2018;
printf("setManager %d %d\n", m.salary, m.year);
}
int main() {
struct Manager m2 = {10000,2019};
setManager(m2);
printf("setManager %d %d\n", m2.salary, m2.year);
system("pause");
}
打印
setManager 1000 2018
setManager 10000 2019
请按任意键继续. . .
7.结构体的地址传递
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct Manager {
int salary;
int year;
};
void setManager(struct Manager *m) {
m->salary = 1000;
m->year = 2018;
printf("setManager %d %d\n", m->salary, m->year);
}
int main() {
struct Manager m2 = {10000,2019};
setManager(&m2);
printf("setManager %d %d\n", m2.salary, m2.year);
system("pause");
}
打印
setManager 1000 2018
setManager 1000 2018
请按任意键继续. . .
8.结构体指针指向栈区空间
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct Manager {
int salary;
int year;
};
int main() {
//在栈内存定义一个结构体变量
struct Manager m;
//定义一个结构体指针指向结构体变量m
struct Manager *p;
p = &m;
p->salary = 1999;
p->year = 2018;
printf("%d %d\n", m.salary, m.year);
system("pause");
}
9.结构体指针指向堆区空间
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct Manager {
int salary;
int year;
};
int main() {
struct Manager *p;
//在堆内存开辟一块空间并由p指向它
p = (struct Manager*)malloc(sizeof(struct Manager));
if (p == NULL) {
printf("malloc err\n");
return 0;
}
p->salary = 1999;
p->year = 2018;
printf("%d %d\n", p->salary, p->year);
if (p != NULL) {
free(p);
p = NULL;
}
system("pause");
}
10.结构体中的指针变量
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct Manager {
int salary;
int year;
char *name;
};
int main() {
struct Manager m;
//在堆区开辟空间并由结构体中的成员变量指向它
//这里是在堆区开辟空间由它指向这个空间,当然也
//可以在栈中定义一个变量由这个指针指向他
m.name =(char *) malloc(strlen("renzhenming") + 1);
strcpy(m.name, "renzhenming");
m.salary = 10000;
m.year = 2019;
printf("%d %d %s\n", m.salary, m.year,m.name);
if (m.name != NULL) {
free(m.name);
m.name = NULL;
}
system("pause");
}
共同体(共用体 联合体)
由于共同体中所有成员公用同一份内存,所以共同体中不可以同时操作两个或两个以上得元素,因为当你操作其中一个,加入给其中一个附了值,那么另一个值就会发生变化,因为内存已经改变了,如下程序中,共同体所占内存为4个字节,因为int最大,int占4个字节,给c赋值0x44332211后,刚好占满内存,由于abc所指向得首地址是相同得,所以a指向从首地址开始第一个字节,那么打印就是11,b指向从首地址开始前两个字节,那么打印就是2211,c指向从首地址开始到结尾这块内存,打印就是44332211
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
union Manager {
unsigned char a;
unsigned short b;
unsigned int c;
};
int main() {
//结构体大小可以简单得认为是成员大小得累加
//共同体得大小为最大成员得大小,成员中最大得是int,所以打印为4
printf("%lu\n", sizeof(union Manager));
//共同体共有一块内存,所有成员地址都一样
union Manager m;
printf("%p,%p,%p,%p\n", &m,&m.a,&m.b,&m.c);
//给某个成员赋值,会影响到另外得成员
//左边是高位,右边是低位
//高位放高地址,低位放低地址
m.c = 0x44332211;
printf("m.c = %x\n",m.c);
printf("m.a = %x\n", m.a);
printf("m.b = %x\n", m.b);
m.a = 00;
printf("m.c = %x\n", m.c);
printf("m.a = %x\n", m.a);
printf("m.b = %x\n", m.b);
system("pause");
}
未完,待续...
`