结构体中的成员项的存储地址是连续的吗?

辨不清方向的小南瓜 2013-10-20 10:39:12
课本上的一个例子:
#include <stdio.h>
struct Key //定义一个结构
{
char *keyword;
int keyno;
};
void main()
{
//定义一个结构数组
struct Key kd[]={{"are",123},{"my",456},{"you",789}};
struct Key *p; //定义一个结构指针变量
int a;
char chr;

p=kd; //将结构数组的首地址赋给结构指针p
a=p->keyno;
printf("p=%d,a=%d\n",p,a);

a=++p->keyno; //相当于chr=++(p->keyno),结构指针无变化
printf("p=%d,a=%d\n",p,a);

/*结构指针指向结构数组的下一个元素,结构指针发生变化;给a赋值的是指针变化后所指向目标的成员数据*/
a=(++p)->keyno;
printf("p=%d,a=%d\n",p,a);
}


程序运行结果:
p=158,a=123
p=158,a=124
p=162,a=456

程序中:kd[]的首地址是158,a为什么会是123?
当指针p=162后,a又为什么会变成456?
...全文
2709 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2013-10-21
  • 打赏
  • 举报
回复
#include <stdio.h>
#define field_offset(s,f) (int)(&(((struct s *)(0))->f))
struct AD  { int a; char b[13]; double c;};
#pragma pack(push)
#pragma pack(1)
struct A1  { int a; char b[13]; double c;};
#pragma pack(2)
struct A2  { int a; char b[13]; double c;};
#pragma pack(4)
struct A4  { int a; char b[13]; double c;};
#pragma pack(8)
struct A8  { int a; char b[13]; double c;};
#pragma pack(16)
struct A16 { int a; char b[13]; double c;};
#pragma pack(pop)
int main() {
    printf("AD.a %d\n",field_offset(AD,a));
    printf("AD.b %d\n",field_offset(AD,b));
    printf("AD.c %d\n",field_offset(AD,c));
    printf("\n");
    printf("A1.a %d\n",field_offset(A1,a));
    printf("A1.b %d\n",field_offset(A1,b));
    printf("A1.c %d\n",field_offset(A1,c));
    printf("\n");
    printf("A2.a %d\n",field_offset(A2,a));
    printf("A2.b %d\n",field_offset(A2,b));
    printf("A2.c %d\n",field_offset(A2,c));
    printf("\n");
    printf("A4.a %d\n",field_offset(A4,a));
    printf("A4.b %d\n",field_offset(A4,b));
    printf("A4.c %d\n",field_offset(A4,c));
    printf("\n");
    printf("A8.a %d\n",field_offset(A8,a));
    printf("A8.b %d\n",field_offset(A8,b));
    printf("A8.c %d\n",field_offset(A8,c));
    printf("\n");
    printf("A16.a %d\n",field_offset(A16,a));
    printf("A16.b %d\n",field_offset(A16,b));
    printf("A16.c %d\n",field_offset(A16,c));
    printf("\n");
    return 0;
}
//AD.a 0
//AD.b 4
//AD.c 24
//
//A1.a 0
//A1.b 4
//A1.c 17
//
//A2.a 0
//A2.b 4
//A2.c 18
//
//A4.a 0
//A4.b 4
//A4.c 20
//
//A8.a 0
//A8.b 4
//A8.c 24
//
//A16.a 0
//A16.b 4
//A16.c 24
//
//
自信男孩 2013-10-21
  • 打赏
  • 举报
回复
是连续的,起码我们看到的虚拟地址是连续的哦。
做或不做 2013-10-21
  • 打赏
  • 举报
回复
根据编译 和机器的不同 采取的对齐方式可能会有偏差 结果也会有一定出入 存在4字节对齐 和机器对齐吧 估计我已经忘了
modyaj 2013-10-21
  • 打赏
  • 举报
回复
应该是尽量 但不是一定
lin5161678 2013-10-21
  • 打赏
  • 举报
回复
不保证连续
秃头披风侠 2013-10-21
  • 打赏
  • 举报
回复
这和结构对齐没什么关系吧, 结构Key本身是对齐的(4byte的指针和4byte的int), 就是指针偏移(指针步长)的问题.
AnYidan 2013-10-21
  • 打赏
  • 举报
