详解C++ sizeof(上)

sizeof是C/C++中的一个操作符(operator),其作用是返回一个对象或者类型所占的内存字节数,使用频繁,有必须对其有个全面的了解。

1.sizeof的基本语法

sizeof有三种语法形式。

(1)sizeof(object); //sizeof(对象);
(2)sizeof(type_name); //sizeof(类型);
(3)sizeof object; //sizeof对象;

第三种语法结构虽然简约,但并不常见,为简单统一,建议使用第一和第二种写法。

int i;
sizeof( i ); // ok
sizeof i; // ok
sizeof( int ); // ok
sizeof int; // error

2.sizeof计算基本类型与表示式

sizeof计算对象的大小实际上是转换成对象类型进行计算,也就是说,同种类型的不同对象其sizeof值都是一致的。这里,对象可以进一步延伸至表达式,即sizeof可以对一个表达式求值,编译器根据表达式的最终结果类型来确定大小,sizeof是编译时进行运算,与运行时无关,不会对表达式进行计算。考察如下代码:

#include <iostream>
using namespace std;
int main(int argc,char* argv[])
{
cout<<"sizeof(char)="<<sizeof(char)<<endl;
cout<<"sizeof(short)="<<sizeof(short int)<<endl;
cout<<"sizeof(int)="<<sizeof(int)<<endl;
cout<<"sizeof(long)="<<sizeof(long int)<<endl;
cout<<"sizeof(long long)="<<sizeof(long int int)<<endl;
cout<<"sizeof(float)="<<sizeof(float)<<endl;
cout<<"sizeof(double)="<<sizeof(double)<<endl;
int i=8;
cout<<"i="<<i<<endl;
cout<<"sizeof(i)="<<sizeof(i)<<endl;
cout<<"sizeof(i)="<<sizeof(i=5)<<endl;
cout<<"i="<<i<<endl;
}

在64bits的Windows下运行结果如下:

sizeof(char)=1
sizeof(short)=2
sizeof(int)=4
sizeof(long)=4
sizeof(long long)=4
sizeof(float)=4
sizeof(double)=8
i=8
sizeof(i)=4
sizeof(i)=4
i=8

观察以上程序需要注意两点。

(1)i的值并未发生改变,表明sizeof括号内的表达式并没有执行,sizeof在编译时求其表达式的运算结果的类型,sizeof运算与运行时无关。sizeof(i)等价于sizeof(int),sizeof(i=5)等价于sizeof(int),也就是说在可执行代码中,并不包含i=5这个表达式,它早在编译阶段就被处理了。
(2)long int是否占8字节,与编译器的实现有关,Visual C++在VS2012中使用的编译器是cl.exe,在64bits的Windows下仍然将long编译为4字节,要想使用8字节长整型,保险起见,使用long long型。

3.sizeof计算指针变量

指针是C/C++的灵魂,它记录了一个对象的地址。指针变量的位宽等于机器字长,机器字长由CPU寄存器位数决定。在32位系统中,一个指针变量的返回值为4字节,64位系统中指针变量的sizeof结果为8字节。

char* pc = "abc";
int* pi=new int[10];
string* ps;
char** ppc = &pc;
void (*pf)(); // 函数指针
char testfunc()
{
return ‘k';
}
sizeof( pc ); // 结果为4
sizeof( pi ); // 结果为4
sizeof( ps ); // 结果为4
sizeof( ppc ); // 结果为4
sizeof( pf ); // 结果为4
sizeof( &testfunc ); // 结果为4
sizeof( testfunc ()); // 结果为1
sizeof(*( testfunc) ()); // 结果为1

考察以上代码,得出如下结论:

(1)指针变量的sizeof值与指针所指的对象类型没有任何关系,与指针申请多少空间没有关系,所有的指针变量所占内存大小均相等。那为什么在本机64bits系统下,指针变量大小仍然是4个字节,因为使用32位编译器编译得到程序是32位,故指针大小是4字节,可自行修改编译器版本,不再赘述。

(2)&testfunc代表一个函数指针,指针大小是4,所以sizeof(&testfunc)==4。testfunc()代表一次函数调用,返回值类型是char,所以sizeof(testfunc())==sizeof(char)==1。testfunc名本身就是一个函数指针,所以(*testfunc)()也是一次函数调用,sizeof((*testfunc)())==sizeof(char)==1

4.sizeof计算数组

当sizeof作用于数组时,求取的是数组所有元素所占用的大小。参考如下代码:

int A[3][5];
char c[]="123456";
double*(*d)[3][6];

cout<<sizeof(A)<<endl; //输出60
cout<<sizeof(A[4])<<endl; //输出20
cout<<sizeof(A[0][0])<<endl;//输出4
cout<<sizeof(c)<<endl; //输出7
cout<<sizeof(d)<<endl; //输出4
cout<<sizeof(*d)<<endl; //输出72
cout<<sizeof(**d)<<endl; //输出24
cout<<sizeof(***d)<<endl; //输出4
cout<<sizeof(****d)<<endl; //输出8

