sizeof求字节以及与strlen的区别
例子一:
/*
*根据以下条件进行计算:
*1、 结构体的大小等于结构体内最大成员大小的整数倍
*2、 结构体内的成员的首地址相对于结构体首地址的偏移量是其类型大小的整数倍,比如说double型成员相对于结构体的首地址的地址
*偏移量应该是8的倍数。
*/
#include<iostream>
#include<cstdlib>
using namespace std; class AA
{
int a;
short b;
int c;
char d;
};
class BB
{
double a;
short b;
int c;
char d;
}; struct{
short a1;
short a2;
short a3;
}A; struct{
long a1;
short a2;
}B; int main()
{
cout<<sizeof(AA)<<" "<<sizeof(BB)<<endl;
char *ss1="";
char ss2[]="";
char ss3[]="";
int ss4[];
char q1[]="abc";
char q2[]="a\n";
char *q3="a\n";
char *str1=(char*)malloc(); void *str2=(void*)malloc(); cout<<sizeof(ss1)<<endl;//ss1是一个字符指针,指针的大小是一个定值,就是4
cout<<sizeof(ss2)<<endl; //ss2是一个字符数组,这个数组最初未定大小,由具体情况填充
cout<<sizeof(ss3)<<endl;//ss3也是一个字符数组,这个数组开始预分配100,所以它的大小一共是100位
cout<<sizeof(ss4)<<endl;//ss4也是一个整型数组,这个数组开始预分配100,但每个整型变量所占空间是4,所以它的大小一共是400
cout<<sizeof(q1)<<endl; //q1和ss2类似,所以是4
cout<<sizeof(q2)<<endl;//q2里面有一个'\n',算作一位,所以它的空间是3
cout<<sizeof(q3)<<endl;//q3是一个字符指针,指针的大小是一个定值,就是4,所以sizeof(q3)是4
cout<<sizeof(A)<<endl; //结构体的长度一定是最长的数据元素的整数倍
cout<<sizeof(B)<<endl;
cout<<sizeof(str1)<<endl; //指针的长度固定是4
cout<<sizeof(str2)<<endl;
}
其中,AA中,a占4个字节,b本应占2个字节,但由于c占4个字节,为了满足条件2,b多占用2个字节,为了满足条件1,d占用4个字节,一共16个字节。
BB中,a占8个字节,b占2个字节,但由于c占4个字节,为了满足条件2,b多占用2个字节,
即abc共占用8+4+4=16个字节,
为了满足条件1,d将占用8个字节,一共24个字节。
例子二:
#include<iostream>
#include<new>
using namespace std; class A{}; class A2{
char d,e;
}; class B{ }; struct C{
char b,c;
}; struct D{
int x,y;
}; int main()
{
cout<<sizeof(A)<<endl; //对于一个类而言,即便它是一个空的类,编译器仍然要给它一个空间,所以类A即便什么都没有,它的空间大小也是1
cout<<sizeof(A2)<<endl; //而类A2大小是类中的两个字符d、e之和,所以它的空间大小依然是2
A *p1=new A();
A p2;
A *p3;
//至于p1 p2 p3,p1和p3是指针,所以它们的大小是一定的,因此是4,p2是类A的对象,所以它的大小和类A相等,也是1
cout<<sizeof(p1)<<endl;
cout<<sizeof(p2)<<endl;
cout<<sizeof(p3)<<endl;
cout<<sizeof(B)<<endl;
cout<<sizeof(C)<<endl;
cout<<sizeof(D)<<endl;
}
例子三:
总结:空的类也是会占用内存空间的,而且大小是1,原因是C++要求每个实例在内存中都有独一无二的地址。
1)类内部的成员变量:
普遍的变量:是要占用内存的,但是要注意内存对齐(这点和struct类型很相似)
static修饰的静态变量:不占用内存,原因是编译器将其放在全局变量区
2)类内部的成员函数
非虚函数(构造函数、static函数、成员函数等):不占用内存
虚函数:要占用4个字节(32操作系统),用来指定虚拟函数表的入口地址。跟虚函数的个数没有关系。父类和子类共享一个虚函数指针。
构成对象本身的只是数据,任何成员函数都不隶属于任何一个对象,非静态成员函数与对象的关系就是绑定,绑定的中介就是this指针。成员函数为该类的对象共享,不仅是处于简化语言实现、节省存储的目的,而且是为了使同类对象由一致的行为。同类对象的行为虽然一致,但是操作不同的数据成员。
#include<iostream>
using namespace std; class A1
{
public:
int a;
static int b; //static在全局变量区,不属于对象
A1();
~A1();
}; class A2
{
public:
int a;
char c;
A2();
~A2();
}; class A3
{
public:
float a;
char c;
A3();
~A3();
}; class A4
{
public:
float a;
int b;
char c;
A4();
~A4();
}; class A5
{
public:
double d;
float a;
int b;
char c;
A5();
~A5();
}; int main()
{
cout<<sizeof(A1)<<endl;
cout<<sizeof(A2)<<endl;
cout<<sizeof(A3)<<endl;
cout<<sizeof(A4)<<endl;
cout<<sizeof(A5)<<endl; }
存在父类和子类以及虚继承时,sizeof的大小
总结:
- 类的大小为类的非静态数据成员的类型大小之和,静态成员数据不作考虑
- 空类的大小为1,单一继承和多重继承的空类空间为1,虚继承为4
- 构造函数、析构函数以及普通的成员函数跟sizeof无关
- 带有虚函数的类,因为要维护一个虚函数表所以占用一个指针的空间4
- 子类如果是重新实现的父类的虚函数,不计入sizeof大小
- 虚继承涉及到虚表(虚指针),大小为4
例如:
#include<iostream>
#include<memory>
#include<assert.h>
using namespace std; class A{ }; class A2{}; class B:public A{}; class C:public virtual B{}; class D:public A,public A2{}; int main()
{
cout<<"sizeof(A): "<<sizeof(A)<<endl;
cout<<"sizeof(B): "<<sizeof(B)<<endl;
cout<<"sizeof(C): "<<sizeof(C)<<endl;
cout<<"sizeof(D): "<<sizeof(D)<<endl;
}
输出:

