先回顾一个基础的知识,不同类型的数据在16位,32位,64位的机器分别占用多少字节。

类型 16位机器(字节) 32位机器(字节) 64位机器(字节)
char 1 1 1
short 2 2 2
int 2 4 4
unsigned int 2 4 4
float 4 4 4
double 8 8 8
long 4 4 4(win) / 8(linux)
long long 8 8 8
unsigned long 4 4 8
指针 2 4 8

可以看到long类型的数据比较特殊,在写跨平台的应用时需要注意,最好是避免使用

定义两个结构体

typedef struct _demo_node_{
struct _demo_node_* pprenode;
struct _demo_node_* pnextnode;
unsigned long member_num;
unsigned short age;
char addr[0];
}demo_node; typedef struct {
char province[8];
char city[8];
}address_info;

写程序来验证一下,结构体本身的地址,以及它包含的成员的地址,有什么样的联系

#include <stdio.h>
#include <malloc.h>
#include <string.h> typedef struct _demo_node_{
struct _demo_node_* pprenode;
struct _demo_node_* pnextnode;
unsigned long member_num;
unsigned short age;
char addr[0];
}demo_node; typedef struct {
char province[8];
char city[8];
}address_info; int main(void)
{
demo_node* person = NULL;
person = (demo_node*)malloc(sizeof(demo_node)+sizeof(address_info));
if(NULL == person)
{
printf("malloc demo_node failed\n\r");
return -1;
} printf("person结构体的地址 = 0x%0x\n",person);
printf("person->pprenode的地址 = 0x%0x\n",&(person->pprenode));
printf("person->pnextnode的地址 = 0x%0x\n", &(person->pnextnode));
printf("person->member_num的地址 = 0x%0x\n", &(person->member_num));
printf("person->age的地址 = 0x%0x\n", &(person->age));
printf("person->addr的地址 = 0x%0x\n", &(person->addr)); free(person);
return 0;
}

采用windows的64位编译器编译,程序输出的结果为

person结构体的地址 = 0x1f1420
person->pprenode的地址 = 0x1f1420
person->pnextnode的地址 = 0x1f1428
person->member_num的地址 = 0x1f1430
person->age的地址 = 0x1f1434
person->addr的地址 = 0x1f1436

我们来分析一下为什么是这样的结果:

  1. 结构体指针person的地址,与它指向的结构体的第一个成员(person->pprenode)地址是一样的,都是0x1f1420

  2. pprenodepnextnode都是指针变量,由于指针变量在64位机器中占8个字节,所以

    person->pnextnode的地址 = 8 + person->pprenode的地址 = 0x1f1428

    person->member_num的地址 = 8 + person->pnextnode的地址 = 0x1f1430

  3. member_num是unsigned long类型的变量,在windows的64位机器中占4个字节,所以person->age的地址 = 4 + person->member_num的地址 = 0x1f1434

  4. age是unsigned short类型的变量,可以等同于short占用的字节,都是2,所以person->addr的地址 = 2 + person->age的地址 = 0x1f1436

关于结构体成员地址,就简单介绍到这里了!

细心的同学一定发现了demo_node 结构体中char addr[0] 这个成员,这其实是个占位符,至于它的用法,可以看我的另一篇文章《C语言,变长数组的用法》,还是在这个示例代码的基础上进行介绍,方便快速理解。

