当前位置: 首页 > 编程笔记 >

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

堵雅健
2023-03-14
本文向大家介绍C语言中结构体struct编写的一些要点解析,包括了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; // 因为 . 的优先级比 * 高,必须要有括号

 类似资料:
  • 本文向大家介绍解析Go语言编程中的struct结构,包括了解析Go语言编程中的struct结构的使用技巧和注意事项,需要的朋友参考一下 struct和C语言的很相似,模拟出class的功能,但是不完全的!没有构造函数等! struct的申明 go指针操作 如下我们要对数值进行改变,先要取内存地址,然后再内存地址上改变他的引用 匿名结构 (1)匿名内部结构的使用 (2)匿名类值不需要数据名称、在赋值

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

  • 主要内容:获取结构体成员,结构体指针作为函数参数当一个 指针变量指向结构体时,我们就称它为 结构体指针。 C语言结构体指针的定义形式一般为: struct 结构体名 *变量名; 下面是一个定义结构体指针的实例: 也可以在定义结构体的同时定义结构体指针: 注意,结构体变量名和数组名不同,数组名在表达式中会被转换为数组指针,而结构体变量名不会,无论在任何表达式中它表示的都是整个集合本身,要想取得结构体变量的地址,必须在前面加 ,所以给 pstu 赋

  • 所谓 结构体数组,是指数组中的每个元素都是一个结构体。在实际应用中, C语言结构体数组常被用来表示一个拥有相同 数据结构的群体,比如一个班的学生、一个车间的职工等。 在C语言中,定义结构体数组和定义结构体变量的方式类似,请看下面的例子: 表示一个班级有5个学生。 结构体数组在定义的同时也可以初始化,例如: 当对数组中全部元素赋值时,也可不给出数组长度,例如: 结构体数组的使用也很简单,例如,获取

  • 在前面我们学习了很多种类的变量,每个变量都会有一种类型。但是如果我们需要定义一个变量,可以同时存储不同的类型的变量,那会在很多场合下很方便的使用。比如我们常见的通信录,里面会包含很多信息,比如姓名,电话号码,邮箱地址等信息。这里面就会涉及到整数,字符串等等。如果每个人建立的时候都分别声明一次其中的变量,那么工作量就会非常的大,也很容易出现错误。 那么怎么解决这种情况呢?这就是今天我们要讲解的内容。

  • 在着色器语言GLSL ES前面内容介绍过浮点数float、整形数int、三维向量vec3、4x4矩阵mat4等各种数据类型,关于结构体主要功能就是利用WebGL着色器已经提供的常见数据类型,自定义一个新的数据类型。 WebGL着色器语言中结构体和C语言类似,结构体是由多个同类或不同类的数据类型构成的一个集合。 // 首先定义一个结构体,也就是自定义一个数据类型 struct Directional