回复
地址是连续的,但其中可能有因为对齐而插入的padding
zhao 2013-10-21
  • 打赏
  • 举报
回复 1
我实在不知道楼主的结果怎么来的!楼主你自己发明创造的吧

程序运行结果:
 p=158,a=123
 p=158,a=124
 p=162,a=456
p还可能等于158,162?还能搞出158这么低的地址来这是低端内存,而你所有的东西是在栈空间的。另外万一中的万一p真的了158了,++p之后p就加4?这可是指针运算啊p + 1等价于((unsigned int p) + sizeof (*p))而sizeof(*p)是多大,还真不好说,默认情况下32位机应该为8,64位机上为16(至于为什么是8或16建议楼主查一下字节对齐)。但是无论任何情况下也不可能等于4。 至于你说a为什么是123和456,p指向了kd[0] p->kveno不就是对其取值吗?不是kd[0].kveno = 123吗? a=++p->keyno 首先p指向了kd【1】.之后。。。 楼主基础真的很薄弱,不要崇拜什么大神!程序要多调多想,多练
Shadow0418 2013-10-20
  • 打赏
  • 举报
回复
p=kd; 相当于p指向了数组里面的第一个元素 a=p->keyno; 取出数组第一个元素里面的整型元素赋值给a,所以a=123 a=(++p)->keyno;指针指向数组里的第二个元素,取出第二个元素里的整型元素a,所以a=456 我用的是gcc编译器。。。p的结果和你的不一样。。
桃大大 2013-10-20
  • 打赏
  • 举报
回复
因为涉及到对齐。所以地址加了8,当然就指向第二个结构体
  • 打赏
  • 举报
回复
成员按照定义时的顺序依次存储在连续的内存空间。但并不是像数组那样的连续 struct stu3   {   char c1;//偏移量为0符合要求   int i;//偏移量为4, 结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍),   char c2;//偏移量为8(偏移量4+int大2小4),符合要求   }
桃大大 2013-10-20
  • 打赏
  • 举报
回复
p是地址 a=p->keyno; a是指向其中的成员 也就是第一个结构体的第二个成员也就是123
  • 打赏
  • 举报
回复
没有大神解释一下吗?
第十二章 自定义数据类型 12.1 结构体 结构体(structure)又叫结构,是一种构造类型,由若干成员构成,成员可以是一个基本数据类型或一个构造类型。 12.1.1 结构体声明 声明结构体的形式: struct 结构名 { 成员表列; }; 成员表列由若干个成员组成,每个成员必须做类型说明,形式为: 类型说明符 成员名; 例1:声明学生结构: struct student { int iNum; char cArrName[20]; char cSex; float fScore; }; 注意不要忘记}后的分号(;)。 成员名可与程序其他变量同名,互不干扰。 结构体声明并不分配空间,结构体声明是在说明一种数据类型,不是变量定义。例1结构体student与int、float一样都是数据类型。 声明结构体后可定义结构体变量,这时分配空间。 12.1.2 结构体变量定义 声明结构体后可以定义结构体变量。 定义方法: a.先声明结构体,再定义结构体变量 struct student { int iNum; char cArrName[20]; char cSex; float fScore; }; struct student stu1,stu2; 可以用宏定义使用一个符号常量表示一个结构体类型。 b.在声明结构体同时定义结构体变量 struct student { int iNum; char cArrName[20]; char cSex; float fScore; }stu1,stu2; c.直接定义结构体变量 struct { int iNum; char cArrName[20]; char cSex; float fScore; }stu1,stu2; 第三种与第二种区别在于省去了结构体类型名,而直接给出结构体变量。这种方法结构体只能用一次,即使再声明成员完全相同的结构体类型,也和此次定义的结构体类型属于不同的结构体类型。 结构体变量在内存空间连续存储的,结构体类型大小为sizeof(struct student),为各成员大小之和,各编译系统为内存管理方便可能分配大一些的内存空间来存储结构体,保证字节对齐。在Dev上述结构体类型student为32字节。 结构体成员可以又是一个结构体,即构成嵌套的结构体。如: struct date { int year; int month; int day; }; struct student { int iNum; char cArrName[20]; char cSex; float fScore; struct date birthday; }; 12.1.3 结构体变量引用 1.结构变量初始化

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