一、基础研究

写一个c程序,打印int、long、double型变量所占的字节数、地址、各个字节的地址和内容。打印地址和内容比较好办,打印地址可以用取址符&,打印内容直接输出就行了,那么怎么打印所占的字节数呢?我们打印一个东西是输出它的值,而变量所占的字节数没有变量或指针来存储,我们可以得到变量所占字节数的方法是用运算符sizeof,首先写的程序如下:

运行结果如下:

发现有错误:1、打印出的地址是负数。2、打印出的c的值为0。

结果发现%d是打印有符号十进制整数,而地址是十六进制无符号整数,所以应该用%x说明符打印。而这里c的内容打印错误也是因为转换说明符写错了,打印double型的变量应该用%lf作为说明符。下面为修改后的程序和运行结果:

还有一点值得注意的是对取址符取出的地址要先进行强制类型转换如(int)&a再对地址进行操作(运算或打印),因为&a是变量a的地址,如果不进行类型转换,在计算时会按照地址的规则进行计算,比如double型变量c,(int)&c+2是在c的地址上再加2个字节,而&c+2是在c的地址上加2个c的长度也就是16个字节。另外在打印c是我使用的是%p说明符,结果发现打印的地址没有变化,只是打印出的地址是以大写字母表示的,而且%x打印0000、0008的地址只会显示0和8,而%p是按照地址的格式显示0000和0008。

我觉得在本程序中,sizeof是可以通过自己写的语句代替的,假如我们要打印一个不知道类型的变量a所占的字节数,我们可以在它后面加一个变量b,这样我们就知道a和b的首地址,二者相减就可以得出a所占的字节数。修改程序如下:

运行结果和上面的是相同的。

再看第二个问题,要求打印结构体变量所占的字节数、地址、各数据项地址、内容和各个字节的内容。程序如下:

运行结果:

在这里要获得每一个字节的内容,我是将地址转换成数字加上字节数,但是这样的话需要在计算后再将结果强制转换成地址形式并输出,所以要定义一个指针变量p用来存放计算结果并打印。

这里有一个问题:在最后输出数组name的每个字节的值,结果数组各项和数组每个字节输出的结果都是两个字节的数据,而不是一个字节的数据,这是为什么?但是对数组进行初始化后结果就是对的:

这是为什么呢,为什么不初始化数组显示每个字节的值是超过一个字节的呢?

同时我还注意到,这里数组name的数据类型是char型,那么它的地址加1就是加一个字节,与上面的方法理论上结果是相同的,我们试验一下,在程序后面加上如下代码:

结果是相同的:

但是这只能对char型数组用,因为只有char型数据按地址加1是增加1个字节的。

再来看下一个问题:写一个程序,反映参数的存储空间与局部变量的存储空间在函数运行后收回。在函数的生命周期结束后参数和局部变量的存储空间会被释放,我们在之前的研究中已经研究过,参数和局部变量的存储空间都是栈段,在函数返回时将栈顶指针sp复原

即将使用过的栈段空间释放,此时虽然这一段空间里的数据没有被覆盖,但是已经不被当前函数使用了,其他函数或程序随时可以使用覆盖,所以空间被释放了。那么怎么体现这个过程呢?我们可以定义全局指针变量,在函数里将它指向参数和局部变量的地址,用*p将参数和局部变量的地址打印出来,之后再使用函数进行一次传参以改变栈段里的值,然后在主函数里再打印一次*p,这时p还是原来的参数和局部变量的地址,如果空间没有回收,此时该地址处的值就不变,否则就说明空间已经被回收了。程序如下:

运行结果为:

两次的结果不一样,说明局部变量的存储空间在函数运行后收回,因为参数和局部变量存储的方式是一样的,所以参数的存储空间也是在函数运行后收回。

二、拓展研究

1、为什么不初始化数组显示每个字节的值是超过一个字节的呢?

2、Sizeof的使用方法。

答:根据有关资料,sizeof运算符以字节为单位返回其操作数的大小,操作数可以是一个具体的数据对象,如一个变量名,也可以是一个类型,如float,如果它是一个类型,操作数必须被括在圆括号里,如sizeof n和sizeof(float)。sizeof操作符不能用于函数类型,不完全类型或位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型,size_t是后者用typedef机制创建的别名。

当操作数是指针时,sizeof依赖于编译器。例如Microsoft C/C++7.0中,near类指针字节数为2,far、huge类指针字节数为4。一般Unix的指针字节数为4。

当操作数具有数组类型时,其结果是数组的总字节数。

联合类型操作数的sizeof是其最大字节成员的字节数。结构类型操作数的sizeof是这种类型对象的总字节数,包括任何垫补(就是为了内存对齐而补充的内存单元)在内。

如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。

3、Sizeof的实现方式。

答:之前我以为sizeof是以库函数的形式实现的,但是发现它是一个运算符。函数与操作符的区别就在于,函数是程序运行是动态计算出一个对象或者类型所占的内存字节数,然而sizeof()操作符是在编译的时候就把字节数计算好,然后把这个字节数编译进行程序。它的实现是编译器的工作。这个数是一个常量。

