结构体:

聚合数据类型是指,能够同时存储超过一个的单独数据,C语言中有两个聚合数据类型,数组和结构体。数组中储存的类型必须相同,元素通过下标和指针引用来访问的。

结构体也是一些值的集合,但是结构体中每个元素的值的类型可以不同,每个元素都有自己的名字,和整数字符一样,结构体也是标量类型

结构体声明:

struct  tag  {  memeber-list   }  variable-list;

结构体声明要包含所有的成员的类型和名字

struct  tag {
  char *name;
  int *age;
} people;

其中,tag时标签字段,可以在后续的声明中使用tag代表成员列表:

struct tag animal;

此处的声明和上面的people一样,animal和people对于编译器来说,是两个不同的类型的。

如果需要定义相同的类型,可以通过typedef来创建新类型:

typedef struct  {
  char *name;
  int *age;
} animal;

现在animal是一新的结构体类型,可以直接使用他进行赋值

animal dog;

结构体的成员:

结构体的成员可以时标量,指针,和其他结构体等等,但是不可以是自身类型的成员,即自己。结构体成员可以通过点号访问

#include <stdio.h>

typedef struct {
char *name;
int age;
} animal; int main()
{
animal dog = { "ted", 3};
printf("%s", dog.name); return 0;
}

运行结果:

如果是指向结构体的指针,可以先解引用操作,然后在使用点操作符,C有个快捷的方法,使用 -> 访问结构体指针指向的结构体成员,上面代码可以如下改写:

animal dog = { "ted", 3};
animal *ptr = &dog;
printf("%s", ptr -> name);

结构体时不可以包含自身类型的成员的,不过可以包含指向自己类型的指针的。

#include <stdio.h>
struct SELF {
char *name;
   //selfPtr是指向自身类型的指针
struct SELF * selfPtr;
} animal; int main()
{
struct SELF dog = { "ted", NULL};
struct SELF cat = {"mimi", &dog}; printf("%s", cat.selfPtr -> name); return 0;
}

运行结果:

注意:下面的这种声明是非法的,因为类型名直到声明结束才定义

typedef struct {
char *name;
struct SELF * selfPtr;
} SELF;

解决方法是添加一个结构标签。

typedef struct SELF {
char *name;
struct SELF * selfPtr;
} animal;

如果两个结构体相互依赖引用,一个结构体包含另一个结构体,另一个结构体包含这个结构体。那么可以使用不完整声明,先声明一个结构体作为标识符,然后使用他,然后把成员和标识符关联。

  //声明表示符,在A中使用
struct B;
struct A {
struct B *bPtr;
}; //关联成员
struct B {
struct A *aPtr;
};

结构体的初始化,类似数组,大括号内部包含逗号分割的初始值,如果初始值列表不够用,剩余的结构成员将使用缺省值初始化。

    struct {
char *name;
int age;
} me = {"yangxunwu", 24};

结构体的储存分配:

由于结构体类别的成员的类型可以不一样,编译器在给成员列表分配内存时,一个接着一个的分配,只有当储存成员需要满足边界对齐时,成员之间会出现储存间隙。系统禁止在一个结构的起始位置跳过几个字节来满足边界对齐要求,因此所有的结构的起始储存位置,必须是边界要求最严格的数据类型所要求的位置,如下:

#include <stdio.h>

int main()
{
struct {
char ch1;
int age;
char ch2;
} stc1; struct {
int age;
     char ch1;
     char ch2;
} stc2; printf("%lu %lu", sizeof(stc1), sizeof(stc2)); return 0;
}

可以通过重新排序成员,让边界对齐要求高的先出现,如上运行:

int类型占四个字节,char占一个字节,因为要从起始位置对齐,所以stc1的第一个char占4字节,而stc2中,age占四个字节,ch1和ch2在一起占四个字节。sizeof可以返回一个long unsigned int表示整个结构体长度。

stddef.h宏 offsetof(type, member) 返回指定成员,距离结构开始偏移几个字节。

 

#include <stdio.h>
#include <stddef.h> int main()
{
struct stc1 {
char ch1;
int age;
char ch2;
} ; struct stc2 {
int age;
char ch1;
char ch2;
} ; printf("%lu %lu", offsetof(struct stc1, ch2), offsetof(struct stc2, ch2)); return 0;
}

 运行:

