知识点
struct Student{
char name[20];
int age;
int classId;
};
int main(int argc, const char * argv[]) {
struct Student student;
return 0;
}
还可以在定义结构体的时候直接声明结构体变量:
struct Student{
char name[20];
int age;
int classId;
}s1,s2;
也可以定义匿名结构体:
struct {
char name[20];
int age;
int classId;
}s1;
但是这样的话就不能在其他地方再定义结构体变量了。
结构体变量初始化(三种方式)
s1={"abcd",20};
printf("name=%s,age=%d,classId=%d\n",s1.name,s1.age,s1.classId);
输出结果:
name=abcd,age=20,classId=0
strcpy(s1.name, "defg");
s1.age=30;
printf("name=%s,age=%d,classId=%d\n",s1.name,s1.age,s1.classId);
输出结果:
name=defg,age=30,classId=0
为什么不能直接s1.name="defg";呢?因为字符串在c语音中表示的是一个地址,例如我们一般只样写:char *p="abcd";所以说s1.name="defg";就相当于是把一个地址赋值给了一个字符串,肯定是行不通的。
struct {
char name[20];
int age;
int classId;
}s1={"ab",32};
输出结果:
name=ab,age=32,classId=0
结构体数组
初始化:
struct Student students[3] ={{"ab",20},{"cd",10},{"ef",5}};
struct可以省略。
int i=0;
Student stu[5];
for(int i=0;i<5;i++)
{
strcpy(stu[i].name, "abc");
stu[i].age=i;
}
结构体指针
使用方法跟普通类型没什么区别
struct Student s1={"abcd",20};
printf("name=%s,age=%d,classId=%d\n",s1.name,s1.age,s1.classId);
struct Student *p;
p=&s1;
printf("name=%s,age=%d,classId=%d\n",p->name,p->age,p->classId);
输出结果:
name=abcd,age=20,classId=0
name=abcd,age=20,classId=0
结构体指针表示数组
先看一段程序以及运行结果:
struct Student *p1;
int i;
p1=(Student *)malloc(sizeof(Student)*5);//必须先分配内存
//memset(p1, 0,sizeof(Student)*5);
for(i=0;i<5;i++)
{
(p1+i)->age=10;
strcpy((p1+i)->name, "lucy");
}
for(int i=0;i<5;i++)
{
printf("name=%s,age=%d,classId=%d\n",(p1+i)->name,(p1+i)->age,(p1+i)->classId);
}
运行结果:
name=lucy,age=10,classId=-1431310072
name=lucy,age=10,classId=0
name=lucy,age=10,classId=0
name=lucy,age=10,classId=0
name=lucy,age=10,classId=0
如果放开
memset(p1, 0,sizeof(Student)*5);//初始化操作
运行结果:
name=lucy,age=10,classId=0
name=lucy,age=10,classId=0
name=lucy,age=10,classId=0
name=lucy,age=10,classId=0
name=lucy,age=10,classId=0
结果体指针变量使用前必须初始化(不同于普通类型指针变量)结构体内部的普通类型指针变量是不用初始化的(看到网上有人说必须初始化,这个是错误的)。
(这个后来发现是错误的啊,最下面有解释)
验证:
struct Student{
char *p;
char name[20];
int age;
int classId;
};
struct Student s1;
s1.p="aaa";
printf("p=%s,name=%s,age=%d,classId=%d\n",s1.p,s1.name,s1.age,s1.classId);
输出结果:
p=aaa,name=,age=0,classId=1606416144
结构体包含函数指针
struct Student{
char *p;
char name[20];
int age;
int classId;
int (*s)(char *,int);
};
int fun(char *p,int i)
{
printf("p=%s,i=%d\n",p,i);
return 0;
}
int main(int argc, const char * argv[]) {
struct Student s1;
s1.s=fun;
s1.s("abcd",10);
return 0;
}
输出结果:
p=abcd,i=10
结构体包含结构体指针(链表的原理)
模拟单行链表,在链表的末尾添加一个节点:
struct Node{
int data;
Node *next;
};
void insertNode(Node *head,int data)
{
//先根据data创建一个Node
Node *node=(Node *)malloc(sizeof(Node));
node->data=data;
node->next=NULL;
//遍历到原链表的末尾
Node *temp=head;
while(temp->next!=NULL)
{
temp=temp->next;//不要用head直接操作,这样的话就找不到链表首地址了
}
temp->next=node;
}
int main(int argc, const char * argv[]) {
Node node;
node.data=10;
node.next=NULL;
insertNode(&node, 20);
Node *head=&node;
while (head->next!=NULL) {
printf("%d\n",head->data);
head=head->next;
}
printf("%d\n",head->data);
}
输出结果:
10
20
疑惑
为什么定义一个结构体变量可以直接使用,但是定义一个结构体指针却必须要动态分配内存?
看这儿:http://blog.csdn.net/dreamzuora/article/details/54377197
摘抄其中的一段文字:
struct data
{
int i;
int j;
};
void main(void)
{
struct data dat1; //定义一个struct data类型的变量,和int i同理。
printf("%d\n", sizeof(struct data)); //8个字节
printf("%d\n", sizeof(dat1)); //8个字节
struct data* pdat1;//定义一个struct data类型的指针,和int *pi 同理。
printf("%d\n", sizeof(pdat1)); //4个字节,就是一个指针的空间,pdat1并没有结构体变量的信息。
pdat1 = (struct data*)malloc(sizeof(struct data)); //申请一个空间,把该空间地址给pdat1.
printf("%d\n", sizeof(*pdat1)); //8个字节
struct data dats1[2];
printf("%d\n", sizeof(dats1)); //16个字节,两个data变量,不是data指针。
dats1[0].i = 20; //可以直接使用数组里面的结构体变量
dats1[0].j = 30;
struct data* dats2[2]; //指针数组,包含两个指针,而不是结构体变量
printf("%d\n", sizeof(dats2)); //8个字节,两个指针的大小
dats2[0]->i = 20; //错误!还没有给dats2[0] 指针分配空间
dats2[0]->i = 20; //错误!还没有给dats2[0] 指针分配空间
dats2[0] = (struct data*)malloc(sizeof(struct data)); //分配空间
dats2[0]->i = 20; //ok
dats2[0]->i = 20; //ok
}
一直以为普通类型的指针是不需要动态分配内存就可以使用的,但是也不行。
int *aa;
aa=(int *)malloc(sizeof(int));//没有这个语句报错
*aa=10;
calloc、malloc
Node *node1=(Node *)malloc(sizeof(Node)*10);//分配10块空间,这10块空间是连续的(块内和块间都连续)。
Node *node2=(Node *)calloc(10,sizeof(Node));//分配10块空间,这10块空间是不连续的(块内是连续的,块间是不连续的,并非一定不连续,看内存使用情况,这个是有当时的系统内存使用情况决定的)。
typedef指令
就是定义别名
typedef char* String;
int main(int argc, const char * argv[]) {
String str="abcde";
printf("%s\n",str);
return 0;
}
输出结果:
abcde
大大的疑问
还是关于指针的:
int main(int argc, const char * argv[]) {
int *p;
int a=10;
p=&a;
printf("%d\n",*p);
return 0;
}
输出结果:
10
int *aa;
aa=(int *)malloc(sizeof(int));//没有这个语句报错
*aa=10;
这样写就必须分配内存,解释下这两种情况:
第一种:定义了一个int类型的变量和一个int类型的指针,然后把int变量的地址存到了int类型的指针中。
第二种:定义了一个int类型的指针,然后分配一块int类型的空间并把这块空间的地址存到int类型的指针中,然后把10存到这块空间中。
这样的话上面关于结构体中的普通类型的指针变量不需要分配空间的描述就是错误的。
union共用体
union xn{
int a;
char b;
float c;
};
int main(int argc, const char * argv[]) {
xn temp;
temp.a=10;
temp.b='a';
temp.c=1.0;
printf("a=%d,b=%c,c=%f\n",temp.a,temp.b,temp.c);
return 0;
}
union中所有变量共享内存,也就是a、b、c内存的首地址都是相同的,可以自己验证,所以在给a、b、c分别赋值之后,会进行值覆盖,只能取到最后一次赋值的变量的值。
enum枚举
enum en{
one,
two,
three
};
int main(int argc, const char * argv[]) {
printf("one=%d,two=%d,three=%d\n",one,two,three);
return 0;
}
输出结果:
one=0,two=1,three=2