考察以上代码,得出如下结论:
(1)A的数据类型是int[3][5]A[4]的数据类型是int[5]A[0][0]数据类型是int。所以

sizeof(A)==sizeof(int[3][5])==3*5*sizeof(int)==60
sizeof(A[4])==sizeof(int[5])=5*sizeof(int)==20
sizeof(A[0][0])==sizeof(int)==4

尽管A[4]的下标越界,但不会造成运行时错误,因为sizeof运算只关心数据类型,在编译阶段就已经完成。

(2)由于字符串以空字符'\0'结尾,所以c的数据类型是char[7],所以sizeof(c)=sizeof(char[7])==7。

(3)d是一个指针,不管它指向的对象是什么数据类型,自身大小永远是4,所以sizeof(d)==4。sizeof(*d)的数据类型是double*[3][6],所以

sizeof(*d)==sizeof(double*[3][6])==3*6*sizeof(double*)==18*4==72

同理,可以推算出

sizeof(**d)==sizeof(double*[6])==6*sizeof(double*)==24
sizeof(***d)==sizeof(double*)==4
sizeof(****d)=sizeof(double)==8

当数组作为函数形参时,下面的i和j的值应该是多少呢?

void foo1(char a1[3])
{
int i = sizeof( a1 ); // i == ?
}
void foo2(char a2[])
{
int j = sizeof( a2); // j == ?
}

也许当你试图回答j的值时已经意识到i答错了,是的,i!=3。这里函数参数a1已不再是数组类型,而是蜕变成指针,相当于char* a1,为什么?仔细想想就不难明白,我们调用函数foo1时,程序会在栈上分配一个大小为3的数组吗?不会!数组是“传址”的,调用者只需将实参的地址传递过去,所以a1自然为指针类型(char*),i的值也就为4,同样j也是4。

以上就是详解C++ sizeof(上)的详细内容,更多关于C++ sizeof的资料请关注我们其它相关文章!

(0)

