例子一:

/*
*根据以下条件进行计算:
*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的区别的更多相关文章

  1. 笔试中sizeof求字节数的问题

    1. ]) { cout<<sizeof(ch)<<endl; //或者sizeof(ch)=?; } 这种情况,数组名作为形参,退化成指针,所以sizeof结果是4(32位编 ...

  2. sizeof()与strlen()的区别

    首先需要说明的是sizeof和strlen都可以求长度,但是却有很大的区别,简单来说可以概括为以下几点: 1.sizeof是一个关键字,而strlen确实一个函数. 2.sizeof求的是字节长度,而 ...

  3. sizeof和strlen的区别和联系总结

    link:http://blog.csdn.net/ghevinn/article/details/9974967    strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头 ...

  4. 我也介绍下sizeof与strlen的区别

    本节我也介绍下sizeof与strlen的区别,很简单,就几条: 1. sizeof是C++中的一个关键字,而strlen是C语言中的一个函数:2. sizeof求的是系统分配的内存总量,而strle ...

  5. strlen 字符型数组和字符数组 sizeof和strlen的区别 cin.get(input,Arsize)

    strlenstrlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值 ...

  6. sizeof && strlen 的区别

    本文主要记录了 sizeof 操作符 和 strlen() 函数的区别,以及各自的用途.(在下才疏学浅,发现错误,还请留言指正) sizeof 和 strlen 的区别 示例代码如下: #includ ...

  7. sizeof和strlen的区别

    一.sizeof    sizeof(...)是运算符,而不是一个函数.    sizeof操作符的结果类型是size_t,在头文件中typedef为unsigned int,其值在编译时即计算好了, ...

  8. Sizeof与Strlen的区别与联系

    转自:http://www.cnblogs.com/carekee/articles/1630789.html 一.sizeof    sizeof(...)是运算符,在头文件中typedef为uns ...

  9. Sizeof与Strlen的区别与联系(转)

    Sizeof与Strlen的区别与联系 一.sizeof     sizeof(...)是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组.指针.类型 ...

随机推荐

  1. Thrift框架使用C++的一个demo

    Thrift编译器会根据选择的目标语言为server产生服务接口代码,为client产生stubs,参数可以是基本类型和结构体. 代码框架用的Thrift,为了了解结构,学习写了一个thrift的De ...

  2. 【LeetCode 215】Kth Largest Element in an Array

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  3. Request、Request.Form和Request.QueryString的区别

    Request.Form:获取以POST方式提交的数据(接收Form提交来的数据): Request.QueryString:获取地址栏参数(以GET方式提交的数据) Request:包含以上两种方式 ...

  4. linux交叉环境的搭建以及嵌入式开发概述

    嵌入式开发概述 由嵌入式本身的特性所影响,嵌入式系统开发与通用系统的开发有很大的区别,嵌入式的开发分为系统总体开发,嵌入式硬件开发,嵌入式系统软件开发3大部分 在系统总体开发中,由于嵌入式系统与硬件依 ...

  5. Vim小知识

    在退出vim编辑的时候,强制退出是q! 感叹号在前,即!q,表示执行外部shell命令,感叹号在后,即q!,表示强制执行vi命令.

  6. 在window server 2008 64位系统上 发布网站的过程中遇到的问题

    发布网站的过程如下: 1.安装数据库系统2.建立数据库,执行sql3.安装iis4.在本地机子上发布网站5.把发布好的东西拷贝到IIS上 1.安装数据库系统: 出现错误:必须使用角色管理工具 安装或配 ...

  7. 新購電腦筆記 - G1.Sniper B7 內建網路晶片在 Mint 17.2(Cinnamon)上無法使用(已解決)

    又好久沒寫文章了,這次因新購電腦,有一些狀況,故做一下記錄,也分享給遇到同樣問題的格友 以前在公司裝 Ubuntu 從沒遇過這麼多問題,這次自己第一次組電腦,也第一次裝 Mint,問題倒是不少 第一個 ...

  8. Chapter 2 Build Caffe

    Caffe for windows 的build药按照一定的顺序进行. ============================================================ 先以b ...

  9. 通过Unity3D发布IOS版游戏

    https://developer.apple.com/ 打开上面的苹果开发者网站,选择上面的"Member Center"登录进入.前提是,你注册了开发者账号,并且付了年费. 选 ...

  10. 从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式(三)

    转载 http://blog.csdn.net/cutesource/article/details/6192163 最后我们再看看NIO方面最著名的框架Mina,抛开Mina有关session和处理 ...