【问题标题】:How come you can cast a pointer to an integer, but not a double? (C)为什么你可以将指针转换为整数,而不是双精度? (C)
【发布时间】:2014-07-21 16:56:44
【问题描述】:

我正在做一个随机练习,给定一个整数数组和双精度数组,你应该计算整数和双精度数的大小。

对于整数大小,我只是简单地使用两个指针指向两个相邻的数组,然后我找到它们的区别。因为指针算法将其计算为差 1,所以我将指针转换为整数,因为我假设指针将明确引用 4 个字节的内存,并且我得到了正确的结果 (4)。

现在,我为双打尝试了同样的操作,但我得到了这个错误:pointer value used where a floating point value was expected

一个可能的猜测是双精度是 8 个字节,而指针是 4 个字节。但我不确定这是否真的重要。

有什么见解吗?

我的确切路线:

int doubSize = (double)doubPtr2 - (double)doubPtr1;
//where doubtPtr1 and doubPtr2 poiny to two adjacent indexes of double array

【问题讨论】:

  • 这个问题不需要任何这样的转换,甚至不需要为任何类型的数组使用不同的代码。
  • 你不能使用sizeof吗?代码示例也会非常有用。
  • @aruisdante sizeof 是不允许的。
  • 给定的函数只是一个大小为 10 的双精度数组和两个双指针,所以我想利用所有这三个。铸造是我能想到的唯一解决方案。

标签: c pointers casting


【解决方案1】:

标准允许将指针强制转换为整数类型,但除非类型足够大,否则强制转换不会恢复原始指针。尽管如此,实际的映射是由实现定义的,尽管有人建议它应该模仿底层的内存架构,这极大地限制了这样做的效用。没有为浮点类型提供此类许可。
请查看intptr_t 以了解保证足够大的类型。

无论如何,更好(和正确)的方法是获取指向相邻数组元素的指针,将它们转换为char*char 保证为一个字节大,一个字节不保证为八位字节),而不是减去它们。 (结果类型应该是size_t 算子)

这假设你的练习,sizeof 被任意禁止,否则这将是这里选择的解决方案。

【讨论】:

  • @Dedupilcator 我可以问一下转换为 char* 的原因吗?
  • @SpagGuy,这是因为 char 是一个字节长。其上的指针算法将给出实际字节。例如,如果你将它转换为 int 之类的东西,你的结果将是 sizeof(int)。
  • @TRKemp 嗯,好吧,我对 C 语言非常陌生,很想理解这一点。我实际上对整个铸造的事情感到困惑,并且觉得我的整数解决方案很幸运(练习提到了铸造,所以我认为它与解决方案有关)。整数数组占用数组的每个索引 4 个字节。任何指针都包含指向一个地址的 4 个字节的数据。假设您将一个 int 指针指向整数数组的第一个索引。然后它引用该整数的 4 字节内存。
  • 您将 char 指针指向该整数数组的第二个索引。因为 char 指针通常指向 1 个字节,所以现在 char 指针实际上指向的是数组内存的哪一部分?第 5 个字节?还是另外 4 个字节(第 5-8 个字节)?
  • 如果你这样做,“char* b=&i[1]”,其中i是一个int数组,b将指向i数组的第二个元素,也就是第五个数组的字节。这假定int 是四个字节长。当我发现这样的概念令人困惑时,我经常会编写一个小程序并在调试器中使用它。
【解决方案2】:

将双精度指针转换为双精度并没有做你认为它正在做的事情,或者至少我不认为它是......参见例如:

int main(int argc, char *argv)
{
  double *a;
  double *b;
  double dummy[3];
  a = &dummy[0];
  b = &dummy[1];

  int *ai;
  int *bi;
  int dummyi[3];
  ai = &dummyi[0];
  bi = &dummyi[1];
  char *ac;
  char *bc;
  ac = (char *)a;
  bc = (char *)b;
  printf("Check for double: %d vs %d\n",sizeof(double),bc-ac);
  ac = (char *)ai;
  bc = (char *)bi;
  printf("Check for int: %d vs %d\n",sizeof(int),bc-ac);


}

(打印输出:

Check for double: 8 vs 8
Check for int: 4 vs 4

)

【讨论】:

  • 我不确定如何解决将双精度指针转换为双精度的问题。但是,我也很困惑为什么 (char *) 演员表起作用(因为它似乎在这段代码中起作用)?
【解决方案3】:

你想多了。指针是一个地址,它只是一个数字。当您拥有任何类型的数组时,每个数组都位于下一个可用地址。因此,要找出类型的大小,只需要数组中相邻条目的地址即可。

double tmp[2];
int size = (char *)(&(tmp[1])) - (char *)(&(tmp[0]));

地址必须转换为char *,以便通过将地址空间视为存储字节而不是任何数据类型来获取数据类型的第一个字节的地址。

【讨论】:

    猜你喜欢
    • 2020-12-10
    • 2016-02-18
    • 2015-06-28
    • 2014-04-18
    • 1970-01-01
    • 2018-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多