C语言,结构体成员的地址的更多相关文章

  1. 3.c语言结构体成员内存对齐详解

    一.关键一点 最关键的一点:结构体在内存中是一个矩形,而不是一个不规则形状 二.编程实战 #include <stdlib.h> #include <stdio.h> stru ...

  2. 【C/C++编程入门学习】C语言结构体硬核玩法分享,一切皆是数据!

    前言 对于结构体的应用太多了,今天这篇文章我主要为大家总结平时关于结构体的一些独特硬核小技巧,对于结构体更多优秀的编程表现,如果你对结构体的基础知识还不具备的话得回头看一下专栏教程或者自己找本书籍学习 ...

  3. C语言结构体的字节对齐原则

    为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据 ...

  4. 关于C语言中结构体中的结构体成员导致的字节对齐问题

    关于结构体的字节对齐是什么,就不赘述,再此附上一篇文章,介绍字节对齐:http://www.linuxsong.org/2010/09/c-byte-alignment/ 这里的结构体字节对齐的数据类 ...

  5. 读陈浩的《C语言结构体里的成员数组和指针》总结,零长度数组

    原文链接:C语言结构体里的成员数组和指针 复制例如以下: 单看这文章的标题,你可能会认为好像没什么意思.你先别下这个结论,相信这篇文章会对你理解C语言有帮助.这篇文章产生的背景是在微博上,看到@Lar ...

  6. 怎样求结构体成员的偏移地址 || 结构体的 sizeof 总结

    C 语言中同意将值为 0 的变量强制转换成任一类型的指针,转换结果是一个NULL指针. (type*)0 // 一个 type 类型的NULL指针 用这个指针訪问结构体内的成员是非法的,可是 & ...

  7. 【C语言】这种求结构体成员大小的方法,你可能需要了解一下~

    在C语言编程中,有时候需要知道某结构体中某成员的大小,比如使用堆内存来存储结构体中的某成员时,需要知道该成员的大小,才好确定所需申请的空间大小.求某结构体中某成员的大小,你会怎么做? 例子: type ...

  8. C语言结构体里的成员数组和指针

    struct test{ int i; char *p; }; struct test *str; ; char *b = "ioiodddddddddddd"; str = (s ...

  9. C语言结构体变量内存分配与地址对齐

    地址对齐简单来说就是为了提高访问内存的速度. 数组的地址分配比较简单,由于数据类型相同,地址对齐是一件自然而然的事情. 结构体由于存在不同基本数据类型的组合,所以地址对齐存在不同情况,但总体来说有以下 ...

  10. 在C语言结构体中添加成员函数

    我们在使用C语言的结构体时,经常都是只定义几个成员变量,而学过面向对象的人应该知道,我们定义类时,不只是定义了成员变量,还定义了成员方法,而类的结构和结构体非常的相似,所以,为什么不想想如何在C语言结 ...

随机推荐

  1. 30-组合可编程逻辑器件-PLD

    组合可编程逻辑器件 1.PLD的结构 1.1 结构 1.2 表示方法 实心点表示连接,但是不可编程 ×点表示连接,但是可以编程 2.编程技术 2.1 熔丝工艺 每个输入线连接二极管和保险丝 2.2 电 ...

  2. Laravel - 改为国内镜像

    composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/    (阿里云) 或 composer ...

  3. [转帖]oracle ZHS16GBK的数据库导入到字符集为AL32UTF8的数据库(转载+自己经验总结)

    字符集子集向其超集转换是可行的,如此例 ZHS16GBK转换为AL32UTF8. 导出使用的字符集将会记录在导出文件中,当文件导入时,将会检查导出时使用的字符集设置,如果这个字符集不同于导入客户端的N ...

  4. [转帖]如何查看Docker容器环境变量,如何向容器传递环境变量

    https://www.cnblogs.com/larrydpk/p/13437535.html 1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! 了解Docker容器的运行 ...

  5. 不同数据库创建用户,数据库的SQL语句整理

    不同数据库创建用户,数据库的SQL语句整理 MySQL mysql -uroot -p # 输入密码登录数据库 CREATE DATABASE IF NOT EXISTS xxxdata_somein ...

  6. Intel 移动CPU天梯榜

    Intel酷睿i9-13980HX 2023 2121 Intel酷睿i9-13900HX 2023 2051 Intel酷睿i9-13950HX 2023 2005 4 + Intel酷睿i9-12 ...

  7. [转帖]RHEL/CentOS 7的systemd target及其中的multi-user.target

    在RHEL/CentOS 6中,使用SysV init和Upstart,通过预定义一组Runlevels(从0到6)表示不同的执行模式. [root@myhost app]# ll /etc/rc.d ...

  8. [转帖]Grafana+influxdb+ntopng简易网络流量分析展示系统

    Grafana逼格高,所以用它展示ntopng的数据 >_< 一,ntopng 根据官网资料 https://www.ntop.org/ntop/ntopng-influxdb-and-g ...

  9. 【转帖】一道面试题:JVM老年代空间担保机制

    面试问题 昨天面试的时候,面试官问的问题: 什么是老年代空间担保机制?担保的过程是什么? 老年代空间担保机制是谁给谁担保? 为什么要有老年代空间担保机制?或者说空间担保机制的目的是什么? 如果没有老年 ...

  10. [转帖]Linux磁盘I/O(二):使用vm.dirty_ratio和vm.dirty_background_ratio优化磁盘性能

    文件缓存是一项重要的性能改进,在大多数情况下,读缓存在绝大多数情况下是有益无害的(程序可以直接从RAM中读取数据).写缓存比较复杂,Linux内核将磁盘写入缓存,过段时间再异步将它们刷新到磁盘.这对加 ...