c++中的sizeof,可以通过以下宏定义实现。

 #include <stdio.h>

 #define sizeof_T(T) ((size_t)((T*)0+1))             ///求类型的大小
#define sizeof_V(T) ((size_t)(&T+1)-(size_t)(&T)) ///求变量的大小 int main() {
int a=, b[]={};
printf("这个类型大小:%d \n这个类型单个变量的大小:%d \n这个类型数组变量的大小%d\n", sizeof_T(int), sizeof_V(a), sizeof_V(b));
return ;
}

那么为什么可以这样实现呢?

对于求类型大小的sizeof_T:

首先我们通过(T*)0得到一个指向00000000的指针,而且这个指针是int类型的,现在我们将这个指针+1。比如我们用一个int *p指针指向一块new int[10]的地址,那么此时很显然(p+1)-p==4而不是1,因为我们其实不是在地址上加1,而是让指针向前前进了一步,而这一步就是T这个类型的大小,也就是我们求的其实是指针步长。

可以通过以下程序发现这个特点,然后我们将00000000位置的指针向前移动一步,很显然,这个时候我们就得到了这个类型的大小。

 #include <stdio.h>
#include <iostream>
using namespace std;
int main() {
char *p=new char[];
int *q=new int[];
printf("%p %p\n%p %p\n", p, p+, q, q+);
delete p;
delete q;
return ;
}

对于求变量大小的sizeof_V:

也是利用了指针步长的原理,这里值得注意的有两点.

一是因为这里我们不是类型,所以说不可能定义一个指向0的指针,只能将自己的地址拿来运算。

二是数组名有一个特性,对于int p[10];这个数组,&p+1的值并不是数组首地址加上指针步长,此时的步长是数组本身,也就是一步跨越了整个数组。

第二点可以通过以下程序来验证

 #include <stdio.h>
int main() {
int p[];
printf("%p %p\n", p, &p+);
return ;
}

所以由以上特性我们就可以手动实现sizeof的功能了,说白了就是求指针步长。

我们既然知道了对数组来说&T+1相当于一步跨过整个数组,那么这是为什么呢,我由自己的做出相应的猜测,如有错误请在评论区指出。

对于int p[10];这个数组来说&p和什么相等呢?我测试的结果是&p==p[][10],也就是&p等于一个二维数组的数组名。也就是相当于将p提高了一个维度,原因就是如下的代码:

#include <stdio.h>
int main() {
int p[][], T[];
printf("%p %p\n%p %p\n", p, p+, T, &T+);
return ;
}

在运行了代码后你会发现p+1和&T+1的步长都是8。

那么其实就是对于数组,我们将他本身作为一个变量类型,就是相当于int [10]是一个变量类型。

再次感受到了那些大佬们的牛逼。

c++ sizeof的实现的更多相关文章

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

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

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

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

  3. sizeof(转载)

    原文地址:http://blog.sina.com.cn/s/blog_5da08c340100bmwu.html 转载至:http://www.cnblogs.com/wangkangluo1/ar ...

  4. C语言中的sizeof()

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

  5. 你必须知道的指针基础-4.sizeof计算数组长度与strcpy的安全性问题

    一.使用sizeof计算数组长度 1.1 sizeof的基本使用 如果在作用域内,变量以数组形式声明,则可以使用sizeof求数组大小,下面一段代码展示了如何使用sizeof: ,,,,,}; int ...

  6. c++面试常用知识(sizeof计算类的大小,虚拟继承,重载,隐藏,覆盖)

    一. sizeof计算结构体 注:本机机器字长为64位 1.最普通的类和普通的继承 #include<iostream> using namespace std; class Parent ...

  7. c语言 sizeof理解

    1.基本数据类型 char :1     short:2   int 4    long 4   long long :8    float:4    double :8字节. 2.数组:对应的基本数 ...

  8. sizeof与strlen的区别

    1 sizeof是操作符,而strlen是库函数: 2 sizeof的参数可以为任意变量或类型,而strlen必须以char*做参数,且字符串必须以‘/0’结尾: 3 数组名用作sizeof参数时不会 ...

  9. sizeof

    一.sizeof使用的场合: 1.sizeof操作符的一个主要用途是与存储分配和I/O系统那样的例程进行通信.例如: void* malloc(size_t size); size_t fread(v ...

  10. strlen()和sizeof()求数组长度

    在字符常量和字符串常量的博文里有提: 求字符串数组的长度 标准库函数strlen(s)可以返回字符串s的长度,在头文件<string.h>里. strlen(s)的判断长度的依据是(s[i ...

随机推荐

  1. 三维显示插件——C++

    Qt 3D 构建自己的C/C++插件开发框架——系列:https://blog.csdn.net/chgaowei/article/details/4545211 如何使用Qt 3D开发3D场景程序: ...

  2. document.referer

    参考文章: 深入理解document.referrer的用法

  3. picker组件 label组件讲解

    label组件:包住表单的组件,将里面的表单和label里的元素,紧紧的包在一起,当触发label里的元素,就相当于触发了表单组件 属性:for:类型 字符串 表单的 id 的值 picker组件:是 ...

  4. 数据库-SqlServer 行转列,列转行

    两篇行转列,列转行的实例文章: 第1篇:https://www.cnblogs.com/cpcpc/archive/2013/04/08/3009021.html 第2篇:https://mp.wei ...

  5. qbzt day3 晚上 平衡树的一些思想

    pks大佬的blog 二叉查找树 任何一个节点左子树的所有元素都小于这个节点,右子树的所有元素都大于这个节点 查找一个节点:从根节点开始,比他小就向左走,比他大就向右走 平衡树:解决二叉查找树的一些痛 ...

  6. EF6中一个关于时间类型 datetime2 的坑

    在一个访问下位机的程序中,返回的时间戳有时候因断线产生0001年01月01日的时间,而原先使用拼接SQL进行数据存储的操作时,这个问题是可以跳过的. 这次把拼接SQL的部分重新改为EF进行管理,这个坑 ...

  7. servlet过滤器Filter使用之DelegatingFilterProxy类

    正常情况下,我们需要添加一个过滤器,需要实现javax.servlet.Filter接口,再在web.xml中配置filter,如下: package cc.eabour.webapp.securit ...

  8. 42 grant与flush privileges

    42 grant与flush privileges 在mysql里, grant是给用户赋权的,一些文档中经常提到在grant执行后,马上执行一个flush privileges,才能使赋权语句生效, ...

  9. Parcel在binder通信readStrongBinder和writeStrongBinder

    Binder IPC通信中,Binder是通信的媒介,Parcel是通信的內容.远程调用过程中,其参数都被打包成Parcel的形式来传递. 在IPC通信的Proxy端,我们经常可以看到下面类似的代码, ...

  10. 剑指offer(2):字符串

    C语言中的字符串 C语言中字符串的存储方式和数组类似,都是连续定长的内存块.字符串数组以\0结尾,所以会比正常数组多一位,char str3[5] = "1234"; //此处赋值 ...