C语言中结构体struct编写的一些要点解析

一、关于结构体的声明
1、匿名声明。如:

struct {
  int i,j;
}point;

说明:
这段代码的含义是,声明一个无名(anonymous)的结构体,并创建了一个结构体变量point。如果这段声明是放在全局域(在任意函数(比如main函数)外)内,那么point内的变量将被初始化为默认值,换句话说,以这种方式声明结构体变量时就已经为它分配了内存空间。
适用于该结构体只需要产生一个变量!本例中,该匿名结构体将有且仅有point这个结构体变量!
不同的匿名结构体变量,类型是不同的!如

struct {
  int i,j;
}p1,p2;

struct {
  int i,j;
}p3;

如果将 p1=p2 ,则ok;如果将 p1=p3 ,则编译器提示"incompatible types when assigning to type ‘struct <anonymous>' from type ‘struct <anonymous>'",两者的实际类型是不一样的。

2、显式声明一个结构体

struct node{
  int i,j;
};

声明了一个结构体 struct node,如果需要声明一个它的对象,则可以这样:struct node n1;
可以声明多个该结构体的变量。
区别"C中的结构体变量" 和 "Java中的类对象"。C中,"struct node n1;"创建了一个结构体变量,并为它分配了内存空间,不一定初始化!得看这个变量是否在全局域;而Java中,"Node n1;"只是声明了一个类对象,也就是说是一个"空引用",可以想象成C中的空指针,当"n1 = new Node();"时,n1才指向了该对象的内存空间。因此,在Java中,可以通过"n1==null"来判断对象是否为空;在C中,不能通过"n1==NULL"来判断,因为"n1"并不是一个指针,而是一个类型变量的名字,就像"int a;"这种,显然"a"不是指针!

3、用typedef来简化结构体的写法

typedefstruct {
  int i,j;
}Node;

相当于把代码改名为Node了。以前需要这样声明"struct node n1;",现在只需要"Node n1;"。
这段代码中,如果没有typedef,代码的意思是"声明了一个匿名结构体变量"!注意区别。
4、在结构体中声明结构体变量。

typedef struct {
  int i,j;
  Node n1;
}Node;

这段代码是错误的!
错误1:直接在结构体中声明另外一个结构体,会出现死循环,如A包括B,B又包括A,A又包括B……使得编译器无法知道结构体的空间大小,因此,无法通过编译!
错误2:typedef还没有将结构体命名为Node,你就在结构体中使用了Node,显然,编译器此时还不知到Node是什么!所以,无法通过编译!
正确的使用方法如下:

typedef struct node{
  int i,j;
  struct node *n1;
}Node;

二、关于结构体的赋值
1、声明一个变量后的默认值

typedef struct {
  char *p;
  int i;
  char ch[256];
}mystr;
mystr str;//声明一个变量,此时已为之分配了空间!

如前面提到的,如果这个变量声明是在全局,则"str.p等于NULL,str.i等于0,str.ch数组都是'\0'",为默认初始值;如果不在全局,则所有值都是"野值"。

2、手动初始化

mystr str2={"abc",2,"def"};
mystr str3={.p="abc",.ch="def"};
mystr str4={.ch[256]="def"};//error!
mystr str5={.ch[10]="def"};//right!

此时,str2声明时手动赋了初值。str2.p和str2.ch赋值时的行为是不一样的!str2.p是一个字符指针,也就是将p指向常量字符串"abc"在内存中的地址;而str2.ch是一个常量字符指针(无法操作指针),代表的是字符数组,也就是将常量字符串"def"逐字符copy到ch数组里,赋值结束后,ch的值是:'d','e','f','\0','\0'……
也可以像str3这样初始化结构体中的某些变量,值得注意的是str4和str5。对于数组(如 char a[size])来说,传递给常量字符指针,可以是"a",可以是"a[n]"(0<=n<size,编译器会忽略掉n),不能是"a[size]"(编译器会检测,报"array index in initializer exceeds array bounds")。

3、赋值

mystr str6;
str6.p = "abc";

或者

mystr * pstr = & str6;//得到这个结构体变量的指针
pstr->p = "abc";