C和指针 第十章 结构和联合 (一)的更多相关文章

  1. C和指针 第十章 结构和联合 (二)

    结构体传值: 结构体也是标量,像字符和整数一样,可以传递给一个函数,但是传入整个结构体效率很低,可以传入指向结构体的指针来提高效率.如果不希望程序对结构体变量改变可以加入const关键词. typed ...

  2. C和指针 第十章 结构和联合 习题

    1. 记账信息结构联合 typedef struct { unsigned int areaNum; unsigned int transNum; unsigned int station; } ph ...

  3. C的指针疑惑:C和指针10(结构和联合)

    结构也可以作为传递给函数的参数,它们也可以作为返回值从函数返回,相同类型的结构体变量相互之间可以赋值. 申明结构时使用另一种良好技巧是用typedef创建一种新的类型. typedef struct{ ...

  4. C和C指针小记(十五)-结构和联合

    1.结构 1.1 结构声明 在声明结构时,必须列出它包含的所有成员.这个列表包括每个成员的类型和名称. struct tag {member-list} variable-list; 例如 //A s ...

  5. C语言的结构和联合,以及PHP是怎么实现弱类型的

    C语言的结构(struct):包含多个成员,可能有多种数据类型,并且需要分配几种类型占用空间之和的空间. 联合(union):支持多种类型,供使用者使用其中一种数据类型,当然是需要分配其中占用空间最大 ...

  6. 【转】结构struct 联合Union和枚举Enum的细节讨论

    结构struct 联合Union和枚举Enum的细节讨论 联合(Union)是一种构造数据类型,它提供了一种使不同类型数据类型成员之间共享存储空间的方法,同时可以实现不同类型数据成员之间的自动类型转换 ...

  7. C++笔记--指针数组和结构

    指针 类型为T*的变量能保存一个类型T对象的地址 Char c=‘a’:Char * p=& c://保存了c的地址 指针的操作一般都是间接的引用,就是相当于引用指针所指的对象. 0是一个特殊 ...

  8. C语言入门第十章----结构体

    C语言结构体从本质上讲是一种自定义的数据类型,只不过这种数据类型比较复杂,是由int.char .float等基本类型组成的,你可以认为结构体是一种聚合类型. 在实际开发中,我们可以将一组类型不同的. ...

  9. C和指针 (pointers on C)——第十章:结构和联合(下一个)锻炼

    //1.本章只为了刷存在演习.. . typedef struct phone { char * quhao; char * jiaohuantai; char * zhanhaoma; }; typ ...

随机推荐

  1. 使用scrollpagination实现页面底端自动加载无需翻页功能

    当阅读到页面最底端的时候,会自动显示一个"加载中"的功能,并自动从服务器端无刷新的将内容下载到本地浏览器显示. 这样的自动加载功能是如何实现的?jQuery的插件 ScrollPa ...

  2. Apache 配置虚拟主机三种方式

    一.基于IP 1. 假设服务器有个IP地址为192.168.1.10,使用ifconfig在同一个网络接口eth0上绑定3个IP: [root@localhost root]# ifconfig et ...

  3. HTTP状态码对应

    HTTP的状态码 对于状态码大家如果经常在线买东西就能知道,我们买了东西就会有个订单状态:出库.发货中.送达中.送达等,其实这些状态就是状态码,只不过这些状态码都是文字.HTTP 响应的时候也有状态码 ...

  4. BZOJ 1227 【SDOI2009】 虔诚的墓主人

    Description 小W 是一片新造公墓的管理人.公墓可以看成一块 \(N×M\) 的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地.当地的居民都是非常虔诚的基督徒,他们愿意 ...

  5. scp 上传文件到多个服务器节点

    参考:scp批量上传文件到多台机器上(升级版) 实测,代码可运行. 1.如果遇到syntax error near unexpected token问题,基本是由于windows环境下编写的shell ...

  6. Python学习Day2笔记(集合和文件操作)

    1.集合的使用 列表是有序的可包含重复内容的 集合是无序的不可包含重复内容的 1) 集合关系测试 #列表去重list_1=[1,4,5,6,7,8,9,7,5,4,23,2] #有重复数据 list_ ...

  7. cf Round 603

    A.Alternative Thinking(思维) 给出一个01串,你可以取反其中一个连续子串,问取反后的01子串的最长非连续010101串的长度是多少. 我们随便翻一个连续子串,显然翻完之后,对于 ...

  8. [CareerCup] 6.6 Toggle Lockers 切换锁的状态

    6.6 There are 100 closed lockers in a hallway. A man begins by opening all 100 lockers. Next, he clo ...

  9. 调用webapi 错误:使用 HTTP 谓词 POST 向虚拟目录发送了一个请求,而默认文档是不支持 GET 或 HEAD 以外的 HTTP 谓词的静态文件。的解决方案

    第一次调用webapi出错如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http:// ...

  10. C/C++实践笔记 007

    进制输出自己写一个_itoa 进制转换void main(){ int num = 0; scanf("%d", &num); printf("num=%i&qu ...