广告

原创 关于C51求数组字节数量的详解(sizeof的详解)

2010-2-6 11:09 5106 0 分类: MCU/ 嵌入式

看了网络上一些关于sizeof的用法,觉得都没有针对C51内的详细说明,在此进行详细解释,以便供大家参考:

例如数组:

 unsigned char code parameter_table[] =
 {
          1,2,3,4,5,6,7,8,   //password_addr
 };

关于数组parameter_table[] 的字节长度计算分析如下:

首先,定义宏定义:#define countof(a)   (sizeof(a) / sizeof(*(a)))


//sizeof(a) = 数组字节长度(例子为8)
//sizeof(*(a)) = 数组变量类型(char = 1、int = 2(例子为1))
//数组长度=sizeof(数组)/sizeof(*数组)
//数组长度=sizeof(数组)/sizeof(*数组) (数组内为纯数字) 
//数组长度=sizeof(数组)-1/sizeof(*数组) (数组内为纯字符或者数字数组混和)

例:unsigned char code parameter_tab[] =
 {
  1,2,3,4,5,6,7,8,"ab"  //password_addr
 }; 

 

最后,那么调用宏定义,即可得出该数组内的字节数量:
#define WriteBufferSize   (countof(parameter_tab))

WriteBufferSize就等于该数组内的字节数量。



另外的一些资料:

问题即:int length(int ar[]);只给出数组首地址,返回该数组的长度
C语言中对数组的操作不太灵活,而数组操作又是不可或缺的

计算内存容量
用运算符sizeof可以计算出数组的容量(字节数)。示例7-3-3(a)中,sizeof(a)的值是12(注意别忘了’\0’)。指针p指向a,但是sizeof(p)的值却是4。这是因为sizeof(p)得到的是一个指针变量的字节数,相当于sizeof(char*),而不是p所指的内存容量。C++/C语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。

注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。示例7-3-3(b)中,不论数组a的容量是多少,sizeof(a)始终等于sizeof(char *)。

char a[] = "hello world";
char *p  = a;
cout<< sizeof(a) << endl;// 12字节
cout<< sizeof(p) << endl;// 4字节
示例7-3-3(a) 计算数组和指针的内存容量

void Func(char a[100])
{
cout<< sizeof(a) << endl;// 4字节而不是100字节
}
示例7-3-3(b) 数组退化为指针

只能把数组的长度作为参数传递。

当然也可以这样:
#include "stdio.h"

typedef struct array_box
{
    int array[10];
}ARRAY_BOX;

void getData(ARRAY_BOX * arrayBox_p)
{
    int count = sizeof(arrayBox_p->array) / sizeof(int);
    int i;
    for (i = 0; i < count; i++)
    {
        arrayBox_p->array = i;
    }
}

main()
{
    ARRAY_BOX arrayBox;
    getData(&arrayBox);
}

做一个只有一个类型为数组的元素的结构体,相当于把数组用一个box包起来,占用的内存空间相同,但是可以达到楼主想要得效果。

至于想要知道数组实际使用长度,那真是没有任何办法了,只有自己数吧~~

1 C风格数组在定义时可以通过sizeof计算出大小,如:

#define AR_SIZE( a ) sizeof( a ) / sizeof( a[0] )

char str[] = "Some thing for test";
int a[] = { 1, 3, 4 };
int b[20];

AR_SIZE( str );  //20
AR_SIZE( a );  //3
AR_SIZE( b );  //20

注意,sizeof是编译器间静态求值的。他必须知道对象的准确类型。


2 数组作为函数参数,作用类似指针。 函数只传递一个4字节的地址,而没有其大小信息。

楼上 JustNewBie(懒惰+骄傲+不耐心!) 做法是错误的。

int length(int ar[])
{
  sizeof ar; // 永远是4(当然,在16位编译器下是2 )
}

3 C99支持动态数组,你可以查查资料,似乎有支持自动指定大小——但是目前支持C99的编译器很少,我没有试过。

