C/C++的sizeof在动态分配内存时经常用到,但之前一直没怎么关注它的具体机制。今天在为一个复杂声明的指针分配内存时,想起来要了解一下sizeof到底是什么?

先抛个问题:

  程序运行过程中对空指针解引用,程序会直接core。那么sizeof对一个空指针“解引用”行不行?(int p=nullptr; size_t iSize=sizeof(*p))。比如如下应用场景:

  int (*p)[10] = nullptr;/*p是一个指向有10个int型元素的数组的指针*/

  如果要分配5个数组的空间,用malloc(5 * 10 * 4)吗?还是用malloc(5 * 10 * sizeof(int))?从结果来看,都能实现。但如果上述数组的类型、大小可能会变化,比如数组大小变成11,就得在声明和分配处分别修改代码,难免会改漏。一种可行的方式是用一个宏来表示数组大小。这里,我想换个方式,指针声明时明确了数组大小,所以能不能在malloc的时候用sizeof计算出指针的元素大小(即数组大小,注意此时指针是空的),从而只需要在声明时说明数组大小,避免在malloc的时候再关心数组多大?

  答案是可以。这条语句是合法的:p = (int (*)[10])malloc(5 * sizeof(*p))。这里sizeof的参数p是空指针,下面解释为什么这里的*p是合法的。

什么是sizeof,以及它的机制?

  sizeof的一般使用形式都是sizeof( xx ),所以sizeof是不是一个函数呢?答案是看情况。有些编程语言里,sizeof是函数,这个不细讲(因为我也不会几种编程语言)。在C/C++里,sizeof不是函数,是一个内置的运算符或操作符,跟“ + - * / ”一样的运算符。sizeof可以返回一个类型或者对象所占用的内存空间字节数。

  而且关键的,sizeof的参数是类型(如sizeof(int)),或者是具体某个变量的类型(如int* p, sizeof(*p),这里的参数是int*)。sizeof是编译器在编译阶段解析并完成计算的,运行阶段并没有sizeof。所以对一个空指针执行sizeof(*p),实际上等价于对p指向的对象的类型作sizeof,而且是在编译阶段就完成了,没解引用,所以是合法的。

  这里分享个《C专家编程》第2章的例子:

  a = N * sizeof * q;/*这里有几个乘号?答案是1个。sizeof操作符把指针q指向的东西作为操作数(即*q)*/

  有意思的是上面这个例子,sizeof的参数没用括号,在函数调用里这显然不合法,但sizeof是操作符就是任性。当sizeof的操作数是类型名时,两边必须加括号,但操作数如果是变量则可以不加括号。

  apple = sizeof(int) * a;/*这个例子书上没给答案。事实上,这里先计算sizeof(int),然后再乘以a的值*/

  最后回到开篇的问题,给p分配内存的另一种方式:

  typedef int pPtr[10];/*为了方便我们用自定义类型*/

  pPtr* p=nullptr;/*相当于int (*p)[10] = nullptr;*/

  p = (int (*)[10])malloc(5 * sizeof(*p))。

  这里sizeof对空指针操作了*p,实际并未解引用,而是在编译阶段计算出指针p指向的类型的大小,所以是合法的。

  

  

