怎样获取int数组长度到int的长度

怎样知道一个INT数字的长度
[问题点数:20分,结帖人phwan]
怎样知道一个INT数字的长度
[问题点数:20分,结帖人phwan]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2006年4月 专题开发/技术/项目大版内专家分月排行榜第二2005年11月 专题开发/技术/项目大版内专家分月排行榜第二2005年10月 专题开发/技术/项目大版内专家分月排行榜第二2005年8月 专题开发/技术/项目大版内专家分月排行榜第二2005年4月 专题开发/技术/项目大版内专家分月排行榜第二2005年3月 专题开发/技术/项目大版内专家分月排行榜第二2005年2月 专题开发/技术/项目大版内专家分月排行榜第二2005年1月 专题开发/技术/项目大版内专家分月排行榜第二2003年6月 专题开发/技术/项目大版内专家分月排行榜第二
2005年7月 专题开发/技术/项目大版内专家分月排行榜第三2004年11月 专题开发/技术/项目大版内专家分月排行榜第三2003年4月 专题开发/技术/项目大版内专家分月排行榜第三
2006年4月 专题开发/技术/项目大版内专家分月排行榜第二2005年11月 专题开发/技术/项目大版内专家分月排行榜第二2005年10月 专题开发/技术/项目大版内专家分月排行榜第二2005年8月 专题开发/技术/项目大版内专家分月排行榜第二2005年4月 专题开发/技术/项目大版内专家分月排行榜第二2005年3月 专题开发/技术/项目大版内专家分月排行榜第二2005年2月 专题开发/技术/项目大版内专家分月排行榜第二2005年1月 专题开发/技术/项目大版内专家分月排行榜第二2003年6月 专题开发/技术/项目大版内专家分月排行榜第二
2005年7月 专题开发/技术/项目大版内专家分月排行榜第三2004年11月 专题开发/技术/项目大版内专家分月排行榜第三2003年4月 专题开发/技术/项目大版内专家分月排行榜第三
2006年4月 专题开发/技术/项目大版内专家分月排行榜第二2005年11月 专题开发/技术/项目大版内专家分月排行榜第二2005年10月 专题开发/技术/项目大版内专家分月排行榜第二2005年8月 专题开发/技术/项目大版内专家分月排行榜第二2005年4月 专题开发/技术/项目大版内专家分月排行榜第二2005年3月 专题开发/技术/项目大版内专家分月排行榜第二2005年2月 专题开发/技术/项目大版内专家分月排行榜第二2005年1月 专题开发/技术/项目大版内专家分月排行榜第二2003年6月 专题开发/技术/项目大版内专家分月排行榜第二
2005年7月 专题开发/技术/项目大版内专家分月排行榜第三2004年11月 专题开发/技术/项目大版内专家分月排行榜第三2003年4月 专题开发/技术/项目大版内专家分月排行榜第三
匿名用户不能发表回复!|trackbacks-0
近来在写程序的时候遇到了一个问题,就是传递一个数组指针进入一个函数的时候,虽然指针能够顺利的传递,但是,我们无法求出该数组的大小。见下面的代码:
#include&&stdio.h&void&setNum(int&*p,int&a);void&setNum(int&*p);int&main(){&&&&int&a[]&=&{<span style="COLOR: #,<span style="COLOR: #,<span style="COLOR: #,<span style="COLOR: #};&&&&printf("%d\n",sizeof(a)/sizeof(a[<span style="COLOR: #]));&&&&setNum(a);}void&setNum(int&*p,int&a){&&&&*p&=&a;}void&setNum(int&*p){&&&&int&Num&=&sizeof(p)/sizeof(p[<span style="COLOR: #]);&&&&printf("%d\n",Num);}
结果是,输出分别是4和1.原因分析:1.对于第一个输出,由于在main函数中定义的为数组,所以可以直接利用sizeof函数来求出a数组的长度。2.对于传递参数类型,比如上面的setNum函数(未传递个数版本),此时,调用该函数的时候,a退化为一个普通的指针,也就是说,此时sizeof(p)求出来的就是一个指针的大小,除以int的大小,恰好为1.启示:C语言中,不能够根据一个数组指针就求出来任意一个数组的大小。解决办法就是传第一个参数进来,指定大小。ps:参考资料(详实):摘录:& & 如果作为函数的参数是没法求的,&& & 但这样是可以的:&& &&& & #define & LENGTH(s) & (sizeof(s) & / & sizeof(int))&& &&& & int & s[12];&& & int & length & = & LENGTH(s);&==================================================&这样的方法只能用于数组变量的数组名,对于指向数组的指针,以及作为参数的数组名都是没有效果的,上面已经有人解释了&》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》不可能有办法的。&当你定义一个数组的时候:&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字节的指针,没有任何变量表示数组的大小会&#8220;自动&#8221;被传递进来。&我们看看这个时候 & 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支持&#8220;两种&#8221;数组。一种是定义处的数组,他分配大片连续内存,和原来的C标准相同。&2 & 另一种是作为参数传递数组。 & 你必须传递地址和数组大小;这个数组实际上是一个8字节的结构{ & 地址; & 大小}(事实上可能更加复杂,考虑多纬数组如何实现? & ) &&3 & 系统必须根据两种不同数组分别实现其 & []、* & 、&等。 & 原有的数组根据其首地址偏移(这是个常量)和下标寻址; & 而参数数组则首先取&#8220;地址&#8221;内容(这是个变量),然后根据这个地址寻址....&厄... & 再考虑多维数组——听起来这不是一整套vector模型么?&-----------------------------------------------&注1: & 对于C99支持的 & flexible & array & ,其 & sizeof & 运算是运行时求值
阅读(10687)
311212131415181920232425262712345678910111213
留言簿(11)
随笔分类(87)
随笔档案(145)
文章分类(70)
文章档案(70)
ACM与算法比赛
LaTex和Tex学习
电子书下载
英语网站(长期学习)
积分与排名
阅读排行榜
评论排行榜没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!When---什么时候需要知道对象的内存大小
在内存足够用的情况下我们是不需要考虑java中一个对象所占内存大小的。但当一个系统的内存有限,或者某块程序代码允许使用的内存大小有限制,又或者设计一个缓存机制,当存储对象内存超过固定值之后写入磁盘做持久化等等,总之我们希望像写C一样,java也能有方法实现获取对象占用内存的大小。
How---java怎样获取对象所占内存大小
在回答这个问题之前,我们需要先了解java的基础数据类型所占内存大小。
所占空间(byte)
byte    
当然,java作为一种面向对象的语言,更多的情况需要考虑对象的内存布局,java对于对象所占内存大小需要分两种情况考虑:
内存布局构成
一般非数组对象
8个字节对象头(mark) + 4/8字节对象指针 + 数据区 + padding内存对齐(按照8的倍数对齐)
数组对象& & & & & & & & & & & & & & & & &
8个字节对象头(mark) + 4/8字节对象指针 + 4字节数组长度 + 数据区 + padding内存对齐(按照8的倍数对齐)
可以看到数组类型对象和普通对象的区别仅在于4字节数组长度的存储区间。而对象指针究竟是4字节还是8字节要看是否开启指针压缩。Oracle JDK从6 update 23开始在64位系统上会默认开启压缩指针http://rednaxelafx.iteye.com/blog/1010079。如果要强行关闭指针压缩使用-XX:-UseCompressedOops,强行启用指针压缩使用: -XX:+UseCompressedOops。&
接下来我们来举例来看实现java获取对象所占内存大小的方法:
假设我们有一个类的定义如下:
private static class ObjectA {
private static class ObjectB {
如果我们直接按照上面掌握的java对象内存布局进行计算,则有:
Size(ObjectA) = Size(对象头(_mark)) + size(oop指针) + size(数据区)Size(ObjectA) = 8 + 4 + 4(String) + 4(int) + 1(byte) + 1(byte) + 2(padding) + 4(int) + 4(ObjectB指针) + 1(byte) + 7(padding)Size(ObjectA) = 40
我们直接通过两种获取java对象内存占用大小的方式来验证我们的计算是否正确。
方式1---通过Instrumentation来获取
这种方法得到的是Shallow Size,即遇到引用时,只计算引用的长度,不计算所引用的对象的实际大小。如果要计算所引用对象的实际大小,必须通过递归的方式去计算。查看jdk的代码发现,Instrumentation是一个接口,本来我想的是可以直接定义一个类实现该接口。但是看了下该接口里面的方法瞬间傻眼。根本没法去重写。calm down,原来Instrumentation接口的实例需要使用代理的方式来获得。具体步骤如下:
1.&编写 premain 函数
编写一个 Java 类,包含如下两个方法当中的任何一个public static void premain(String agentArgs, Instrumentation inst);
[1]public static void premain(String agentArgs); [2]其中,[1] 的优先级比 [2] 高,将会被优先执行([1] 和 [2] 同时存在时,[2] 被忽略)。在这个 premain 函数中,开发者可以进行对类的各种操作。agentArgs 是 premain 函数得到的程序参数,随同 && javaagent&一起传入。与 main 函数不同的是,这个参数是一个字符串而不是一个字符串数组,如果程序参数有多个,程序将自行解析这个字符串。Inst 是一个 java.lang.instrument.Instrumentation 的实例,由 JVM 自动传入。java.lang.instrument.Instrumentation 是 instrument 包中定义的一个接口,也是这个包的核心部分,集中了其中几乎所有的功能方法,例如类定义的转换和操作等。
1 package instrumentation.
3 import java.lang.instrument.I
5 public class ObjectShallowSize {
private static I
public static void premain(String agentArgs, Instrumentation instP){
inst = instP;
public static long sizeOf(Object obj){
return inst.getObjectSize(obj);
2. 在META-INF下面新建MANIFEST.MF文件,并且指定
Manifest-Version: 1.0 Premain-Class: instrumentation.test.ObjectShallowSize
3.&通过eclipse-&export-&jar-&next-&next,然后选中定制的 MANIFEST.MF 文件,进行jar打包。
4. 给需要使用ObjectShallowSize的工程引入该jar包,并通过代码测试对象所占内存大小:
&1 System.out.println(ObjectShallowSize.sizeOf(new ObjectA())); // 32&5. 在运行调用ObjectShallowSize.sizeof的类的工程中加上刚打的jar包依赖,同时eclipse里面run configuration,在VM arguments中添加(标红部分为jar包的绝对路径):
-javaagent:E:/software/instrumentation-sizeof.jar
方式2---使用Unsafe来获取
关于Unsafe的使用,后面我会专门开一个专题来详细讲述,这里暂时让我们来见识下Unsafe的神奇之处。
private final static Unsafe UNSAFE;
// 只能通过反射获取Unsafe对象的实例
UNSAFE = (Unsafe) Unsafe.class.getDeclaredField("theUnsafe").get(null);
} catch (Exception e) {
throw new Error();
Field[] fields = ObjectA.class.getDeclaredFields();
for (Field field : fields) {
  System.out.println(field.getName() + "---offSet:" + UNSAFE.objectFieldOffset(field));
输出结果为:
str---offSet:24
i1---offSet:12
b1---offSet:20
b2---offSet:21
i2---offSet:16
obj---offSet:28
b3---offSet:22
我们同样可以算得对象实际占用的内存大小:
Size(ObjectA) = Size(对象头(_mark)) + size(oop指针) + size(排序后数据区)& =& 8 + 4 + (28+4-12)& =& 32.
我们再回过头来,看我们在通过代码获取对象所占内存大小之前的预估值40。比我们实际算出来的值多了8个字节。通过Unsafe打印的详细信息,我们不难想到这其实是由hotspot创建对象时的排序决定的:
HotSpot创建的对象的字段会先按照给定顺序排列,默认的顺序为:从长到短排列,引用排最后: long/double && int/float && short/char && byte/boolean && Reference。
所以我们重新计算对象所占内存大小得:
Size(ObjectA) = Size(对象头(_mark)) + size(oop指针) + size(排序后数据区)Size(ObjectA) = 8 + 4 + 4(int) + 4(int) + byte(1) + byte(1) + 2(padding) + 4(String) + 4(ObjectB指针)Size(ObjectA) = 32
与上面计算结果一致。
Deeper---深入分析的一个例子:
以下代码摘抄自原链接:
3 import java.lang.reflect.A
4 import java.lang.reflect.F
5 import java.lang.reflect.M
6 import java.util.ArrayL
7 import java.util.A
8 import java.util.C
9 import java.util.HashM
10 import java.util.IdentityHashM
11 import java.util.L
12 import java.util.M
14 import sun.misc.U
16 public class ClassIntrospector {
private static final U
/** Size of any Object reference */
private static final int objectRefS
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (Unsafe) field.get(null);
// 可以通过Object[]数组得到oop指针究竟是压缩后的4个字节还是未压缩的8个字节
objectRefSize = unsafe.arrayIndexScale(Object[].class);
} catch (Exception e) {
throw new RuntimeException(e);
/** Sizes of all primitive values */
private static final Map&Class&?&, Integer& primitiveS
primitiveSizes = new HashMap&Class&?&, Integer&(10);
primitiveSizes.put(byte.class, 1);
primitiveSizes.put(char.class, 2);
primitiveSizes.put(int.class, 4);
primitiveSizes.put(long.class, 8);
primitiveSizes.put(float.class, 4);
primitiveSizes.put(double.class, 8);
primitiveSizes.put(boolean.class, 1);
* Get object information for any Java object. Do not pass primitives to
* this method because they will boxed and the information you will get will
* be related to a boxed version of your value.
* @param obj
Object to introspect
* @return Object info
* @throws IllegalAccessException
public ObjectInfo introspect(final Object obj)
throws IllegalAccessException {
return introspect(obj, null);
} finally { // clean visited cache before returning in order to make
// this object reusable
m_visited.clear();
// we need to keep track of already visited objects in order to support
// cycles in the object graphs
private IdentityHashMap&Object, Boolean& m_visited = new IdentityHashMap&Object, Boolean&(
private ObjectInfo introspect(final Object obj, final Field fld)
throws IllegalAccessException {
// use Field type only if the field contains null. In this case we will
// at least know what's expected to be
// stored in this field. Otherwise, if a field has interface type, we
// won't see what's really stored in it.
// Besides, we should be careful about primitives, because they are
// passed as boxed values in this method
// (first arg is object) - for them we should still rely on the field
boolean isPrimitive = fld != null && fld.getType().isPrimitive();
boolean isRecursive = false; // will be set to true if we have already
// seen this object
if (!isPrimitive) {
if (m_visited.containsKey(obj))
isRecursive = true;
m_visited.put(obj, true);
final Class&?& type = (fld == null || (obj != null && !isPrimitive)) ? obj
.getClass() : fld.getType();
int arraySize = 0;
int baseOffset = 0;
int indexScale = 0;
if (type.isArray() && obj != null) {
baseOffset = unsafe.arrayBaseOffset(type);
indexScale = unsafe.arrayIndexScale(type);
arraySize = baseOffset + indexScale * Array.getLength(obj);
final ObjectI
if (fld == null) {
root = new ObjectInfo("", type.getCanonicalName(), getContents(obj,
type), 0, getShallowSize(type), arraySize, baseOffset,
indexScale);
final int offset = (int) unsafe.objectFieldOffset(fld);
root = new ObjectInfo(fld.getName(), type.getCanonicalName(),
getContents(obj, type), offset, getShallowSize(type),
arraySize, baseOffset, indexScale);
if (!isRecursive && obj != null) {
if (isObjectArray(type)) {
// introspect object arrays
final Object[] ar = (Object[])
for (final Object item : ar)
if (item != null)
root.addChild(introspect(item, null));
for (final Field field : getAllFields(type)) {
if ((field.getModifiers() & Modifier.STATIC) != 0) {
field.setAccessible(true);
root.addChild(introspect(field.get(obj), field));
root.sort(); // sort by offset
// get all fields for this class, including all superclasses fields
private static List&Field& getAllFields(final Class&?& type) {
if (type.isPrimitive())
return Collections.emptyList();
Class&?& cur =
final List&Field& res = new ArrayList&Field&(10);
while (true) {
Collections.addAll(res, cur.getDeclaredFields());
if (cur == Object.class)
cur = cur.getSuperclass();
// check if it is an array of objects. I suspect there must be a more
// API-friendly way to make this check.
private static boolean isObjectArray(final Class&?& type) {
if (!type.isArray())
return false;
if (type == byte[].class || type == boolean[].class
|| type == char[].class || type == short[].class
|| type == int[].class || type == long[].class
|| type == float[].class || type == double[].class)
return false;
return true;
// advanced toString logic
private static String getContents(final Object val, final Class&?& type) {
if (val == null)
return "null";
if (type.isArray()) {
if (type == byte[].class)
return Arrays.toString((byte[]) val);
else if (type == boolean[].class)
return Arrays.toString((boolean[]) val);
else if (type == char[].class)
return Arrays.toString((char[]) val);
else if (type == short[].class)
return Arrays.toString((short[]) val);
else if (type == int[].class)
return Arrays.toString((int[]) val);
else if (type == long[].class)
return Arrays.toString((long[]) val);
else if (type == float[].class)
return Arrays.toString((float[]) val);
else if (type == double[].class)
return Arrays.toString((double[]) val);
return Arrays.toString((Object[]) val);
return val.toString();
// obtain a shallow size of a field of given class (primitive or object
// reference size)
private static int getShallowSize(final Class&?& type) {
if (type.isPrimitive()) {
final Integer res = primitiveSizes.get(type);
return res != null ? res : 0;
return objectRefS
下面来分析ObjectC所占内存大小:
3 public class IntrospectorTest {
private static class ObjectC {
ObjectD[] array = new ObjectD[2];
private static class ObjectD {
public static void main(String[] args) throws IllegalAccessException {
final ClassIntrospector ci = new ClassIntrospector();
ObjectInfo res = ci.introspect(new ObjectC());
System.out.println( res.getDeepSize() );
代码输出为:40。
下面我们来分析下ObjectC的内存布局:
ShallowSize(ObjectC) = Size(对象头) + Size(oop指针) + Size(内容) + Size(对齐)
ShallowSize(ObjectC) = 8 + 4 + 4(ObjectD[]数组引用) =16
Size(ObjectD[] arr) = 8(数组对象头) + 4(oop指针) + 4(数组长度) + 4(ObjectD[0]对象引用) + 4(ObjectD[1]对象引用) = 24
因为arr没有具体赋值,所以此时具体引用的为null,不占用内存。否则需要再次计算ObjectD的内存最后想加。
所以总共得到:Size(ObjectC) =&ShallowSize(ObjectC) +&Size(ObjectD[] arr)& = 40。
参考链接:
http://blog.csdn.net/antony9118/article/details/https://www.cnblogs.com/licheng/p/6576644.html
阅读(...) 评论()C/C++中获取数组长度的方法示例
转载 &更新时间:日 09:55:10 & 投稿:shichen2014
这篇文章主要介绍了C/C++中获取数组长度的方法,很实用的一种方法,需要的朋友可以参考下
学过C/C++的人都知道,在C/C++中并没有提供直接获取数组长度的函数,对于存放字符串的字符数组提供了一个strlen函数获取其长度,那么对于其他类型的数组如何获取他们的长度呢?
其中一种方法是使用sizeof(array) / sizeof(array[0]), 在C语言中习惯上在使用时都把它定义成一个宏,比如:
#define GET_ARRAY_LEN(array,len) {len = (sizeof(array) / sizeof(array[0]));}
而在C++中则可以使用模板技术定义一个函数,比如:
template &class T&
int getArrayLen(T& array)
return (sizeof(array) / sizeof(array[0]));
这样对于一些简单的数组可以使用这个宏或者这个函数来获取数组的长度了。
以下是两个Demo程序,一个C语言的,一个C++的:
注意:若数组为存储字符串的字符数组,即以双引号括起来的字符串整体初始化的字符数组
char a[]="abcdefg"
char a[]={"abcdefg"}
则所求得的长度为字符数组的长度,而不是对应的字符串的长度,要求字符串的长度还需要减一。原因为存储字符串的字符数组末尾有一个'\0'字符,需要去掉它。
对于下例:
char a[]="abcdefg";
sizeof(a)/sizeof(a[0])=8;
要求字符串长度的话应该减1.
char a[]={'a','b','c','d','e','f','g'};
sizeof(a)/sizeof(a[0])=7
C语言实例如下:
#include &stdio.h&
#include &stdlib.h&
#define GET_ARRAY_LEN(array,len) {len = (sizeof(array) / sizeof(array[0]));}
//定义一个带参数的宏,将数组长度存储在变量len中
int main()
char a[] = {'1','2','3','4'};
GET_ARRAY_LEN(a,len)
//调用预定义的宏,取得数组a的长度,并将其存储在变量len中
printf("%d\n",len);
system("pause");
输出结果为:4
C++实例如下:
#include &iostream&
template &class T&
int getArrayLen(T& array) //使用模板定义一个函数getArrayLen,该函数将返回数组array的长度
return (sizeof(array) / sizeof(array[0]));
int main()
char a[] = {'1','2','3'};
cout && getArrayLen(a) &&
输出结果为:3
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具}

我要回帖

更多关于 int 长度 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信