为什么指针在此处被类型转换为 char?

Why pointer is typecasted as a char here?

我通过这个程序来查找结构的长度而不使用 sizeof。我有一些问题找不到答案。

  1. 我无法理解这一步 (char*)(p+1)-(char*)p) - 为什么将指针类型转换为 char。

  2. 我打印出了每种数据类型的大小。因此,结构的大小应该是 3* int 的大小 + float 的大小 + char 的大小 = 17。但是,结构的大小是 20。请解释如何。

  3. 为什么 (float*)(p+1)-(float*)p) 的输出是 5。

代码:

#include<stdio.h>

struct sample
{
    int a,b;
    float c;
    char z;
    int k;
};

void main()
{
    struct sample *p;
    struct sample x;
    printf("size of struct w/o using sizeof: %d\n", (char*)(p+1)-(char*)p);

    printf("size of struct w/o using sizeof: %d\n", (float*)(p+1)-(float*)p);

    printf("size of struct using sizeof: %d\n", sizeof(struct sample));

    printf(" %d %d %d %d\n", sizeof(char), sizeof(int), sizeof(float), sizeof(x));

}

输出:

size of struct w/o using sizeof: 20
size of struct w/o using sizeof: 5
size of struct using sizeof: 20
1 4 4 20

4) 感谢您的回答。我还有一个疑问。

代码

struct sample
{
int a,b;
float c;
char z;
int k;
char s;
};

填充后,该结构的大小为 24 字节。为什么在 float (float)((float*)(p+1)-(float*)p) 中打印它不会给出 5.8000 而不是 6。

  1. 以字节为单位转换会得到两个指针之间的字节差

  2. 您的结构将填充对齐到 4 字节边界。在您的结构中,真实尺寸如下(包括填充)

    struct sample
    {
         int a,b; // 8 bytes, 4 bytes each
         float c; // 4 bytes
         char d; // 4 bytes, 1 byte + 3 padding
         int k; // 4 bytes
    }
    
  3. 转换为浮点数将为您提供浮点数中的 sizeof 结构(5 个浮点数 = 20 字节)

  1. 类型转换为 (char*),因为您要以 char(字节)为单位打印大小。当你增加 p 时,它会增加 p 的大小。所以 (p+1)-p 是结构的大小, (char *) 帮助以字节为单位打印它。

  2. 了解结构对齐和填充

  3. 5 因为这次它被类型转换为 (float *) 因为你想以 float(4 字节)为单位打印大小。当你增加 p 时,它会增加 p 的大小。所以 (p+1)-p 是结构的大小, (float *) 帮助打印它的浮点数(4 字节)。

  1. 尽管 (char*)(p+1) - (char*)p) 承诺不使用 sizeof *p,但它隐含地这样做了,因为指向 p 的指针乘以它们各自类型的大小... . C99中提到了这样的:http://www.iso-9899.info/n1256.html#FOOTNOTE.91

  2. 许多 cpu 架构,包括英特尔 x86 系列处理器需要在可被其大小整除的地址读取其多字节整数,例如 4 -byte 类型的地址必须能被 4 整除。这意味着,当创建数组时 struct,第二个元素的 ints 必须 also即使您的 char 在末尾,也能被 4 整除。这就是为什么要在此处添加填充并将其包含在结构的总大小中的原因。

  3. 此结果是结构的大小除以 float 类型的大小。因为我们现在知道你的结构的大小是 20,所以 p+1 计算出 p 之后 20 个字节的地址,但随后它被强制转换为 float*,它将偏移量除以适合的浮点数进入区间