关于sizeof,对空指针sizeof(*p)可以吗?的更多相关文章

  1. sizeof(int *) 和 sizeof(int)型的大小问题

    小问题,暂时记录注意一下   printf("sizeof(int): %d\n", (int)sizeof(int));     printf("sizeof(int ...

  2. sizeof()与Marshal.SizeOf()的不同

    在.NET中一般都是通过sizeof()或Marshal.SizeOf()来获取数据类型的大小,来简要地看一下它们二者有何不同. sizeof() sizeof()在MSDN中的介绍是,在编译时获得一 ...

  3. #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )

    原文 功能: 首先,sizeof(int)肯定是2的次方数,比如32位是4,64位是8 ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) 的意思就 ...

  4. 虚函数指针sizeof不为sizeof(void*)

    ref:http://bbs.csdn.net/topics/360249561 一个继承了两个虚基类又增加了自己的一个虚函数pif的类,sizeof(指向pif的指针)竟然是8(X86).我是从这里 ...

  5. 数组类型与sizeof与指针的引用

    以char类型为例: char a[100];     //a类型为char[100]    &a类型为 char (*)[100]    *a类型为char char *p = a;     ...

  6. sizeof运算符、malloc函数及free函数

    一.sizeof运算符的用法 1.sizeof运算符给出某个类型或变量在内存中所占据的字节数. int a;  sizeof(a)=4;  //sizeof(int)=4; double b;  si ...

  7. 聊聊 C 语言中的 sizeof 运算

    聊聊 sizeof 运算 在这两次的课上,同学们已经学到了数组了.下面几节课,应该就会学习到指针.这个速度的确是很快的. 对于同学们来说,暂时应该也有些概念理解起来可能会比较的吃力. 先说一个概念叫内 ...

  8. c/c++中关于sizeof、strlen的使用说明

    sizeof: 一般指类型.变量等占用的内存大小(由于在编译时计算,因此sizeof不能用来返回动态分配的内存空间的大小) strlen: c字符串的长度(参数必须是字符型指针 char*,当数组名作 ...

  9. C语言中的sizeof()

    sizeof,一个其貌不扬的家伙,引无数菜鸟竟折腰,小虾我当初也没少犯迷糊,秉着"辛苦我一个,幸福千万人"的伟大思想,我决定将其尽可能详细的总结一下. 但当我总结的时候才发现,这个 ...

随机推荐

  1. 持续集成~Jenkins构建dotnetCore的项目

    上周一个大件就是dotnet core2.0发布了,伴随着.NET Standard2.0也发布了,整个微软的生态环境大好,当然也有一个BUG出来了,比如EFCore对Mysql的支持比起1.1来说, ...

  2. RESTful API设计相关

    一  RESTful架构 在当今时代,越来越多人意识到了网站即软件. 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high laten ...

  3. Java虚拟机内存分配与回收策略

    内存分配与回收策略 Minor GC 和 Full GC Minor GC:发生在新生代上,因为新生代对象存活时间很短,因此 Minor GC 会频繁执行, 执行的速度一般也会比较快. Full GC ...

  4. java类及编写public类的基础点

    1.一个java文件中只能有一个public类.且公共类名称必须与java文件名一致,否则会出现错误提示.与其他面向对象编程语言的一样,在利用java分析问题时,基本思路即为将问题的属性(静)与行为( ...

  5. Android Framework中的Application Framework层介绍

    Android的四层架构相比大家都很清楚,老生常谈的说一下分别为:Linux2.6内核层,核心库层,应用框架层,应用层.我今天重点介绍一下应用框架层Framework,其实也是我自己的学习心得. Fr ...

  6. UML的九种模型图

    本文转自UML 的九种模型图,仅供学习交流! 一.作为一种建模语言,UML的定义包括UML语义和UML表示法两个部分. UML语义:描述基于UML的精确元模型定义. UML表示法:定义UML符号的表示 ...

  7. userBean设置属性2

    package com.java.model; public class Student { private String name;private int age; public String ge ...

  8. 使用脚本在Linux服务器上自动安装Kubernetes的包管理器Helm

    Helm之于Kubernetes好比yum之于Red Hat Enterprise Linux,或者apt-get之于Ubuntu. Helm是由helm CLI和Tiller组成,是典型的Clien ...

  9. UVALive 5031 Graph and Queries (Treap)

    删除边的操作不容易实现,那么就先离线然后逆序来做. 逆序就变成了合并,用并存集判断连通,用Treap树来维护一个连通分量里的名次. Treap = Tree + Heap.用一个随机的优先级来平衡搜索 ...

  10. Android(java)学习笔记122:BroadcastReceiver之 有序广播和无序广播(BroadcastReceiver优先级)

    之前我们在Android(java)学习笔记178中自定义的广播是无序广播,下面我们要了解一下有序广播: 1. 我们首先了解一下有序广播和无序广播区别和联系? (1)有序广播> 接受者有优先级, ...