dnspod网站备案不关站,微信订阅号不认证可以做网站吗,wordpress 拉不到底,有模板做ppt的网站有哪些什么是自定义数据类型呢#xff1f;顾名思义#xff0c;就是我们用户自己定义和设置的类型。
在C语言中#xff0c;我们的自定义数据类型一共有三种#xff0c;它们分别是#xff1a;结构体(struct)#xff0c;枚举(enum)#xff0c;联合(union)。接下来#xff0c;我…什么是自定义数据类型呢顾名思义就是我们用户自己定义和设置的类型。
在C语言中我们的自定义数据类型一共有三种它们分别是结构体(struct)枚举(enum)联合(union)。接下来我们将对这三者中的结构体进行系统和深入的学习。
目录 一、结构体的声明与创建
1如何声明和创建结构体类型
2函数内声明和函数外声明
3匿名结构体的声明与创建
二、结构体的自引用
问题一自引用的成员变量不是以指针的形式出现的
问题二使用不完整的数据类型去定义自引用成员变量
三、结构体变量定义初始化和赋值
1关于结构体变量的定义
2关于结构体变量的初始化 i. 按照顺序进行初始化可以进行不完全的初始化
ii. 指定成员进行初始化
3区分赋值和初始化
四、和结构体有关的计算 一、结构体的声明与创建
1如何声明和创建结构体类型
在使用C语言来解决一些实际问题的过程当中我们难免会发现对于生活中的有一些数据实体我们难以直接使用某一种单一的基本数据类型来阐述它。
比如说我现在想要表示一个学生的实体那对于一个学生这样的实体而言我们需要关注的信息可能有他的名字name他的年龄gae他考试得了多少分score等等诸如此类的要素。显然站在我们程序设计者的角度在这些要素里面既有字符类型name又有int类型age还有double类型的score。
没法用一个单一的基本数据类型来阐述它而我们又不希望把这些诸多要素分散开来更希望把它们整合起来表达一个具体的实体。这个时候结构体struct应运而生结构体类型允许用户使用struct关键字将各种不同的数据类型组合在一起形成新的数据类型用以表示复杂的数据对象。
比如下面就是一个典型的用以表示学生的结构体类型它的声明代码
struct Student
{char name[20];//名字int age; //年龄char sex[5]; //性别double score; //成绩
};
其中struct是关键字Student是结构体的名字显然这个可以由用户自己来设计{}里面的内容诸如nameage……这些我们称之为结构体的成员变量这个也是用户根据自己的业务需求来设计。
另外这里唯一值得大家注意和说明的一点就是Student它不是一个完整的数据类型struct Student它才是一个完整的数据类型。即
struct Student
{char name[20];//名字int age; //年龄char sex[5]; //性别double score; //成绩
};int main()
{Student data1 //error这种定义结构体的方式是不正确的struct Student data2 //right这种定义结构体的方式才正确return 0;
} 2函数内声明和函数外声明
结构体声明啥的有了那带来的第一个问题便是声明位置的问题。
我们很多时候声明结构体都习惯于将其放在函数外声明。但是并不排除有小伙伴会把结构体的声明放在函数内如图所示
#includestdio.hint main()
{struct Book{char name[20];char author[12];float price;};struct Book data { Childhood,Gorky,5 };printf(%ss %s costs $%.2f, data.name, data.author, data.price);return 0;
}
这样写有没有问题呢OK没有问题。这里面可能还涉及有一些东西诸如结构体变量的初始化这些你可能还不太会。但是这些都不是重点我希望你注意到的是
结构体类型和本地变量一样在函数内声明的结构体类型往往只能在函数内部被使用。
所以大部分的开发者都习惯于将一个结构体的声明放在函数的外面这样这个结构体类型就能在多个函数里面被使用啦。 3匿名结构体的声明与创建
关于C语言结构体的声明和创建在有些地方你可能会发现有人会把代码写成下面这样的形式
struct
{int x;int y;
}p1, p2;
这段声明和我们前面所提到的结构体声明它最大的特点就是在struct后面没有那个用户所指定的名字了。然后后面紧接着的p1p2它们是这个类型的两个变量注意它不是这个类型的名字。这种定义结构体变量的方式在C语言里面是被允许的。
我们把这种没有名字的结构体类型统一地叫做匿名结构体。这种结构体类型的最大特点是它没有名字无法被用户长期地使用。
使用这种结构体的开发者他们的需求仅仅只是暂时性地需要一个或多个这种类型的变量罢了。然后这几个变量里面呢有一些明确的成员比如x和y。至于这个类型它是什么名字的我不关心因为这只是我暂时性的需求我并不打算在很远的将来继续使用这种类型。这个时候我就可以去使用这种匿名结构体。
关于匿名结构体另外一个好玩的事情是我们不妨先来一起来看一下下面这段代码
#includestdio.h
//匿名结构体类型
struct
{int a;char b;float c;
}x;
struct
{int a;char b;float c;
}*p;然后提出的问题是在上面代码的基础上下面这段代码是否合法
int main()
{p x;return 0;
}
有很多人会简单认为说这两个匿名结构体成员变量都是一模一样的因此他们是两个相同的结构体类型。实际上在编译器看来虽然这两个匿名结构体内部的成员都是一模一样的但仍然是两个不同的结构体类型。 因此用户如果在前面代码的基础上执行p x操作这样的行为将会认为是不合法的。
但是现在绝大多数的编译器它大概率只会给你一个警告但是我仍然希望广大读者朋友们不要这样草率地去使用匿名结构体。 二、结构体的自引用
结构体的自引用是指在结构体中包含一个类型为该结构体本身的成员这个成员变量总是以指针的形式出现。
这种结构体的应用场景常常出现在数据结构中。如图所示示范如何用结构体声明一个链表结构。
//数据结构————链表的声明
struct ListNode
{int val;struct ListNode* next;
};
这里有两个初学者容易出问题的地方。
问题一自引用的成员变量不是以指针的形式出现的
//数据结构————链表的声明
struct ListNode
{int val;struct ListNode next;
};
这样做在C语言里面是不被允许的。你想如果这样做的行为被允许了那带来的其中一个问题就是结构体大小将变得无法计算。
即最开始的那种定义的链表它结构体的大小如果要计算的话我只要知道当前这台机器它的系统架构是x86C语言的指针在x86的系统架构下大小是4Byte还是x64C语言的指针在x64的系统架构下大小是8Byte.我就能大概判断出
sizeof(struct ListNode) sizeof(int) 4/8实际的大小计算会更复杂我们将在后续的篇章给大家介绍。
但是如果说自引用的成员变量不是以指针的形式出现的。那
sizeof(struct ListNode) sizeof(int) sizeof(struct ListNode)
你会发现这将是一个无法被计算的表达式。
问题二使用不完整的数据类型去定义自引用成员变量
在正式阐述这个问题之前我们先来认识一个C语言里面的关键字typrdef我们说typedef是C语言里面的一个关键字它的作用就是用来给一个数据类型起别名的。
注意这里起别名的含义起了别名并不代表你前面那个类型的名字你用不了了。eg
typedef int DataType;int main()
{//以下都是在定义int类型的变量int x 0;DataType y 0;return 0;
}
有了这个语法做铺垫小伙伴们以后在定义链表的时候就可以这样声明和创建它了
//数据结构————链表的声明
typedef struct ListNode
{int val;struct ListNode* next;
}ListNode;int mian()
{//ListNode就是struct ListNode的别名因此下面两种写法都是正确的struct ListNode node1;ListNode node2;return 0;
}
而带来便捷的同时也可能带来一些潜在的隐患
//数据结构————链表的声明
typedef struct ListNode
{int val;ListNode* next;//error不要使用不完整的数据类型
}ListNode;
注意这样去写就又不对了这是因为我的typedef这个动作做完之后ListNode才是struct ListNode换句话说在这段代码语句中ListNode仍然还只是一个不完整的不可被使用的数据类型。
对于结构体的自引用大家平时注意一下这两个问题那基本的使用就问题不大了。因此这一块的内容我们给大家介绍到这里。 三、结构体变量定义初始化和赋值
有了类型接下来我们还需要学会如何去使用这个我们自定义出来的数据类型。首先第一点当然就是如何使用这个数据类型去定义一个变量并对这个变量进行初始化的操作。
1关于结构体变量的定义
我们这里主要和大家介绍两种不同的定义结构体变量的方式方法。
第一种就是一个结构体类型被声明出来时这个时候我们是可以去定义一些结构体变量的。如图所示
//s1s2都是struct Student类型的结构体变量
struct Student
{char name[20];int age;
}s1,s2;
第二种就是声明时我不定义变量在函数内部当我要用到这种类型的变量时我再去定义它。如图所示
#includestdio.h
struct Student
{char name[20];int age;
};int main()
{//当我需要这种类型变量的时候我再去定义它struct Student s1;return 0;
} 2关于结构体变量的初始化
关于结构体变量的初始化一般而言有两种方式
按照顺序对它的各个成员进行初始化指定其成员变量进行变量。
接下来我们将就一个表示学生的struct Student来进行逐个说明
//一个表示学生的结构体
struct Student
{char name[20];int age;double score;
}; i. 按照顺序进行初始化可以进行不完全的初始化
如图所示即为按照顺序对结构体的各个成员进行初始化示例
#includestdio.hstruct Student
{char name[20];int age;double score;
};int main()
{//一、在结构体变量定义时按顺序进行初始化(可以只初始化一部分,只要按顺序即可)struct Student s1 { Lisi,20,100 };struct Student s2 { Wangwu,19};printf(name%s\tage%d \tscore%.2f\n, s1.name, s1.age, s1.score);printf(name%s\tage%d \tscore%.2f\n, s2.name, s2.age, s2.score);return 0;
}
ii. 指定成员进行初始化
如图所示即为在定义结构体变量时指定成员进行初始化示例
#includestdio.hstruct Student
{char name[20];int age;double score;
};int main()
{//一、在结构体变量定义时按顺序进行初始化(可以只初始化一部分,只要按顺序即可)struct Student s1 { Lisi,20,100 };struct Student s2 { Wangwu,19};printf(name%s\tage%d \tscore%.2f\n, s1.name, s1.age, s1.score);printf(name%s\tage%d \tscore%.2f\n, s2.name, s2.age, s2.score);//二、在结构体变量定义时指定成员进行初始化struct Student s3 { .name Zhangsan, .score 80 };printf(name%s\tage%d \tscore%.2f\n, s3.name, s3.age, s3.score);return 0;
} 3区分赋值和初始化
大家在对变量进行操作时一定要区分好赋值和初始化。在C语言里面它们是两个截然不同的概念。如图所示
#includestdio.hint main()
{//变量的初始化int x 10;//变量的赋值x 20;return 0;
}
简单来说
初始化是指在变量声明时就为其赋予的初值变量一开始是没有值的或者说只有未知值初始化的目的在于使变量一开始就处于一个已知的状态这一点对于避免未定义的行为非常重要。赋值是指在变量已经有一个确定的值的前提即初始化下改变其当前值的行为。
如果有了上面的基础你大概就能很好地掌握我接下来要阐述的关于结构体赋值的几个要点。关于结构体的赋值在C语言里面我们要注意不能使用列表列表也就是形如{......}的这种形式。即下面这些关于结构体赋值的操作在C语言里面都是错误的行为如果你的这些行为被允许了请考虑将你文件改为.c因为这种行为在C里面是被允许的但是纯C当然就不行
#includestdio.hstruct Book {char name[20];double price;
}book1;int main()
{//错误的结构体赋值操作book1 { 平凡的世界, 8 };book1 { .name 查理九世, .price 5 };return 0;
}
那正确的赋值操作应该怎么做正确的赋值操作应该是下面这种的
#includestdio.h
#includestdlib.hstruct Book {char name[20];double price;
}book1;int main()
{//正确的结构体赋值操作strcpy(book1.name, 查理九世);book1.price 5;return 0;
}
既然用不了列表我们就不要去用列表嘛OK就是这么简单。另外小伙伴可能会有下面这种行为
book.name 查理九世;
注意name是个数组名数组名是数组首元素的地址那是一个常量的地址。即name的地址是改不了了的但是你上面的代码语句的操作是将一个常量字符串的地址交给name这种行为已经对name的值进行改变了因此是不被允许的。 你只能改的是name数组里面存储的内容。这里用我们前面学过的字符串内容拷贝函数——strcpy是个不错的选择。 四、和结构体有关的计算
以下面这个结构体为例子我们来快速过一下和结构体有关的一些运算
//p1p2是两个struct Point的结构体变量
struct Point
{int x;int y;
}point1 {1, 2}, point2 {3, 4};
首先和一般的变量一样你可以用 操作符拿到结构体变量的地址并把它交给一个同类型的结构体指针变量进行保存
struct Point* p1 point1;
再者两个不同的结构体变量之间可以进行诸如point1 point2也就是赋值的操作
point1 point2; //相当于point1.x point2.xpoint1.y point2.y。
point1 (struct Point){ 5,6 }; //相当于point1.x 5point1.y 6。
当然啦结构体也可以作为我们函数的参数比方说我现在想要设计一个函数PrintStruct这个函数可以打印出给定结构体的各个成员我大致可以这样来设计它的参数类型一般情况下我们更加推介大家使用第二种写法(即传址优于传值)具体原因我们会在之后的篇章给大家进行说明
//写法一形参写的是结构体变量
void PrintStruct(struct Point point);
//写法二形参写的是结构体指针
void PrintStruct(struct Point* p);
其次对于结构体变量来说我们可以使用 . 结构体变量访问成员操作符。来访问它的内部成员。
printf(point1.x %d, point1.y %d, point1.x, point1.y); 最后对于结构体指针变量可以使用 - 结构体指针访问成员操作符。来访问它的内部成员。
printf(point1.x %d, point1.y %d, p1 - x, p1 - y);
文章转载自: http://www.morning.zpqbh.cn.gov.cn.zpqbh.cn http://www.morning.kttbx.cn.gov.cn.kttbx.cn http://www.morning.ryfq.cn.gov.cn.ryfq.cn http://www.morning.srrzb.cn.gov.cn.srrzb.cn http://www.morning.mjmtm.cn.gov.cn.mjmtm.cn http://www.morning.myzfz.com.gov.cn.myzfz.com http://www.morning.wxgd.cn.gov.cn.wxgd.cn http://www.morning.wpcfm.cn.gov.cn.wpcfm.cn http://www.morning.gwkwt.cn.gov.cn.gwkwt.cn http://www.morning.lngyd.cn.gov.cn.lngyd.cn http://www.morning.nfmlt.cn.gov.cn.nfmlt.cn http://www.morning.dhyqg.cn.gov.cn.dhyqg.cn http://www.morning.mfbcs.cn.gov.cn.mfbcs.cn http://www.morning.rsszk.cn.gov.cn.rsszk.cn http://www.morning.xllrf.cn.gov.cn.xllrf.cn http://www.morning.mcwgn.cn.gov.cn.mcwgn.cn http://www.morning.mjbjq.cn.gov.cn.mjbjq.cn http://www.morning.rgwz.cn.gov.cn.rgwz.cn http://www.morning.wjzzh.cn.gov.cn.wjzzh.cn http://www.morning.junyaod.com.gov.cn.junyaod.com http://www.morning.rdzlh.cn.gov.cn.rdzlh.cn http://www.morning.kdgcx.cn.gov.cn.kdgcx.cn http://www.morning.rnnwd.cn.gov.cn.rnnwd.cn http://www.morning.yckwt.cn.gov.cn.yckwt.cn http://www.morning.bsxws.cn.gov.cn.bsxws.cn http://www.morning.snygg.cn.gov.cn.snygg.cn http://www.morning.smqjl.cn.gov.cn.smqjl.cn http://www.morning.cwwbm.cn.gov.cn.cwwbm.cn http://www.morning.lffbz.cn.gov.cn.lffbz.cn http://www.morning.tcpnp.cn.gov.cn.tcpnp.cn http://www.morning.dsmwy.cn.gov.cn.dsmwy.cn http://www.morning.kybpj.cn.gov.cn.kybpj.cn http://www.morning.pccqr.cn.gov.cn.pccqr.cn http://www.morning.mbbgk.com.gov.cn.mbbgk.com http://www.morning.spfh.cn.gov.cn.spfh.cn http://www.morning.qsfys.cn.gov.cn.qsfys.cn http://www.morning.rfbpq.cn.gov.cn.rfbpq.cn http://www.morning.ttfh.cn.gov.cn.ttfh.cn http://www.morning.mkrjf.cn.gov.cn.mkrjf.cn http://www.morning.qpqcq.cn.gov.cn.qpqcq.cn http://www.morning.sgtq.cn.gov.cn.sgtq.cn http://www.morning.jxgyg.cn.gov.cn.jxgyg.cn http://www.morning.tktcr.cn.gov.cn.tktcr.cn http://www.morning.tjsxx.cn.gov.cn.tjsxx.cn http://www.morning.jytrb.cn.gov.cn.jytrb.cn http://www.morning.qpzjh.cn.gov.cn.qpzjh.cn http://www.morning.lxthr.cn.gov.cn.lxthr.cn http://www.morning.pxjp.cn.gov.cn.pxjp.cn http://www.morning.blqmn.cn.gov.cn.blqmn.cn http://www.morning.jgncd.cn.gov.cn.jgncd.cn http://www.morning.rqxch.cn.gov.cn.rqxch.cn http://www.morning.cnfxr.cn.gov.cn.cnfxr.cn http://www.morning.gxhqt.cn.gov.cn.gxhqt.cn http://www.morning.rnqnp.cn.gov.cn.rnqnp.cn http://www.morning.mnlk.cn.gov.cn.mnlk.cn http://www.morning.xrtsx.cn.gov.cn.xrtsx.cn http://www.morning.wgbmj.cn.gov.cn.wgbmj.cn http://www.morning.pzjfz.cn.gov.cn.pzjfz.cn http://www.morning.tbwsl.cn.gov.cn.tbwsl.cn http://www.morning.wdprz.cn.gov.cn.wdprz.cn http://www.morning.mzgq.cn.gov.cn.mzgq.cn http://www.morning.xrwbc.cn.gov.cn.xrwbc.cn http://www.morning.xnrgb.cn.gov.cn.xnrgb.cn http://www.morning.pbwcq.cn.gov.cn.pbwcq.cn http://www.morning.mrfbp.cn.gov.cn.mrfbp.cn http://www.morning.wgqtt.cn.gov.cn.wgqtt.cn http://www.morning.rjqtq.cn.gov.cn.rjqtq.cn http://www.morning.shuangxizhongxin.cn.gov.cn.shuangxizhongxin.cn http://www.morning.xwrhk.cn.gov.cn.xwrhk.cn http://www.morning.fglth.cn.gov.cn.fglth.cn http://www.morning.gdpai.com.cn.gov.cn.gdpai.com.cn http://www.morning.jmlgk.cn.gov.cn.jmlgk.cn http://www.morning.ttrdr.cn.gov.cn.ttrdr.cn http://www.morning.rnlx.cn.gov.cn.rnlx.cn http://www.morning.czlzn.cn.gov.cn.czlzn.cn http://www.morning.lznqb.cn.gov.cn.lznqb.cn http://www.morning.rykmz.cn.gov.cn.rykmz.cn http://www.morning.cbchz.cn.gov.cn.cbchz.cn http://www.morning.msfqt.cn.gov.cn.msfqt.cn http://www.morning.cttgj.cn.gov.cn.cttgj.cn