概述
结构体
the C programme指出:结构体是一个或者多个变量的集合,该变量可能属于不同的类型;ANSI C 标准中定义对结构的赋值操作--结构体可以拷贝、赋值、传送给函数并被函数返回值。
定义一个结构体类型 ;
- 1.struct是关键字 ;
- 2. struct Student合起来才是结构体类型;
- 3.结构体内部定义的变量不能直接赋值 ;
- 4.结构体只是一个类型,没有定义变量前,是没有分配空间,没有空间,就不能赋值 。
结构基础
关键字struct用于引入结构声明,由包含在花括号内一些列说明组成。关键字struct其后跟的名字是可选的,结构标记用于命名结构,在定义之后,结构标记tag就代表花括号内的声明,可用它作为该声明的简写形式。
struct tag {member-list}variable-list;//定义结构
struct tag tag_var; //声明结构
结构中定义的变量称为成员。结构成员、结构标记和普通变量(即非成员)可采用相同的名字,它们之间不会冲突,不同结构中成员可使用相同的名字,但结合编程风格,只有密切相关的对象才会使用相同的名字。
struct声明定义了一种数据类型,在标志结构成员表结束的右花括号之后可跟一个变量表,如下。两者具有类似的意义,这两个声明都将x,y,z声明为指定类型的变量,并且为它们分配存储空间。
struct pomit {
int x;
int y;
}x,y,z;//定义及声明结构
int x,y,z;
如果结构声明的后面不带变量表,则不需要为它分配存储空间,它仅为描述一个结构的模板或轮廓。
定义一个struct tag类型的变量pt,结构的初始化可在定义的后面使用初值表进行初始化,初值表中同每个成员对应的初值必须是常量表达式,如
struct point pt = {300,200};
自动结构也可通过赋值初始化,还可通过调用返回相应类型结构的函数进行初始化。在表达式中,可通过如下引用某个特定结构中的成员: 结构名.成员。其中结构成员运算符"."将结构名与成员名连接起来
printf("%d,%d",pt.x,pt.y);
一个结构说明定义其他类型定义声明结构体变量、结构体数组及结构体指针,如下所示。
struct key{
char *word;
int count;
}x,keytab[],*y;
//x,keytab,y为标签
typedef struct {
char *word;
int count;
}simple;
//simple为类型名
//定义结构
simple key1;
/*struct_def.c 结构应用举例*/
#include<stdio.h>
#include<string.h>
/*
struct Student
{
//定义
int age;
float score;
char name[50];
}s1,s2,*p,array[20];//声明变量列表
*/
typedef struct Student
{
int age;
float score;
char name[50];
}stu;
int main()
{
//声明及初始化
struct Student s1 = {18,88,"mike"};
//赋值
stu s2 = s1;
//结构体指针
stu *p = &s1; //结构体指针
//结构体数组
stu array[20]; //结构体数组
array[0] = s1;
printf("%d,%s,%fn",s2.age,s2.name,s2.score);
printf("%d,%s,%fn",p->age,p->name,p->score);
printf("%d,%s,%fn",array[0].age,array[0].name,array[0].score);
return 0;
}
18,mike,88.000000
18,mike,88.000000
18,mike,88.000000
结构嵌套
结构可以嵌套,形式如下:
struct rect{
struct point pt1;
struct point pt2;
};
/* struct_nest.c 结构嵌套举例*/
#include<stdio.h>
#include<string.h>
struct Info
{
int age;
float score;
};
struct Student
{
struct Info info;
char name[50];
};
int main()
{
struct Student s;
struct Student *p = &s;
p->info.age = 18;
strcpy(p->name,"mike");
p->info.score = 66;
struct Student tmp ={18,77,"mike"
};
printf("%d,%s,%fn",tmp.info.age,tmp.name,tmp.info.score);
printf("%d,%s,%fn",s.info.age,s.name,s.info.score);
return 0;
}
结构与函数
结构合法操作只有几种,作为一个整体复制和赋值,通过& 运算符取其地址,访问结构成员,其中复制和赋值包括函数传递参数以及从函数返回值。结构间不能比较,可用一个常量成员值列表初始化或自动结构可通过赋值进行初始化。
传递结构操作:传送各个结构成员、传送整个结构、传送指向结构的指针;
/*makepoint:make a point from x and y componets*/
struct point makepoint(int x, int y){
struct point temp;
temp.x = x;
temp.y = y;
return temp;
}
注意:参数名和结构成员同名不会引起冲突,事实,使用重名可强调两者的关系;
可使用makepoint函数动态地初始化任意结构,也可向函数提供结构类型的参数,如下:
struct rect screen;
struct point middle;
struct point makepoint(int, int);
screen.pt1 = makepoint(0, 0);
screen.pt1 = makepoint(XMAX, YMAX);
middle = makepoint((screen.pt1.x + screen.pt2.x)/2,
(screen.pt1.y + screen.pt2.y)/2);
写一个函数对点执行算数运算
/*addpoints:add two points*/
struct addpoint(struct point p1,struct point p2){
p1.x +=p2.x;
p1.y +=p2.y;
return p1;
}
结构指针
如果传递给函数的结构很大,使用指针方式效率通常比复制整个结构的效率要高,结构指针类似普通变量指针,声明:
struct point *pp;
struct point origin;
pp = &origin;
printf("origin is (%d,%d)n",(*p).x,(*p).y);
将pp定义为一个指向struct point类型对象的指针,若pp指向一个point指针,那么*pp即为该结构。而(*pp).x和(*p).y则是结构成员,其中(*pp).x中圆括号是必需的,因为结构成员运算符"."的优先级比"*"的优先级高。而表达式*pp.x的含义等价于*(p.x);
为了方便使用,C中提供一个简写方式,假定p是一个指向结构的指针,可用p->结构成员;
printf("origin is (%d,%d)n",p->x,p->y);
运算符.和->都是从左向右结合的,所以,对于下面是声明,以下4个表达式是等价的
struct rect r,*rp = &r;
//4个表达式等价
r.pt1.x;
rp->pt1.x;
(rp.ptr1).x;
(rp->ptr1).x;
在所有运算符中,以下4个运算符的优先级最高:运算符"."和"->"、用于函数调用的"()"以及用于下表"[]",如
struct{
int len;
char *str;
} *p;
++p->len;
将增加len的值,而不是增加p的值,其中的隐含括号关系是++(p->len)。可使用括号改变结合次序,如(++p)->len将先执行p的加1操作,再对len执行操作;而(p++)->len则先对len执行操作,然后再将p加1,该表达式括号也可省略。
同理,*p->str读取的是指针str所指向的对象的值;*p->str++ 先读取指针str指向对象的值,然后再将str加1(与*s++相同);
(*p->str)++ 将指针str指向的对象的值加1;*p++->str 先读取指针str指向的对象的值,然后再将p加1;
例子
#include <stdio.h>
#include <string.h>
struct Student
{
int age;
char name[50];
int score;
};//有分号
int main()
{
struct Student stu2 = {18,"mike",59};
struct Student tmp;
//如果是普通变量,使用.点运算符
tmp.age = 18;
//tmp.name = "mike";//name成员是数组名,数组名是常量,不能修改
strcpy(tmp.name,"mike");
tmp.score = 59;
//如果是指针变量,使用->
//如果是指针,指针有合法指向,才能操作结构体成员
struct Student *p;
p = &tmp;
p->age =19;
p->score = 88;
strcpy(p->name,"mike");
//任何结构体变量都可用.或->操作成员
(&tmp)->age = 18;
//.优先级高,所以加()
(*p).age = 18;
p[0].age = 18;
}
结构体数组
考虑编写一个统计输入中各个C关键字出现的次数程序。需要使用一个字符串数组存放关键字名,一个整型数组存放相应的关键字的出现次数。一种实现方法是,使用两个独立的数组 keyword和keycount分别来存放它们,如下
char *keyword[NKEYS];
int keycount[NKEYS];
这两数组大小相同,考虑该特点,可从采用另一种不同的组织方式,即结构体数组,每个关键字向包含一对变量:
struct key{
char *word;
int count;
}keytab[NKEYS];
它声明了一个结构体类型key,并定义了该类型的结构数组keytab,同时为其分配存储空间,数组keytab的每个元素都是一个结构。它包含一个固定的名字集合,所以最好将它声明为外部变量,只需初始化一次,所有地方都可以使用。
该结构的初始化方法通结构的初始化方法类似——在定义的后面通过一个用圆括号括起来的初值表进行初始化,如
struct key{
char *word;
int count;
}keytab[N] = {
"auto",0,
"break",0,
"case",0,
"char",0,
"const",0,
"continue",0,
"default",0,
/*...*/
"unsigned",0,
"void",0,
"vo;atile",0,
"while",0,
};
与结构成员相应,初值也要按照成对的方式列出,更精确的做法是,将每一行(即每个结构)的初值都括在花括号内,如
{"auto",0},
{"break",0},
{"case",0},
...
若初值是简单变量或字符串,并且其中的任何值都不为空,则内层的花括号可省略。一般,若初值存在并且方括号[]中没有数值,编译器程序将计算数组中keytab中的项数;
例子
#include<stdio.h>
#include<string.h>
struct Student
{
int age;
float score;
char name[50];
};
int main()
{
struct Student a[5]; //结构体数组
//操作元素
a[0].age = 18;
a[0].score = 89;
strcpy(a[0].name,"mike");
//操作元素地址
(a+1)->age = 19;//可以操作结构体 ,只是编译器中没有显示age;
strcpy((a+1)->name,"jiang");
(a+1)->score = 59;
// 操作元素
//操作不了(C语言编译器中应该 可以编译或操作
(*(a+2)).age = 20;
strcpy((*(a+2)).name,"Lily");
(*(a+2)).score = 61;
struct Student *p =a;
p = &a[0];
p[3].age = 21;
p[3].score = 79;
strcpy(p[3].name,"xiaowang");
//(p+4)->age = 22;//操作不了
p[4].age = 24;
p[4].score = 80;
strcpy(p[4].name,"xiaozhang");
int i=0;
int n = sizeof(a)/sizeof(a[0]);
for(i =0;i<n;i++)
{
printf("%d,%s,%fn",a[i].age,a[i].name,a[i].score);
}
return 0;
}
输出:
18,mike,89.000000
19,jiang,59.000000
20,Lily,61.000000
21,xiaowang,79.000000
24,xiaozhang,80.000000
结构体用法解释
1、一个指向 struct Student 类型的指针,p指向一个 Student 结构,*p就是该结构体;(*p).age就是结构成员;
struct Student *p;
2、结构指针使用频率高,一种简写方式作为可选的标记法:
p->age;//表示 结构成员
3、结构体成员运算符. 的优先级比*高;表达式*p.age的含义是:*(p.age),因为age不是指针??,表达式非法;
(*p).age = 18;
4、结构成员运算符(.和->)、函数调用的()以及下标[]的优先级最高,结合最紧密;
增加的是age的值而不是p的值。因为->的优先级比++高,所以该表达式等价于++(p->len)但可以使用括号改变结合次序:(++p)->len:先p加1操作,再对len操作;
++p->age;
最后
以上就是单纯蚂蚁为你收集整理的结构体 结构体的全部内容,希望文章能够帮你解决结构体 结构体所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复