相关推荐

  • C++无法重载点符号、::、sizeof等的原因

    大多数的运算符能够被程序员重载.例外的是:     . (点符号) :: ?: sizeof 并没有什么根本的原因要禁止重载?:.仅仅是因为,我没有发现有哪种特殊的情况需要重载一个三元运算符.注意一个重载了 表达式1?表达式2:表达式3 的函数,不能够保证表达式2:表达式3 中只有一个会被执行. Sizeof 不能够被重载是因为内建的操作(built-in operations),诸如对一个指向数组的指针进行增量操作,必须依靠它.考虑一下: X a[10]; X* p = &a[3]; X* q

  • C++ sizeof 实例解析

    在C++中使用sizeof要比C复杂很多,因为C++类中有static静态变量,virtual虚函数,还有继承.派生等.sizeof是C语言的一种单目操作符,如C语言的其他操作符++.--等.它并不是函数.sizeof操作符以字节形式给出了其操作数的存储大小.sizeof使用形式有三种:sizeof(var_name)或sizeof var_name或sizeof(var_type). [例1]:(列子中忽略构造及析构函数) 复制代码 代码如下: class A  {      public:

  • C/C++中的sizeof运算符和size_t类型的详解

    sizeof的作用 sizeof是c的运算符之一,用于获取操作数被分配的内存空间,以字节单位表示. 这里指的操作数,可以是变量,也可以是数据类型,如int,float等.所以就可以通过它来获取本地c库定义的基本类型的范围. sizeof的使用 1.对于一般变量,形式2种:sizeof a 或 sizeof(a); 2.对于数据类型,必须使用带括号的方式,如sizeof(int). size_t的说明 size_t是标准C库中定义的,应为unsigned int,在64位系统中为 long uns

  • 详解C++编程中的sizeof运算符与typeid运算符

    sizeof 运算符 产生与 char 类型的大小有关的操作数大小. 语法 sizeof unary-expression sizeof ( type-name ) 备注 sizeof 运算符的结果为 size_t 类型,它是包含文件 STDDEF.H 中定义的整数类型.利用此运算符,你可以避免在程序中指定依赖于计算机的数据大小. sizeof 的操作数可以是下列项之一: 类型名称.若要将 sizeof 用于类型名称,则该名称必须用括号括起. 一个表达式.当用于表达式时,无论是否使用括号都可指定

  • C/C++ 中sizeof('a')对比详细介绍

    C/C++ 中sizeof('a')的值对比详细介绍 C语言: char a = 'a'; sizeof(char) = 1 sizeof(a) = 1 sizeof('a') = 4 C++语言: char a = 'a'; sizeof(char) = 1 sizeof(a) = 1 sizeof('a') = 1 字符型变量是1字节这个没错,奇怪就奇怪在C语言认为'a'是4字节,而C++语言认为'a'是1字节. 原因如下: C99标准的规定,'a'叫做整型字符常量(integer char

  • 浅析C/C++中被人误解的SIZEOF

    1:sizeof是一个函数吗?2:sizeof与strlen的区别?3:sizeof(int)(*p)的值是多少? 复制代码 代码如下: int a[10];   sizeof(a);//是多少?   sizeof(a[10]);//是多少?   void f(int a[10])   {     cout<<sizeof(a)<<endl;//值是多少?   }View Code 解答:1:对于第一个问题,sizeof 不是一个函数,而是一个语言内置的关键字,不信你试试sizeo

  • 详解C++ sizeof(上)

    sizeof是C/C++中的一个操作符(operator),其作用是返回一个对象或者类型所占的内存字节数,使用频繁,有必须对其有个全面的了解. 1.sizeof的基本语法 sizeof有三种语法形式. (1)sizeof(object); //sizeof(对象); (2)sizeof(type_name); //sizeof(类型); (3)sizeof object; //sizeof对象; 第三种语法结构虽然简约,但并不常见,为简单统一,建议使用第一和第二种写法. int i; sizeo

  • 详解C++ sizeof(下)

    sizeof作用于基本数据类型,在特定的平台和特定的编译器中,结果是确定的,如果使用sizeof计算构造类型:结构体.联合体和类的大小时,情况稍微复杂一些. 1.sizeof计算结构体 考察如下代码: struct S1 { char c; int i; }; cout<<"sizeof(S1)="<<sizeof(S1)<<endl; sizeof(S1)结果是8,并不是想象中的sizeof(char)+sizeof(int)=5.这是因为结构体或

  • C语言详解关键字sizeof与unsigned及signed的用法

    目录 最冤枉的关键字sizeof理解 被误解为函数 sizeof(int)*p 表示什么意思 signed与unsigned 关键字 有符号整数vs无符号整数 整形在内存的存储 原码 反码 补码 存储的本质 十进制二进制快速转化 为什么存储的是补码 大小端 最冤枉的关键字sizeof理解 sizeof:确定一种类型在开辟空间的时候的大小. 被误解为函数 sizeof是关键字而不是函数,可以借助编译器来确定它的身份. #include<stdio.h> int main() { int a =

  • Java Fluent Mybatis 项目工程化与常规操作详解流程篇 上

    目录 前言 Maven依赖 配置文件调整 Knife4j配置 添加必要实体 增/改 总结 前言 接着上一篇,上篇已经测试通过,成功添加了数据.那么这篇主要是继续上一个项目,将项目进行工程化包装,增加一些必要配置,并且生成增删改查接口. GitHub代码仓库:GitHub仓库 Maven依赖 增加了druid数据库连接池,所以之前的配置文件也需要调整,下面会发出来. <dependency> <groupId>cn.hutool</groupId> <artifac

  • 详解在网页上通过JS实现文本的语音朗读

    摘要: 语音合成:也被称为文本转换技术(TTS),它是将计算机自己产生的.或外部输入的文字信息转变为可以听得懂的.流利的口语输出的技术. 1.接口定义 http://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&spd=2&text=你要转换的文字 参数说明: lan=zh:语言是中文,如果改为lan=en,则语言是英文. ie=UTF-8:文字格式. spd=2:语速,可以是1-9的数字,数字越大,语速越快. text=**:这个就是你要转换的

  • 详解vue 图片上传功能

    这次做了vue页面的图片上传功能,不带裁剪功能的! 首先是html代码,在input框上添加change事件,如下: <ul class="clearfix"> <li v-if="imgs.length>0" v-for='(item ,index ) in imgs'> <img :src="item"> </li> <li style="position:relative

  • 详解bootstrap-fileinput文件上传控件的亲身实践

    经理让我帮服务器开发人员开发一个上传文件功能界面,我就想着以前使用过bootstrap-fileinput插件进行文件上传,很不错.赶紧就撸起来了. 1.下载压缩包.插件地址https://github.com/kartik-v/bootstrap-fileinput/ ,下载压缩包解压之后,拿出fileinput.min.js.fileinput.min.css.和中文需要引用的插件zh.js,因为这款插件默认的语言是英语.把这几个文件引入进页面 2.文件的引入顺序 引入bootstrap.m

  • 详解ftp文件上传下载命令

    介绍:从本地以用户wasqry登录的机器1*.1**.21.67上通过ftp远程登录到ftp服务器上,登录用户名是lte****,以下为使用该连接做的实验. 查看远程ftp服务器上用户lte****相应目录下的文件所使用的命令为:ls,登录到ftp后在ftp命令提示符下查看本地机器用户wasqry相应目录下文件的命令是:!ls.查询ftp命令可在提示符下输入:?,然后回车.   1.从远程ftp服务器下载文件的命令格式: get  远程ftp服务器上当前目录下要下载的文件名  [下载到本地机器上

  • 详解SpringBoot文件上传下载和多文件上传(图文)

    最近在学习SpringBoot,以下是最近学习整理的实现文件上传下载的Java代码: 1.开发环境: IDEA15+ Maven+JDK1.8 2.新建一个maven工程: 3.工程框架 4.pom.xml文件依赖项 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation

  • 详解Spring boot上配置与使用mybatis plus

    http://mp.baomidou.com/#/?id=%e7%ae%80%e4%bb%8b这个是mybatisplus的官方文档,上面是mybtisplus的配置使用方法,以及一些功能的介绍 下面开始配置 maven依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <

随机推荐