sizeof 运算符的实现
- 2024-11-08 09:04:00
- admin 原创
- 25
问题描述:
我尝试实现sizeof运算符。 我这样做了:
#define my_sizeof(x) ((&x + 1) - &x)
但对于任一数据类型,它最终总是给出结果“1”。
然后我用谷歌搜索了一下,找到了以下代码:
#define my_size(x) ((char *)(&x + 1) - (char *)&x)
如果进行了类型转换,代码就可以正常工作,我不明白为什么。此代码还可以完美地填充结构。
它还适用于:
#define my_sizeof(x) (unsigned int)(&x + 1) - (unsigned int)(&x)
有人可以解释一下类型转换后它是如何工作的吗?
解决方案 1:
指针减法的结果以元素为单位,而不是以字节为单位。因此,根据定义,第一个表达式的计算结果为1
。
除此之外,你真的应该在宏中使用括号:
#define my_sizeof(x) ((&x + 1) - &x)
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)
my_sizeof()
否则尝试在表达式中使用可能会导致错误。
解决方案 2:
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)
此my_sizeof()
宏在下列情况下不起作用:
sizeof 1
- 4 字节(对于具有 4 字节的平台int
)
my_sizeof(1)
- 根本无法编译。
sizeof (int)
- 4 字节(对于具有 4 字节的平台int
)
my_sizeof(int)
- 根本无法编译代码。
它只适用于变量。它不适用于诸如int
、float
等数据类型char
,诸如、、等文字2
,也不适用于诸如或之类的右值表达式3.4
。'A'
`a+b`foo()
解决方案 3:
#define my_sizeof(x) ((&x + 1) - &x)
&x
给出程序中声明的变量(假设为 double x)的地址,并将其加 1 给出可以存储类型 x 的下一个变量的地址(此处addr_of(x) + 8
,double 的大小为 8Byte)。
差异得出的结果是,x
在该内存量中可以存储多少个类型的变量,对于类型 x 来说,这个结果显然是 1(因为将其增加 1 并取差值就是我们所做的)。
#define my_size(x) ((char *)(&x + 1) - (char *)&x)
将其类型转换为char*
并取差值将告诉我们char
在给定的内存空间中可以存储多少个类型的变量(差值)。由于每个char
变量仅需要 1 个字节的内存,因此 (内存量)/1 将给出传递给宏的变量类型的两个连续内存位置之间的字节数,从而给出类型变量所需的内存量x
。
但是您无法将任何文字传递给该宏并知道它们的大小。
解决方案 4:
该sizeof
运算符是 C(和 C++)语言规范的一部分,并在编译器(前端)内部实现。无法使用其他 C 构造来实现它(除非您使用 GCC 扩展,如typeof),因为它可以接受类型或表达式作为操作数,而不会产生任何副作用(例如sizeof((i>1)?i:(1/i))
,当除以零时不会崩溃,i==0
但您的宏my_sizeof
会因除以零而崩溃)。另请参阅C 编码指南和维基百科。
您应该了解 C指针算法。例如,请参阅这个问题。指针差异以元素而不是字节表示。
解决方案 5:
但对于任何一种数据类型,它的结果总是为“1”
是的,这就是指针算法的工作原理。它以指向的类型为单位工作。因此,强制转换为以 为char *
单位工作char
,这正是您想要的。
解决方案 6:
这对于文字和变量都有效。
#define my_sizeof(x) (char*) (&(((__typeof__(x) *)0)[1])) - (char *)(&(((__typeof__(x) *)0)[0]))
解决方案 7:
#define my_sizeof(x) ((&x + 1) - &x)
这基本上是(两个内存值的差异)/(数据类型的大小)。
它给出可以存储多少个 x 类型元素的数字。即 1。您可以在此内存空间中容纳一个完整的 x 元素。
当我们将其转换为其他数据类型时,它表示该内存空间中可以存储多少个该数据类型的元素。
#define my_size(x) ((char *)(&x + 1) - (char *)&x)
将其类型转换为 (char *) 可以为您提供准确的内存字节数,因为 char 是一个字节。
#define my_sizeof(x) (unsigned int)(&x + 1) - (unsigned int)(&x)
当您将指针类型转换为 int 时,它会导致编译错误。
解决方案 8:
#define MY_SIZEOF(type) (unsigned int)( (type*)0 + 1)
将 NULL(0) ptr 转换为类型,然后加一。由于指针算法,编译器会根据类型增加大小。然后将其转换回无符号整数,因为我们想要表示大小。
还:
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)
依赖于正在定义的类型的变量。
来源:discord 上的 @Neo21。我的只是将其转换为unsigned int
。
解决方案 9:
我昨天搜索了这一点,发现了这个宏:
#define mysizeof(X) ((X*)0+1)
它仅扩展 X 一次(没有像 x++ 这样的表达式双重评估那样的错误),并且到目前为止运行良好。
解决方案 10:
定义 my_sizeof(x) ((&x + 1) - &x)
&x 给出变量的地址,将其加一 (&x + 1) 将给出可以存储另一个类型 x 的变量的地址。现在,如果我们对这些地址进行算术运算,如 ((&x + 1) - &x),那么它将告诉我们,在 ((&x + 1) - &x) 地址范围内可以存储 1 个类型 x 的变量。
现在,如果我们用 (char ) 对该内存量进行类型转换 [因为 char 的大小为 1 个字节,而增加 char 只会移动一个字节],那么我们将得到类型 x 所消耗的字节数
解决方案 11:
#include<bits/stdc++.h>
using namespace std;
//#define mySizeOf(T) (char*)(&T + 1) - (char*)(&T)
template<class T>
size_t mySizeOf(T)
{
T temp1;
return (char*)(&temp1 + 1) - (char*)(&temp1);
}
int main()
{
int num = 5;
long numl = 10;
long long numll = 100;
unsigned int num_un_sz = 500;
cout<<"size of int="<<mySizeOf(num) << endl;
cout<<"size of long="<<mySizeOf(numl) << endl;
cout<<"size of long long ="<<mySizeOf(numll) << endl;
cout<<"size of unsigned int="<<mySizeOf(num_un_sz) << endl;
return 0;
}
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件