三、研究总结

Sizeof也是由别人编写的实现计算变量长度的一个函数,与一般的函数不同的是它是要对地址进行操作来实现的,这体现了c语言的特点。当然我们也可以自己写代码来代替它的功能,但是这样程序不精简,占用的空间也更多。人类进化的重要标志就是会用工具来减少自己的工作量,也就是由底层向高层发展的过程,库函数、宏的出现也符合这一趋势。随着科技的发展,我们要做的工作越来越少,而机器和系统、软件却越来越丰富、智能,这条进化之路的最后会是人工智能出现,机器具有接近人的思维吗?我觉得是有可能实现的。

sizeof用法研究的更多相关文章

  1. 类的大小——sizeof 的研究

    类的大小——sizeof 的研究(1) 先看一个空的类占多少空间? class Base { public: Base(); ~Base(); }; 注意到我这里显示声明了构造跟析构,但是sizeof ...

  2. sizeof()用法

    参考:sizeof_百度百科 sizeof()用法汇总(经典) 声明:本文是笔者抽出对自己有用的细节,对前两文的总结. 1.sizeof概念 sizeof是C语言中判断数据类型或者表达式长度符:不是一 ...

  3. 别人不会给你说的---C语言中数组名和指针的区别 及 sizeof用法

    引自: http://blog.csdn.net/tianyue168/article/details/5781924 #i nclude <iostream.h> int  main( ...

  4. 关于Python的super用法研究

    一.问题的发现与提出 在Python类的方法(method)中,要调用父类的某个方法,在python 2.2以前,通常的写法如代码段1: 代码段1: class A:  def __init__(se ...

  5. sizeof用法

    c语言详解sizeof   原文地址:http://blog.sina.com.cn/s/blog_5da08c340100bmwu.html 一.sizeof的概念   sizeof是C语言的一种单 ...

  6. 关于flask-sqlalchemy的用法研究

    最近使用到flask的sqlalchemy,因为flask对sqlalchemy做了一些封装,加上自己本身对sqlalchemy也不熟悉,用法上走了很多弯路. 因为没时间去研究sqlalchemy的源 ...

  7. sizeof()用法汇总

    sizeof()功能:计算数据空间的字节数 1.与strlen()比较      strlen()计算字符数组的字符数,以"\0"为结束判断,不计算为'\0'的数组元素.      ...

  8. sizeof()用法汇总【转载】

    转载自:http://www.cnblogs.com/chengxin1982/archive/2009/01/13/1374575.html 参考:http://blog.csdn.net/free ...

  9. 如何比较一个类型【模板使用】【sizeof用法】

    #include <iostream> using namespace std; void testEmptyClass(); struct Empty { }; struct Dummy ...

随机推荐

  1. puppet yum安装配置,简单证书维护

    Puppet学习之puppet的安装和配置 一.Puppet简介 Puppet基于ruby语言开发的自动化系统配置工具,可以C/S模式或独立运行,支持对所有UNIX及类UNIX系统的配置管理,最新版本 ...

  2. 首届京东自有品牌科技周“京东点亮生活”圆满成功 - 课程公告板 - 京东内部论坛 - Powered by Discuz!

    首届京东自有品牌科技周"京东点亮生活"圆满成功 - 课程公告板 - 京东内部论坛 - Powered by Discuz! 首届京东自有品牌科技周"京东点亮生活" ...

  3. jQuery.holdReady()方法用法实例

    调用此方法可以延迟jQuery的ready事件,也就是说尽管文档已经加载完成,也不会执行ready事件处理方法.可以多次调用jQuery.holdReady()方法,以延迟jQuery的ready事件 ...

  4. Linux查看端口信息命令

    netstat -tlnp|grep 端口 eg: netstat -tlnp|grep 9889

  5. 《JAVA课程设计》实训第四天——《猜猜看》游戏

    第四天,本来想进一步去改进<猜猜看>游戏的.可是非常多问题都不理解.也不熟悉怎么去弄到连接数据库.统计猜对次数,所以并没有进行再多的改动. 基本上就是这种执行结果了 import java ...

  6. Android 网络编程与通信协议

    大多数的Android应用程序都会使用HTTP协议来发送和接收网络数据,而Android中主要提供了两种方式来进行HTTP操作, HttpURLConnection和HttpClient.这两种方式都 ...

  7. c# 字符串编码问题

    一. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte). ...

  8. java多线程心得

    多并发的时候,在什么情况下必须加锁?如果不加锁会产生什么样的后果. 加锁的场景跟java的new thread和Runnable的关系是什么? 看看java的concurrentMap源码. 还有sp ...

  9. 关于char与varchar,varchar2的区别

    http://zhidao.baidu.com/question/220360696.html?qbl=relate_question_0&word=char%BA%CDvarchar2%B5 ...

  10. eclipse中的web-inf下没有web.xml