我是靠谱客的博主 单纯蚂蚁,最近开发中收集的这篇文章主要介绍结构体 结构体,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

 结构体

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;

 

最后

以上就是单纯蚂蚁为你收集整理的结构体 结构体的全部内容,希望文章能够帮你解决结构体 结构体所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部