【问题标题】:Should/Do I cast a void pointer in C in general? [closed]一般来说,我应该/是否应该在 C 中转换一个 void 指针? [关闭]
【发布时间】:2020-01-12 19:06:10
【问题描述】:

Do I cast the result of malloc? 中说,您不需要强制转换malloc() 函数或其家族成员之一返回的void 指针,因为由于标准它可以省略并且可能导致问题之手。

但是一般来说,void 指针的转换呢?投射void 指针的一般方法有什么不同吗?

  • 应该将 void 指针转换为 C 中的另一个类型指针吗?
  • 在 C 语言中是否有任何地方可以转换 void 指针?

【问题讨论】:

  • 我会投票关闭作为副本 - 没有什么不同。
  • 是的,有:在您为 qsort 提供的回调函数中,它具有 void* 参数。你需要让他们对他们做任何有用的事情。
  • 不,@WeatherVane,您需要转换它们才能对它们做任何有用的事情。这种转换可以在没有强制转换的情况下执行。例如,通过分配给正确类型的变量。
  • @WeatherVane 或分配给变量。
  • 为了解决我应该演员表,有一个通常的演员表指导方针:如果你不需要,不要明确指定一个。 (其中“需要”足够模糊,无法进行编码风格讨论。)

标签: c pointers casting void


【解决方案1】:

有两种正确的情况,您需要进行演员表:

  • 将指向 void 的指针转换回其原始的非 void 类型,而不将结果分配给变量(包括初始化的分配,或将其作为参数传递)。 p>

  • 使愚蠢的编译器静音,该编译器会发出有关缩小转换的警告。 C11/C18 Annex I:

    1. 在许多情况下,实现可能会生成警告,但本国际标准中没有一种情况被指定。以下是一些比较常见的情况。

    2. [...]

      • 遇到隐式缩小转换,例如将 long int 或 double 分配给 int,或 将指向 void 的指针指向指向字符类型以外的任何类型的指针 (6.3 )。

对于第一部分:您几乎总是可以使用临时变量。例如,您可以编写

int comparator(const void *a, const void *b)  
{ 
    int sa = ((const struct foo *)a)->bar; 
    int sb = ((const struct foo *)b)->bar;  
    return (sa > sb) - (sa < sb); 
} 

int comparator(const void *a, const void *b)  
{ 
    const struct foo *sa = a; 
    const struct foo *sb = b;  
    return (sa->bar > sb->bar) - (sa->bar < sb->bar); 
} 

- 它们的按键次数几乎相同。

对于第二种情况,您只需要避免使用此类编译器或尝试通过一些开关来关闭这种唠叨。


除了这个问题之外,“我是否应该在不需要的地方进行演员表”。在 C 程序中,有很多东西不是必需,但为了清楚起见而添加。例如缩进或换行!添加它们使事情变得更加清晰。问题是例如为来自malloc 的返回值添加一个无用的转换是否使其更具可读性:

char *foo = malloc(42);

对比

char *foo = (char *)malloc(42);

即使没有演员表,结果也应该转换为char * 或至少foo 的结果不是很明显吗?

【讨论】:

  • 优秀的答案。我能想到的唯一其他注意事项是明确说明您永远不应该强制转换为 void 以试图克服关于不兼容类型的编译器警告或试图破坏类型双关指针警告。
  • ...第二个版本更易读恕我直言。典型用法是在函数中首先分配隐式转换变量,有效地声明“这些void* 实际上应该指向类型const struct foo”,以及其他合同声明,如assert()
  • 它写const对象
  • 人们将malloc 的返回值(你经常在这里看到)因为 VS 是一个非常流行的 IDE,MS 编译器默认编译为 C++。作为初学者,他们并不清楚发生了什么 - 所以添加一些东西只是为了编译代码。
【解决方案2】:

当您拥有void* 时,您可以将其隐式转换为任何指针类型。 这仅适用于void*。它不适用于double*,也不适用于int,它甚至都不是指针。

当您添加演员表时,您扩展了允许的输入类型集。突然,任何指针都可以转换就像任何整型一样。

现在,如果将int 转换为myStruct* 会发生什么?确切地。废话。您希望编译器对此抛出错误。


同样,如果您有一个指针,并将其隐式转换为 void*,则该指针仅适用于指针(以及 0 文字)。如果添加强制转换,您将失去对该值实际上是指针的检查。现在,使用 char 作为输入时,转换同样有效。

当您将'a' 转换为指针时会发生什么?确切地。废话。您希望编译器对此抛出错误。


所以,请不要添加不必要的演员表。它们总是扩大编译器无法捕获的错误的可能性。如果您必须通过 void* 传递指针,请确保它仅适用于指针。

【讨论】:

    猜你喜欢
    • 2011-02-08
    • 2018-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多