程序机器级表示之数据

数组

基本原则

1、声明一个数据类型为T,程度为N的数组A ,T A[N]。这句语句的意思为在存储器中分配N*sizeof(T)个字节的存储空间,其中A为指向该存储空间的首地址,在Ubantu下用 p A打印指令,可以看出A存储的是一个地址。
下面来看看几个数组的声明:
char A[12]
char *B[4]
int C[8]
int * D[8]

数组元素大小
A1字节
B4字节
C4字节
D4字节

*这里是32位机上的结果,对于指针数组的元素,其存的是地址,为32位,大小为4字节。对于64位机,则是8字节。

元素访问

返回a数组中的下标index的元素

// 访问数组内的元素
int get_elemen(a,int index){
   return a[index];
}

IA32的汇编代码

%edx = a;
%eax = index;
movl (%edx,%eax,4),%eax //取a[index]放入eax

edx存储数组首地址,eax存储下标值,访问数据的地址为4%eax+%edx,然后利用内存寻址方式取值。

二维数组

T A[R][C] 数据类型T,R行,C列
数组大小:R* C * K 个字节。K为每个元素的大小
排列方式:以行优先

元素访问

A[i][j]的地址为:A+C * K * i + j *K

嵌套数组

跟二维数据类似,只不过访问二维数组只需要访问一次内存,而嵌套数组要先访问存储地址的数组,然后根据地址访问数据所在的内存,一共访问了两次内存,其优点是灵活性强。
在这里插入图片描述

结构体

C语言中的结构体
struct r{
 int a[3];
 int i;
 struct r *n; //指向结构体的指针
}

1、分配的内存连续
2、可以通过结构体名字和成员名字访问相应的数据。例如.,->
3、可包含不同数据类型的数据

数据访问

rec ->a 或 rec.a
*一般->用于指针运算

IA32机器表示

C代码

void set(struct r *rec,int value){
      rec->i = value;
}

汇编

%edx=value;
%eax = rec;
movl %edx,12(%eax)
  • i是结构体中的第2个元素,前面的a数组占了3*4=12个字节,所以i的地址为rec+12。
结构与对齐

结构体内分配的内存的大小是最大数据类型大小的整数倍。并且,每个数据类型都有自己的对齐规则,即自身类型的大小的整数倍。如下:
char类型:没有限制
short类型:地址位的低两位是(00)2,即偶数地址对齐。
int、float、char*:4的倍数地址边界对齐
double:(Linux是4的倍数地址边界对齐,Windows和绝大多数为8的倍数的地址边界对齐)
long double:12的倍数的地址边界对齐

  • 对齐提高了存储器系统的性能。
    举个例子:对于下面的结构体
struct r{
char c;
int i[2];
double v;
} *p

没有对齐的内存分配:
在这里插入图片描述
对齐后:
在这里插入图片描述

  • 这里的数据类型的最大长度为8字节,所以整个长度为8的整数倍。
  • 为了节省空间,把长度大的数据类型放在前面,可减少因对齐额外分配内存。

联合体(Union)

内存分配

联合体的定义跟结构体语法一样,但其分配内存是根据最大长度元素的长度分配内存空间,而且每个成员共享这一块内存。

struct r{
char c;
int i[2];
double v;
} *p

在这里插入图片描述

union r{
char c;
int i[2];
double v;
} *p

在这里插入图片描述

字节顺序

联合体可用来判断机器的大端、小端表示法。
下面是在Ubantu下进行演示

#include<stdio.h>
#include<stdlib.h>

int
main(int argc, char **argv)
{
    union {
        short  s;
        char   c[sizeof(short)];
    } un;

    un.s = 0x0102;
    if (sizeof(short) == 2) {
    if (un.c[0] == 1 && un.c[1] == 2)
        printf("大端法\n");
    else if (un.c[0] == 2 && un.c[1] == 1)
        printf("小端法\n");
    else
        printf("不能判断\n");
    } else
    printf("sizeof(short) = %d\n", sizeof(short));

    exit(0);
}


小端:低位存储在低位,高位存储在高位。0x0102,0x02是低位,存储在低地址,0x01存储在高地址。
大端:与小端相反
可以看出32位Linux系统下数据的存储方式是小端法。

  • 本片博客是我拿来复习用的,因为也才刚刚入手,如有描述不对的地方,还请各位多加指正。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

J.K.Roling

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值