sizeof与strlen之间的区别:
例子一:
char *ss="0123456789";
sizeof(ss)结果为4,ss是指向字符串常量的字符数组。
sizeof(*ss)结果是1,*ss是第一个字符
例子二:
char ss[]="0123456789";
sizeof(ss)结果为11,ss是数组,计算到'\0'位置,因此是(10+1)。
sizeof(*ss)结果是1,*ss是第一个字符
例子三:
char ss[100]="0123456789";
sizeof(ss)结果是100,ss表示在内存中预分配的大小,100*1。
strlen(ss)结果是10,它的内部实现是用一个循环计算字符串的长度,直到'\0'为止,并且不包含'\0'。
例子四:
int ss[100]="0123456789";
sizeof(ss)结果是400,ss表示在内存中的大小,100*4。
strlen(ss)错误,strlen的参数只能是char*,且必须是以'\0'结尾的。
例子五:
class X
{
int i;
int j;
char k;
};
X x;
cout<<sizeof(X)<<endl; 结果是12,内存补齐
cout<<sizeof(x)<<endl; 结果是12,理由同上
通过上面的sizeof与strlen的深入理解,得出两者区别如下:
1)sizeof操作符的结构类型是size_t,它在头文件中的typedef为unsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小。
2)sizeof是操作符,strlen是函数
3)sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以'\0'结尾的。sizeof还可以用函数做参数,比如:
short f();
printf("%d\n",sizeof(f()));
输出的结果是sizeof(short),即2
4)数组做sizeof的参数不退化,传递给strlen就退化为指针。
5)大部分编译程序在编译的时候就把sizeof计算过了,是类型或是变量的长度。这就是sizeof(x)可以用来定义数组维数的原因:
char str[20]="0123456789";
int a=strlen(str); //a=10;
int b=sizeof(str); //而b=20;
6)strlen的结果要在运行的时候才能计算出来,用来计算字符串的长度,而不是类型占内存的大小。
7)sizeof后如果是类型必须加括号,如果是变量名可以不加括号。这是因为sizeof是个操作符而不是函数。
8)当使用一个结构类型或变量时,sizeof返回时实际的大小。当使用静态的数组空间时,sizeof返回全部数组的尺寸。sizeof操作符不能返回被动态分配的数组或外部的数组的尺寸。
9)数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,如:fun(char [8]),fun(char[])都等价于fun(char*)。在C++里传递数组永远都是传递指向数组首元素的指针,编译器不知道数组的大小。如果想在函数内知道数组的大小,需要这样做:进入函数后用memcpy将数组拷贝出来,长度由另一个形参传进去。代码如下:
fun (unsigned char *p1,int len)
{
unsigned char *buf=new unsigned char[len+];
memcpy(buf,p1,len);
}
10)计算结构变量的大小就必须讨论数据对齐问题。为了使CPU存取的速度最快,C++在处理数据时经常把结构变量中的成员的大小按照4或8的倍数计算,这就叫数据对齐。
11)sizeof操作符不能用于函数类型、不完全类型或位字段。不完全类型指具有未知存储大小数据的数据类型,如未存储大小的数组类型、未知内容的结构或联合类型、void类型等。
sizeof对于指针,求出的是指针的大小,如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。
例如:
char var[10];
int test(char var[])
{
return sizeof(var);
};
sizeof求字节以及与strlen的区别的更多相关文章
- 笔试中sizeof求字节数的问题
1. ]) { cout<<sizeof(ch)<<endl; //或者sizeof(ch)=?; } 这种情况,数组名作为形参,退化成指针,所以sizeof结果是4(32位编 ...
- sizeof()与strlen()的区别
首先需要说明的是sizeof和strlen都可以求长度,但是却有很大的区别,简单来说可以概括为以下几点: 1.sizeof是一个关键字,而strlen确实一个函数. 2.sizeof求的是字节长度,而 ...
- sizeof和strlen的区别和联系总结
link:http://blog.csdn.net/ghevinn/article/details/9974967 strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头 ...
- 我也介绍下sizeof与strlen的区别
本节我也介绍下sizeof与strlen的区别,很简单,就几条: 1. sizeof是C++中的一个关键字,而strlen是C语言中的一个函数:2. sizeof求的是系统分配的内存总量,而strle ...
- strlen 字符型数组和字符数组 sizeof和strlen的区别 cin.get(input,Arsize)
strlenstrlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值 ...
- sizeof && strlen 的区别
本文主要记录了 sizeof 操作符 和 strlen() 函数的区别,以及各自的用途.(在下才疏学浅,发现错误,还请留言指正) sizeof 和 strlen 的区别 示例代码如下: #includ ...
- sizeof和strlen的区别
一.sizeof sizeof(...)是运算符,而不是一个函数. sizeof操作符的结果类型是size_t,在头文件中typedef为unsigned int,其值在编译时即计算好了, ...
- Sizeof与Strlen的区别与联系
转自:http://www.cnblogs.com/carekee/articles/1630789.html 一.sizeof sizeof(...)是运算符,在头文件中typedef为uns ...
- Sizeof与Strlen的区别与联系(转)
Sizeof与Strlen的区别与联系 一.sizeof sizeof(...)是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组.指针.类型 ...
随机推荐
- C++实现网格水印之调试笔记(一)
首先说一下我的一些简单的调试方法,除了常规的断点调试之外,我还会使用注释的方法来调试.当整个工程代码量相当多且调用层次关系较为复杂时,这种方法能够比较高效的定位到出错误的代码段或某个函数,然后在出现错 ...
- User experience
User experience 以用户为中心, --通过简单的操作快速完成美好的任务 简单 聚焦,我在干什么?我接下来要干什么? 删除.隐藏,合并.分组 使用背景色,而非边框来划分区域 碎片化,电话不 ...
- JavaEE5 Tutorial_JavaBean,JSTL
<jsp:useBean id="beanName" class="fully_qualified_classname" scope="scop ...
- jsp文件上传、下载
一.文件上传 上传文件是Web开发中经常要用到的功能:例如在基于B/S的人事信息管理系统中上传照片,在新闻发布系统中上传图片等等.....要实现文件上传功能,就需要综合利用java中的文件输入和输出相 ...
- 软件开发杂谈之从需求到上线---valen
背景 IT已经成为当代企业必不可少的竞争手段,从无到有到标配,可以说以后不懂IT的就是文盲这句一点也不过,而软件开发是个复杂工程,零零碎碎各种理论工具和技巧,一言难尽. 本文意在言简意赅,简述软件开发 ...
- 【转】CocoaPods的安装以及遇到的坑
一.CocoaPods是什么? CocoaPods是一个用Ruby写的.负责管理iOS项目中第三方开源库的工具,CocoaPods能让我们集中的.统一管理第三方开源库,为我们节省设置和更新第三方开源库 ...
- UVALive 7278 Game of Cards (sg函数)
Game of Cards 题目链接: http://acm.hust.edu.cn/vjudge/contest/127406#problem/G Description Alice and Bob ...
- CodeForces 489B BerSU Ball (贪心)
BerSU Ball 题目链接: http://acm.hust.edu.cn/vjudge/contest/121332#problem/E Description The Berland Stat ...
- AutoCAD.NET二次开发:创建自定义菜单(AcCui)
从CAD2007之后,Autodesk提供了一个新的程序集AcCui.dll,使用这个程序集,我们可以方便地做一些界面方面的操作,比如创建自定义菜单. 下面介绍一下菜单的创建过程: 1.在项目中添加引 ...
- Codeforces Round #337 (Div. 2) D. Vika and Segments (线段树+扫描线+离散化)
题目链接:http://codeforces.com/contest/610/problem/D 就是给你宽度为1的n个线段,然你求总共有多少单位的长度. 相当于用线段树求面积并,只不过宽为1,注意y ...