关于sizeof,对空指针sizeof(*p)可以吗?
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)可以吗?的更多相关文章
- sizeof(int *) 和 sizeof(int)型的大小问题
小问题,暂时记录注意一下 printf("sizeof(int): %d\n", (int)sizeof(int)); printf("sizeof(int ...
- sizeof()与Marshal.SizeOf()的不同
在.NET中一般都是通过sizeof()或Marshal.SizeOf()来获取数据类型的大小,来简要地看一下它们二者有何不同. sizeof() sizeof()在MSDN中的介绍是,在编译时获得一 ...
- #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) ) 的意思就 ...
- 虚函数指针sizeof不为sizeof(void*)
ref:http://bbs.csdn.net/topics/360249561 一个继承了两个虚基类又增加了自己的一个虚函数pif的类,sizeof(指向pif的指针)竟然是8(X86).我是从这里 ...
- 数组类型与sizeof与指针的引用
以char类型为例: char a[100]; //a类型为char[100] &a类型为 char (*)[100] *a类型为char char *p = a; ...
- sizeof运算符、malloc函数及free函数
一.sizeof运算符的用法 1.sizeof运算符给出某个类型或变量在内存中所占据的字节数. int a; sizeof(a)=4; //sizeof(int)=4; double b; si ...
- 聊聊 C 语言中的 sizeof 运算
聊聊 sizeof 运算 在这两次的课上,同学们已经学到了数组了.下面几节课,应该就会学习到指针.这个速度的确是很快的. 对于同学们来说,暂时应该也有些概念理解起来可能会比较的吃力. 先说一个概念叫内 ...
- c/c++中关于sizeof、strlen的使用说明
sizeof: 一般指类型.变量等占用的内存大小(由于在编译时计算,因此sizeof不能用来返回动态分配的内存空间的大小) strlen: c字符串的长度(参数必须是字符型指针 char*,当数组名作 ...
- C语言中的sizeof()
sizeof,一个其貌不扬的家伙,引无数菜鸟竟折腰,小虾我当初也没少犯迷糊,秉着"辛苦我一个,幸福千万人"的伟大思想,我决定将其尽可能详细的总结一下. 但当我总结的时候才发现,这个 ...
随机推荐
- SSIS连接-左外连接
应用场景: 当有多个数据源时,可能是在不同的数据库,或者是一个数据源来自数据库,另一个来自excel文件,想要把他们合并,像sql的左外联接时,应用到 源1: select 'A01' GoodsNo ...
- Java编码优化
Java编码优化 1.尽可能使用局部变量 调用方法时传递的参数以及在调用中创建的临时变量都保存在栈中速度较快,其他变 量,如静态变量.实例变量等,都在堆中创建,速度较慢.另外,栈中创建的变量,随 着方 ...
- windows live writer 安装失败 0x80190194 解决方法
windows live writer已经停止更新,部分安装包无法下载. 改安装windows软件包即可,其中包含windows live writer的安装. 参考: http://jingyan. ...
- 定时器 & 日期时间对象 & 正则
1 JavaScript 计时事件 通过使用 JavaScript,有能力做到在一个设定的时间间隔之后来执行代码,而不是在函数被调用后立即执行,这称之为计时事件. 两个关键方法是: setInterv ...
- feign实现服务间的负载均衡
feign Feign是一个声明式的Web Service客户端,它使得编写Web Serivce客户端变得更加简单.我们只需要使用Feign来创建一个接口并用注解来配置它既可完成.它具备可插拔的注解 ...
- Author: Jan Odvarko, www.janodvarko.cz
/* * Author: Jan Odvarko, www.janodvarko.cz */ FBL.ns(function() { with (FBL) { function HelloWorld ...
- mac不限速下载百度网盘
本文转载自:https://blog.csdn.net/u010837612/article/details/80029212 相信大家都比较困惑,百度网盘客户端限速后一般只有几十K的下载速度,Win ...
- C-C++字符输出时遇到字符'\n','\0'区别
#include "iostream" #include "stdio.h" #include "stdio_ext.h" #include ...
- 【转载】UWP应用设置和文件设置:科普
数据有两个基本的分类,应用数据和用户数据,而用户数据则为由用户拥有的数据,如文档,音乐或电子邮件等,下面将大致的介绍一下应用数据的基本操作. 应用数据:应用数据包含APP的状态信息(如运行时状态,用户 ...
- C基础练习题
1.下面有关C程序操作过程的说法中,错误的是______. A.C源程序经过编译,得到的目标文件即为可执行文件 B.C源程序的链接实质上是将目标代码文件和库函数等代码进行连接的过程 C.C源程序不能通 ...