sizeof用法研究
一、基础研究
写一个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用法研究的更多相关文章
- 类的大小——sizeof 的研究
类的大小——sizeof 的研究(1) 先看一个空的类占多少空间? class Base { public: Base(); ~Base(); }; 注意到我这里显示声明了构造跟析构,但是sizeof ...
- sizeof()用法
参考:sizeof_百度百科 sizeof()用法汇总(经典) 声明:本文是笔者抽出对自己有用的细节,对前两文的总结. 1.sizeof概念 sizeof是C语言中判断数据类型或者表达式长度符:不是一 ...
- 别人不会给你说的---C语言中数组名和指针的区别 及 sizeof用法
引自: http://blog.csdn.net/tianyue168/article/details/5781924 #i nclude <iostream.h> int main( ...
- 关于Python的super用法研究
一.问题的发现与提出 在Python类的方法(method)中,要调用父类的某个方法,在python 2.2以前,通常的写法如代码段1: 代码段1: class A: def __init__(se ...
- sizeof用法
c语言详解sizeof 原文地址:http://blog.sina.com.cn/s/blog_5da08c340100bmwu.html 一.sizeof的概念 sizeof是C语言的一种单 ...
- 关于flask-sqlalchemy的用法研究
最近使用到flask的sqlalchemy,因为flask对sqlalchemy做了一些封装,加上自己本身对sqlalchemy也不熟悉,用法上走了很多弯路. 因为没时间去研究sqlalchemy的源 ...
- sizeof()用法汇总
sizeof()功能:计算数据空间的字节数 1.与strlen()比较 strlen()计算字符数组的字符数,以"\0"为结束判断,不计算为'\0'的数组元素. ...
- sizeof()用法汇总【转载】
转载自:http://www.cnblogs.com/chengxin1982/archive/2009/01/13/1374575.html 参考:http://blog.csdn.net/free ...
- 如何比较一个类型【模板使用】【sizeof用法】
#include <iostream> using namespace std; void testEmptyClass(); struct Empty { }; struct Dummy ...
随机推荐
- [Java] 实例创建的步骤
创建类的一个实例时,按照下面步骤进行创建: 1. 给当前类及其父.祖类的所有成员字段分配空间,并给它们赋予默认值 2. 开始执行当前类的构造器 3. 如果当前类有父类,则对父类创建一个实例:从第 2 ...
- HDU 4604 Deque 最长子序列
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4604 Deque Time Limit: 4000/2000 MS (Java/Others) ...
- 修改上一篇文章的node.js代码,支持默认页及支持中文
服务端 app.js var app = require('http').createServer(handler) var io = require('socket.io')(app); var f ...
- powershell利用winform批量执行tsql语句
#加载.net的winform模块 [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") $app= ...
- linux —— 问题解决(锦集)
这里收录了我在使用ubuntu 时遇到的问题以及解决方案. 1. Ubuntu上由于/boot容量不足引起的无法更新系统 解决: [ link1 ] [ link2 ] 2. 在未联网的情况下,sud ...
- AutoCompleteTextView ArrayAdapter
AutoCompleteTextView 继承于EditText,拥有EditText所有属性和方法 在输入框中输入我们想要输入的信息就会出现其他与其相关的提示信息 首先在activity_mai ...
- hdu 3037 Saving Beans(组合数学)
hdu 3037 Saving Beans 题目大意:n个数,和不大于m的情况,结果模掉p,p保证为素数. 解题思路:隔板法,C(nn+m)多选的一块保证了n个数的和小于等于m.可是n,m非常大,所以 ...
- JDBC batch批处理Statement executeBatch 具体解释
JDBC提供了数据库batch处理的能力,在数据大批量操作(新增.删除等)的情况下能够大幅度提升系统的性能.我曾经接触的一个项目,在没有採用batch处理时,删除5万条数据大概要半个小时左右,后来对系 ...
- App发布AppStore【苹果开发者中心需要做的事】
请准许我的这句抱怨,也说明发布app到AppStore理清这些东西的重要性:起初打包出现各种 ApplicationVerificationFailed,不是这里没有搞对就是那个证书没有搞对,整个人签 ...
- linux下用phpize给PHP动态添加扩展(转)
使用php的常见问题是:编译php时忘记添加某扩展,后来想添加扩展,但是因为安装php后又装了一些东西如PEAR等,不想删除目录重装,别说,php还真有这样的功能. 我没有在手册中看到. 如我想增加b ...