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="0123456789";
    char ss2[]="0123456790";
    char ss3[100]="0123456789";
    int ss4[100];
    char q1[]="abc";
    char q2[]="a\n";
    char *q3="a\n";
    char *str1=(char*)malloc(100);

    void *str2=(void*)malloc(100);

    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+1];
    memcpy(buf,p1,len);
}

10)计算结构变量的大小就必须讨论数据对齐问题。为了使CPU存取的速度最快,C++在处理数据时经常把结构变量中的成员的大小按照4或8的倍数计算,这就叫数据对齐。

11)sizeof操作符不能用于函数类型、不完全类型或位字段。不完全类型指具有未知存储大小数据的数据类型,如未存储大小的数组类型、未知内容的结构或联合类型、void类型等。

 

 

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

 例如:

char var[10];

int test(char var[])

{

  return sizeof(var);

};

时间: 2024-09-27 13:53:28

sizeof求字节以及与strlen的区别的相关文章

Sizeof与Strlen的区别与联系

转自http://www.cnblogs.com/carekee/articles/1630789.html 一.sizeof     sizeof(...)是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组.指针.类型.对象.函数等.     它的功能是:获得保证能容纳实现所建立的最大对象的字节大小.     由于在编译时计算,因此sizeof不能用来返回动态分配的内存空间的大小.实际上,用sizeof来返回类型以及静态分配的对象.结构或数组所

基于Sizeof与Strlen的区别以及联系的使用详解_C 语言

一.sizeof    sizeof(...)是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组.指针.类型.对象.函数等.    它的功能是:获得保证能容纳实现所建立的最大对象的字节大小.    由于在编译时计算,因此sizeof不能用来返回动态分配的内存空间的大小.实际上,用sizeof来返回类型以及静态分配的对象.结构或数组所占的空间,返回值跟对象.结构.数组所存储的内容没有关系.    具体而言,当参数分别如下时,sizeof返回的值表示

c语言-C语言用sizeof求数组长度,为什么结果不对?

问题描述 C语言用sizeof求数组长度,为什么结果不对? int aaaaa[10]; printf("%d/n",sizeof(aaaaa)); 结果是40? 解决方案 printf("%d/n",sizeof(aaaaa) / sizeof(int)); 解决方案二: sizeof求的不是数组的长度而是数据占用的空间,单位是字节

一道用 sizeof 求结构体所占大小的笔试题?求教

问题描述 一道用 sizeof 求结构体所占大小的笔试题?求教 下列程序,为什么输出的结果是 120? int main(int argc, char* argv[]) { union u_type { int i; double x; float f; }; struct str_type { char str[100]; union u_type u[2]; }; printf("%dn",sizeof(struct str_type)); } 解决方案 首先union u_typ

c语言编程-求解答这两个的区别!(前两张图片),还有为什么不执行了(最后一张

问题描述 求解答这两个的区别!(前两张图片),还有为什么不执行了(最后一张 解决方案 左边的翻译一下就是如果....如果.....,两个if语句都会执行的,右边的翻译一下就是如果......不然.....,在不满足if时,才会判断else if. 下面的那个如果year不满足if中的条件的话就不会执行,if后面括号中的是用来判断的,只有符合条件才会执行大括号中的方法体 解决方案二: 右边的程序,只有当第一个条件不满足,才会判断第二个条件.左边不管第一个条件,都会判断第二个. 下面程序,不知道ye

[面试题]sizeof与strlen的区别

例题: constchar *p = "Hello World"; char p[] = "Hello World";分别求长度和所占用空间大小,有啥区别? 答:求长度都可以用strlen(p),求占内存空间大小第一个不能用sizeof,第二个可以用sizeof 另外:第二个:strlen(p) = 11, sizeof(p) = 12 举一反三: l   sizeof     sizeof(...)是运算符,在头文件中typedef为unsigned int,其值

C语言中关于sizeof 和 strlen的区别分析_C 语言

1.编译时计算运算符sizeof,可用类型或变量做参数,计算占用内存的大小.sizeof后若是类型必须加括弧,若是变量名可不加括弧.sizeof(x)可用来定义数组维数如: 复制代码 代码如下: printf("%d\n", sizeof(short));     输出的结果为短整型的长度2.用结构类型或变量做参数时,sizeof 返回实际的大小,当用于静态数组时,sizeof 返回全部数组的尺寸.sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸 2.运行时计算str

c语言-C语言sizeof(&amp;amp;quot;&amp;amp;quot;) strlen(&amp;amp;quot;&amp;amp;quot;)

问题描述 C语言sizeof("") strlen("") 在32位编译系统中,字符型变量占1个字节,则sizeof("") .strlen("")分别为()A.1 2 B.2 1 C.2 0 D. 2 2 求大侠详细解释 解决方案 sizeof("")=2 sizeof是编译器在编译时计算,计算括号中内容的大小,注意,这和地址没关系,因为这发生在编译期 那么""是多大呢?是1个字符,再

求重点针对vb6和netvb区别的学习教材

问题描述 有没有教材重点讲net的,vb6很熟悉的,求net和vb6区别. 解决方案 解决方案二:没人知道???解决方案三:既然vb6很熟悉,那就放下vb的姿态主动学习vb.net就行了.你自己来把握区别.10年前也许还能写一堆,因为那个时候正是vb的转型期,现在懒得写了.谁可能在这么多年之后还给重复介绍?欢迎你使用vb.net.不过建议你直接使用c#也不错哦.