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. 巨杉db

    巨杉数据库 and mongo db ,分布式数据库,

  2. 将JWT与Spring Security OAuth结合使用

    1.概述 在本教程中,我们将讨论如何使用Spring Security OAuth2实现来使用JSON Web令牌. 我们还将继续构建此OAuth系列的上一篇文章. 2. Maven配置 首先,我们需 ...

  3. This file's format is not supported or you don't specify a correct format. 解决办法

    string path = @"c:\请假统计表.xlsx"; Workbook workBook = new Workbook(); workBook.Open(path); A ...

  4. Nuxt使用记录

    代码及插件需要根据环境引入 (服务端没有window,document,浏览器端没有global) const myPlugins = { install(Vue, options) { Vue.pr ...

  5. java实现xml文件读取并保存到对象

    首先浅聊一下解析xml的四种方式: 1.DOM方式:有缺点但是这个缺点却也是他的优点.下面详细介绍: 以树形的层次结构组织节点或信息片断集合,可以获得同一个文档中的多处不同数据.使用起来简单. 优点是 ...

  6. Java @Validated 遇到的大坑

    我在一个Controller内,在两个方法内使用@Validated,这是两个POST方法会进入的方法,这两个方法的实体类的命名(下图红框内容)不能一样,一样的话就会导致第二个在页面显示不出来错误信息 ...

  7. html5响应式

    (function (doc, win) { var docEl = doc.documentElement, resizeEvt = ‘orientationchange’ in window ? ...

  8. 字典(dict),增删改查,嵌套

    一丶字典 dict 用{}来表示  键值对数据  {key:value}  唯一性 键 都必须是可哈希的 不可变的数据类型就可以当做字典中的键 值 没有任何限制 二丶字典的增删改查 1.增 dic[k ...

  9. 【复习笔记】CSS基础

    外观 color:rgba(255,255,255,1),a表示alpha,透明度值0~1 font-family:字体1,字体2,字体3;确保某字体不存在时自动选择下一个,最好使用字体的英文名称保证 ...

  10. 织梦dedecms手机版上下篇链接错误的解决方法

    打开 \include\arc.archives.class.php 1. 找到 $this->PreNext['pre'] = "上一篇:<a href='$mlink'> ...