【问题标题】:Assign result of `log10(2)` to a constant将 `log10(2)` 的结果分配给常量
【发布时间】:2018-07-20 17:40:43
【问题描述】:

我想将log10(2) 的结果赋值给一个常量。

我做到了

const float f = log10(2);

它告诉Initializer element is not a constant expression。我还定义了一个新函数

const float Log10(float f) {
    return (const float)log10(f);
}

但是编译器在抱怨(为什么不呢?我也在使用log10 函数)Type qualifiers are ignored on function's return type。这是否意味着没有可以返回常量的函数?那我该怎么做呢?

编辑:

由于有些人有疑问,我包含了math.h头文件并与-lm链接,但是我在gcc中使用了-pedantic选项,它不接受它。

【问题讨论】:

  • 你链接到-lm(数学库)了吗?
  • 如果这不是您试图找到答案的一般问题,您可以硬编码log10(2) 的值。 const float f = 0.30102999566;
  • 在哪里你定义了const float f?它只能用作局部变量。
  • @Garmekain 这就是我写的。你不能用函数的返回值给全局变量赋值,不管它是不是const
  • 我不知道。我好像是个怪人。我怀疑存在中间函数调用这一事实将始终阻止分配给全局——即使返回本身将是一个常量值。看起来全局类型将丢弃 const 限定符并默认为 type 单独。但是,它确实允许全局返回 const 合格的指针

标签: c function constants return-value return-type


【解决方案1】:

假设f 在全局级别声明。

与 C++ 不同,C 不允许在初始化全局变量时使用运行时表达式。所有表达式必须在编译时可计算。

因此

const float f = log10(2);

不是有效的 C,而

const float f = 0.30102999566;

有效。

来自C Reference

在初始化静态或线程本地存储持续时间的对象时,初始化程序中的每个表达式都必须是常量表达式或字符串字面量。

【讨论】:

    【解决方案2】:

    你的问题是,如果f是一个全局变量,在C语言中你需要一个编译时常量表达式来初始化它,而编译时常量表达式不能包含log10()这样的函数调用。

    如果你可以移动这条线

    const float f = log10(2);
    

    进入main或其他一些函数,它会起作用。

    如果你需要它是全局的,你可以将它声明为

    float f;
    

    然后在main()设置的早期

    f = log10(2);
    

    但缺点是 (a) f 不能是 const 和 (b) 将初始化移动到 main 是一件麻烦事。

    你可以的

    const float f = 0.301029995663981;   /* log10(2) */
    

    但缺点很明显。

    或者您可以使用 C++,其中对编译时表达式的限制相当宽松,并且

    const float f = log10(2);
    

    我相信会奏效。

    【讨论】:

    • 我建议使用const float f = 0.301029995663981f; 来避免双舍入的任何潜在问题(从十进制文字到double,从doublefloat)。诚然,此类问题很少见,但发生的可能性非零。
    • @njuffa 好吧,如果有人使用float,他们已经说过他们不关心精度。所以我认为剩下的唯一问题是某些(尤其是 Windows)编译器可能会发出警告,在这种情况下这是一件好事,因为它会提醒 OP 重新考虑这个问题。
    • 这些天来,他们更有可能确定使用float 计算从准确性的角度来看是足够的,虽然他们受益于性能的提高,但还意识到他们无法承受丢失float 提供的少数位中的任何一个 :-)
    • @SteveSummit:按照这个逻辑,使用char 的人说他们不关心范围,所以他们的表达式中的溢出从来不是问题。
    【解决方案3】:

    这会起作用

    #include <stdio.h>
    #include <math.h>
    
    int main() { 
        const float f = log10(2);
        printf("%f\n", f);
    }
    

    但这行不通

    #include <stdio.h>
    #include <math.h>
    
    const float f = log10(2);
    
    int main() { 
        printf("%f\n", f);
    }
    

    因为你不能从函数返回值初始化一个全局变量。

    还要注意,编译器会警告将floatdouble 混合使用。永远不要使用float,除非有很好的理由不能使用double

    【讨论】:

    • 您使用了哪些编译器标志? -Wall -Werror -Wextra -pedantic 我没有收到任何警告/错误
    • @Garmekain 我不使用 gcc。
    • @Garmekain 它是“警告 C4244:'initializing':从 'double' 转换为 'const float',可能丢失数据”,我看不出抑制它的编译器标志如何有用.
    • 我看到这篇文章中的其他答案比这个更好,信息量更大,即使你是第一个得出结论的人。
    猜你喜欢
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-29
    • 2018-03-13
    • 1970-01-01
    相关资源
    最近更新 更多