27

我已经尝试实现 sizeof 运算符。我是这样做的:

#define my_sizeof(x) ((&x + 1) - &x)

但它总是以任何一种数据类型的结果为“1”。

然后我用谷歌搜索了它,我发现了以下代码:

#define my_size(x) ((char *)(&x + 1) - (char *)&x)

如果是typecasted,代码就可以工作,我不明白为什么。这段代码也完美地填充了一个结构。

它也适用于:

#define my_sizeof(x) (unsigned int)(&x + 1) - (unsigned int)(&x)

任何人都可以解释一下如果类型转换它是如何工作的?

4

10 回答 10

31

指针减法的结果是元素而不是字节。因此,第一个表达式1根据定义计算为。

除此之外,你真的应该在宏中使用括号:

#define my_sizeof(x) ((&x + 1) - &x)
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)

否则尝试my_sizeof()在表达式中使用可能会导致错误。

于 2013-01-05T11:04:59.877 回答
8

运算符是 C(和 C++)语言规范的sizeof一部分,并在编译器(前端)内部实现。没有办法用其他 C 构造来实现它(除非你使用像typeof这样的 GCC 扩展),因为它可以接受类型或表达式作为操作数,而不会产生任何副作用(例如sizeof((i>1)?i:(1/i)),当i==0你的宏my_sizeof会崩溃时不会崩溃)除以零)。另请参阅C 编码指南维基百科

您应该了解 C指针算法。参见例如这个问题。指针差异以元素而不是字节表示。

于 2013-01-05T11:05:29.647 回答
8
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)

my_sizeof()宏在以下情况下不起作用:

  1. sizeof 1- 4 字节(对于具有 4 字节的平台int
    my_sizeof(1)- 根本无法编译。

  2. sizeof (int)- 4 字节(对于具有 4 字节的平台int
    my_sizeof(int)- 根本不会编译代码。

它仅适用于变量。它不适用于 , 等数据类型,不适用于int, float,char等文字2,也不适用于or等​​右值表达式。3.4'A'a+bfoo()

于 2016-02-03T14:29:56.067 回答
7
#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

但是您将无法将任何文字传递给该宏并知道它们的大小。

于 2016-05-04T05:47:17.430 回答
6

但它总是以任何一种数据类型的结果为“1”

是的,这就是指针算法的工作原理。它以所指向的类型为单位工作。因此,转换为 的char *工作单位char,这就是您想要的。

于 2013-01-05T11:04:57.643 回答
2

这适用于文字和变量。

#define my_sizeof(x) (char*) (&(((__typeof__(x) *)0)[1])) - (char *)(&(((__typeof__(x) *)0)[0]))
于 2020-08-09T07:19:08.810 回答
0

我昨天搜索了这个,我发现了这个宏:

#define mysizeof(X)  ((X*)0+1)

它仅将 X 扩展一次(没有错误,因为像 x++ 这样的表达式的双重评估),并且直到现在它都可以正常工作。

于 2018-06-26T14:21:26.583 回答
0
#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 时,它会给您带来编译错误。
于 2021-11-14T17:51:56.797 回答
-1

# 定义 my_sizeof(x) ((&x + 1) - &x)

&x 给出变量的地址并将其加一 (&x + 1),将给出地址,其中可以存储另一个 x 类型的变量。现在,如果我们对这些地址进行算术运算,例如 ((&x + 1) - &x),那么它将告诉在 ((&x + 1) - &x) 地址范围内,可以存储 1 个 x 类型的变量。

现在,如果我们用 (char *) 对内存量进行类型转换[因为 char 的大小是 1 个字节,并且 char * 递增只会移动一个字节],那么我们将得到类型 x 消耗的字节数

于 2015-10-24T08:28:29.210 回答
-1
#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;
}
于 2019-03-13T21:11:42.967 回答