不可能有办法的。
当你定义一个数组的时候:
int a[] = {1, 2, 3};  // 实际上被编译为 int a[3] = {1,2,3}

数组名代表的是数组的地址。注意 —— 你绝对没有办法通过数组名动态获得数组的大小。当你丢失a的长度信息的时候,你永远不可能知道他的长度。

那么 sizeof 是怎么回事呢?他不是通过 a 的名字获得 a的大小了么? —— 大错特错!

关键字 sizeof 产生的是一个编译期常量(注1) 他的运作方式是这样的:

当你写:
sizeof a 
实质是:
sizeof ( a的类型 )

而a的类型是什么呢?编译器察看 a的定义发现, 是 int [3]
就是说,这里 sizeof a 实质是:
sizeof ( int[3] )
完全等同于常量 12 (假定int为4字节)。


考虑一个函数
void func( int a[] );  
// 写成 int a[3] 也不会有本质区别——也许你该试试写成 int (&a) [3] ?

C++规定,数组作为形参的时候,a代表数组首地址。
他的底层意义是: a 退化为了一个4字节的指针,没有任何变量表示数组的大小会“自动”被传递进来。

我们看看这个时候 sizeof a是什么:
sizeof( 函数形参的a[] )  = sizeof( int* const ) = 4  // 当然a[]不是合法的C++类型

仍然不服气?好——我们反问一个问题:若你是C /C++的设计者, 你怎么在兼容原有设计的基础上让void func( int a[] )同时传递地址和大小?

首先,a是一个变量,而且类似数组。他必须是一个地址,否则你不知道如何索引元素。
他怎么再带上一个变量表示他的大小呢?

扩充 sizeof (a) 的能力?

sizeof a 必须产生代码——不管是常量还是什么。 要让他在运行时决定 a的值, a就必须带上他的大小信息。

1 你必须修改C标准,让C支持“两种”数组。一种是定义处的数组,他分配大片连续内存,和原来的C标准相同。

2 另一种是作为参数传递数组。 你必须传递地址和数组大小;这个数组实际上是一个8字节的结构{ 地址; 大小}(事实上可能更加复杂,考虑多纬数组如何实现? )

3 系统必须根据两种不同数组分别实现其 []、* 、&等。 原有的数组根据其首地址偏移(这是个常量)和下标寻址; 而参数数组则首先取“地址”内容(这是个变量),然后根据这个地址寻址....

厄... 再考虑多维数组——听起来这不是一整套vector模型么?

-----------------------------------------------
注1: 对于C99支持的 flexible array ,其 sizeof 运算是运行时求值 






广告

文章评论 0条评论)

登录后参与讨论
相关推荐阅读
zxzxy1988 2010-03-03 18:23
广告贴
发个广告哈,呵呵http://bbs.cnttr.cn/?fromuid=469963主要是需要流量来下一本书...汗终于发了一个原创帖了...
zxzxy1988 2010-01-04 11:12
全地址译码、部分地址译码和线性选择译码
5.5.2 存储器芯片与CPU的连接  存储器芯片的外部引脚按功能分为数据线(DB)、地址线(AB)和控制线(CB)。CPU对存储器的读写操作首先是向其地址线发地址信号,然后向控制线发读写控制信号,最...
zxzxy1988 2009-12-31 16:44
浅谈C中的malloc和free(转)
转自http://blog.21ic.com/user1/5473/archives/2009/54832.html一、malloc()和free()的基本概念以及基本用法:1、函数原型及说明:voi...
zxzxy1988 2009-12-31 16:32
PIC单片机中asm volatile的问题
读师兄们写的操作系统,有这么句话asm volatile ("push _CurrentTaskPCL");查了资料(http://www.microchip.com.tw/modules/newbb...
zxzxy1988 2009-12-23 22:27
SRAM和DRAM
SRAM 是静态随机存储器DRAM是动态随机存储器DRAM,动态随机存取存储器,需要不断的刷新,才能保存数据。 而且是行列地址复用的,许多都有页模式。 SRAM,静态的随机存取存储器,加电情况下,不需...
我要评论
0
0
广告