4、动态生成结构体变量

mystr * pstr = (mystr*)malloc(sizeof(mystr));
pstr->p = "abc";

注意,如果是动态生成的结构体变量(用到了malloc),则必须在丢弃该变量前将他的内存空间释放掉(用free)。
如果结构体内部也存在动态生成的对象,在释放结构体之前要先释放掉其内部的内存空间,如下

pstr->p = (char*)malloc(sizeof(char)*256);
free(pstr->p);
free(pstr);

三、结构体数组

我们知道基本数据类型的变量数组直接定义就可以分配空间了,结构体可以看作一种新类型,它也是定义声明变量之后就会自动分配空间的,结构体的数组也是这样。

struct book library[10];

这样就定义了一个有10个book变量的数组,并且已经分配了存储空间。 结构体的数组和普通数组索引方式是一样的。

结构体数组也可以使用字面量初始化方法,如下

struct book lib[2] = {
 {"apue", "stevens", 128.0},
 {"cpp", "prata", 60.0}
};

是不是很方便了。要注意最外面的是 { ,不是 [ 哦。 对于成员是一个结构的结构体变量,同样可以使用字面量初始化,记住,只是初始化,不能用于对结构体变量的赋值哦。

四、指向结构的指针

指向结构体的指针是一个一直都没有掌握好的点,希望这里能记录好一点,加强理解。

对于指针有几个好处,第一:就像指向数组的指针比数组本身更容易操作一样,指向结构的指针通常也更容易操作; 第二:在早期的C中参数传递只能使用结构的指针;第三:很多奇妙的数据表示都是用了包含指向其他结构的指针的结构。

和数组不同,结构的名字不是该结构的地址(即单独的结构名并不是该结构地址的同义词),必须使用 & 运算符。声明一个指针的方式与一个普通变量没有什么区别:

struct book *cpp;
struct book c = {
 "c primer plus",
 "prata",
 60.1
};

cpp = &c;

假设 lib 是一个 struct book 的数组,现在用结构指针 cpp 指向 lib[0],那么根据指针的运算规则, cpp+1 会指向 lib[1]。虽然在一般的认识里面,结构体中的元素在存储器中是一次排列的,所以可以根据各个元素的大小来计算 cpp+1 与 cpp 之间的地址差多少。但是考虑到系统对存储器的对齐要求,不同的系统对齐的方式可能不一样,所以使用各个成员大小相加的方式计算结构的存储大小是不合适的。

五、访问结构的成员

这个比较简单,注意结构和指向机构的指针访问成员的方式不一样,结构本身使用 .运算符访问,而指向结构的指针则使用 -> 访问。

strcut book cpp, *pcpp;
...
char *title;
title = cpp.title;
// title = pcpp->title;
// title = (*pcpp).title; // 因为 . 的优先级比 * 高,必须要有括号
(0)

相关推荐

  • C语言中隐藏结构体的细节

    我们都知道,在C语言中,结构体中的字段都是可以访问的.或者说,在C++ 中,类和结构体的主要区别就是类中成员变量默认为private,而结构体中默认为public.结构体的这一个特性,导致结构体中封装的数据,实际上并没有封装,外界都可以访问结构体重的字段. C++中我们尚可用类来替代结构体,但是,C语言中是没有类的,只能用结构体,但很多时候,我们需要隐藏结构体的字段,不让外界直接访问,而是通过我们写的函数进行间接访问,这样就提高了程序的封装性. 实现方法,简单来说,就是,结构体定义时,要定义在.

  • 浅谈C语言中结构体的初始化

    <代码大全>建议在变量定义的时候进行初始化,但是很多人,特别是新人对结构体或者结构体数组定义是一般不会初始化,或者不知道怎么初始化.1.初始化 复制代码 代码如下: typedef struct _TEST_T {        int i;        char c[10];}TEST_T;TEST_T gst  = {1, "12345"};//可以初始化,设置i为1,s为一个字符串.TEST_T gst  = {1};//初始化个数少于实际个数时,只初始化前面的成员

  • C语言中结构体(struct)的几种初始化方法

    本文给大家总结的struct数据有3种初始化方法 1.顺序 2.C风格的乱序 3.C++风格的乱序 下面通过示例代码详细介绍这三种初始化方法. 1)顺序 这种方法很常见,在一般的介绍C的书中都有介绍.顺序初始化的特点是: 按照成员定义的顺序,从前到后逐个初始化:允许只初始化部分成员:在被初始化的成员之前,不能有未初始化的成员. 示例: struct User oneUser = {10, "Lucy", "/home/Lucy"}; 2)乱序(C风格) 顺序的缺陷是

  • C语言中的结构体的入门学习教程

    C语言中数组允许定义类型的变量,可容纳相同类型的多个数据项,但结构体在C语言编程中,它允许定义不同种类的数据项可供其他用户定义的数据类型. 结构是用来代表一个记录,假设要跟踪图书馆的书籍.可能要跟踪有关每本书以下属性: Title - 标题 Author - 作者 Subject - 科目 Book ID - 编号 定义结构体 定义一个结构体,必须使用结构体的struct语句.该struct语句定义了一个新的数据类型,程序不止一个成员.struct语句的格式是这样的: struct [struc

  • C语言 结构体(Struct)详解及示例代码

    前面的教程中我们讲解了数组(Array),它是一组具有相同类型的数据的集合.但在实际的编程过程中,我们往往还需要一组类型不同的数据,例如对于学生信息登记表,姓名为字符串,学号为整数,年龄为整数,所在的学习小组为字符,成绩为小数,因为数据类型不同,显然不能用一个数组来存放. 在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据.结构体的定义形式为: struct 结构体名{     结构体所包含的变量或数组 }; 结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可

  • php读取二进制流(C语言结构体struct数据文件)的深入解析

    尽管php是用C语言开发的,不过令我不解的是php没有提供对结构体struct的直接支持.不过php提供了pack和unpack函数,用来进行二进制数据(binary data)和php内部数据的互转: 复制代码 代码如下: string pack ( string $format [, mixed $args [, mixed $...]] )   //Pack given arguments into binary string according to format.  array unp

  • 深入分析C语言中结构体指针的定义与引用详解

    指向结构体类型变量的使用首先让我们定义结构体:struct stu{char name[20];long number;float score[4];} ;再定义指向结构体类型变量的指针变量:struct stu *p1, *p2 ;定义指针变量p 1.p 2,分别指向结构体类型变量.引用形式为:指针变量→成员:[例7-2] 对指向结构体类型变量的正确使用.输入一个结构体类型变量的成员,并输出. 复制代码 代码如下: #include <stdlib.h> /*使用m a l l o c (

  • 详解C语言中结构体的自引用和相互引用

    结构体的自引用(self reference),就是在结构体内部,包含指向自身类型结构体的指针. 结构体的相互引用(mutual reference),就是说在多个结构体中,都包含指向其他结构体的指针. 1. 自引用 结构体 1.1 不使用typedef时 错误的方式: struct tag_1{ struct tag_1 A; /* 结构体 */ int value; }; 这种声明是错误的,因为这种声明实际上是一个无限循环,成员b是一个结构体,b的内部还会有成员是结构体,依次下去,无线循环.

  • C语言中结构体struct编写的一些要点解析

    一.关于结构体的声明 1.匿名声明.如: struct { int i,j; }point; 说明: 这段代码的含义是,声明一个无名(anonymous)的结构体,并创建了一个结构体变量point.如果这段声明是放在全局域(在任意函数(比如main函数)外)内,那么point内的变量将被初始化为默认值,换句话说,以这种方式声明结构体变量时就已经为它分配了内存空间. 适用于该结构体只需要产生一个变量!本例中,该匿名结构体将有且仅有point这个结构体变量! 不同的匿名结构体变量,类型是不同的!如

  • 详解C语言中结构体(struct)的用法

    目录 粉丝问答 三种结构体类型变量说明 1. 先定义结构,再定义结构变量 2. 定义结构体类型的同时说明变量 3. 直接说明结构变量 结构体成员表示方法 结构体指针做参数 结构体初始化 定义变量的同时初始化 先定义在初始化 常用初始化 typedef与struct 前置声明 结构体对齐 粉丝问答 有个粉丝在群里问了这样一个问题,问题在图中已经标出,如下图. DQuestsion 头文件的结构体的定义为: typedef struct{ u8 bmRequestType; u8 bRequest;

  • 解析C语言中结构体struct的对齐问题

    首先看一下结构体对齐的三个概念值: 数据类型的默认对齐值(自身对齐): 1.基本数据类型:为指定平台上基本类型的长度.如在32位机器中,char对齐值为1,short为2,int,float为4,double为8: 结构体:其数据成员中默认对齐值最大的那个值. 2.指定对齐值:#pragma pack (value)时的指定对齐值value. 3.数据类型的有效对齐值:默认对齐值和指定对齐值中小的那个值. 有了这些值,我们就可以很方便的来讨论具体数据结构的成员和其自身的对齐方式.有效对齐值N是最

  • C语言中结构体和共用体实例教程

    目录 一.实验目的 二.实验内容 三.实验记录 3.1 候选人选票统计 3.2 print函数 3.3 链表 总结 一.实验目的 掌握结构体类型变量的定义和使用: 掌握结构体类型数组的概念和应用: 掌握链表的概念,初步学会对链表进行操作: 掌握共用体的概念与使用: 掌握指向结构体变量的指针. 掌握指向结构体数组的指针的应用. 二.实验内容 编写下列程序,然后上机调试运行. 对候选人得票的统计程序.设有3个候选人,每次输入一个得票的候选人的名字,要求最后输出各人得票结果. 编写一个函数print,

  • 详解C语言中结构体的使用

    目录 结构体的声明 结构体成员的类型 结构体成员的访问 结构体的声明 结构体的定义:结构体是一些值的集合,这些值称为成员变量,结构体的每个成员可以是不同类型的变量. 举例: //定义结构体类型 struct tag//struct结构体关键字 tag结构体标签 struct tag结构体类型 { //成员变量 char name[20]; short age; char telphone[12]; char sex[5]; }s1,s2,s3;//s1,s2,s3是三个全局结构体变量 int m

  • Go语言中结构体方法副本传参与指针传参的区别介绍

    GO语言结构体方法跟结构体指针方法的区别 首先,我定了三个接口.一个结构和三个方法: type DeptModeA interface { Name() string SetName(name string) } type DeptModeB interface { Relocate(building string, floor uint8) } type Dept struct { name string building string floor uint8 Key string } fun

  • C语言中结构体、联合体的成员内存对齐情况

    前言 最近项目进行中,遇到一个小问题,在数据协议传输过程中,我为了方便解析,就定义了一个结构体,在数据的指针传入函数的时候,我用定义好的结构体进行强制转化,没想到一直解析失败,调试很久,终于反应过来,在用结构体指针对数据强制转换时,定义结构体我没有注意到数据对齐,因为在底层实现中,我传入的数据buffer是排列整齐的,而强制转化的结构体格式中,我定义的时候没有使用__attribute__((__packed__))或者__packed强制数据对齐,导致结构体成员真实排列会按照成员中最大的变量的

  • C语言中结构体与内存对齐实例解析

    1.结构体类型 C语言中的2种类型:原生类型和自定义类型,结构体类型是一种自定义类型. 2.结构体使用时先定义结构体类型再用类型定义变量 -> 结构体定义时需要先定义结构体类型,然后再用类型来定义变量. -> 也可以在定义结构体类型的同时定义结构体变量. // 定义类型 struct people { char name[20]; int age; }; // 定义类型的同时定义变量. struct student { char name[20]; int age; }s1; // 将类型st

  • C语言中结构体实例解析

    目录 一.结构体定义 二.实例演示 结构体作为函数参数 结构体指针 三.typedef struct 和 struct的区别 1.声明不同 2.访问成员变量不同 3.重新定义不同 总结 一.结构体定义 C语言结构体由一系列相同或者不同类型的数据构成的集合,结构体类型就是以struct关键字定义的数据类型. 结构体的格式如下: struct 结构名称 { 结构体所包含的数据成员,包括变量数组等 } 结构变量 ;//结构变量可以指定一个或多个 举例: struct Student { char na

随机推荐