如何表示常量的类型
How to express the type for a constant?
我必须在相对较少的行数中编写一些包含大量常量的函数
(不要担心我写公式的方式,它只是为了简单地表达我在一个小包中有很多常数的事实,这个具体的例子也很小,在实践中我每个函数至少有6-7个常数)
T foo( T x )
{
return k1 * k2 * x - k3;
}
假设我对将常量声明为静态不感兴趣(在我的特定情况下,这也会导致命名约定的问题)const T k1 = 42;
,我想找到一个替代方案。
一个可行的替代方案是
T foo( T x )
{
return uint32_t{42} * uint32_t{21} * x - uint32_t{33};
}
现在主要有两个问题:
- 我不确定这种声明是否会创建一个完整的对象或只是"一个数字"
- 这是一个c++唯一的解决方案,我写了非常简单的函数,应该是C99+兼容。
为什么我想这样做?
这很简单,这个常量的值是高度可变的,非常小的值或大的值,非常小的值会浪费大量的空间,加上这个常量是数学常量,所以它们永远不会改变,我可以从第一个版本开始优化这一部分。
还有另一个方面,数字常量的默认类型是一个有符号整数,我想去一个任意大小的无符号整数类型。
函数外的静态声明const T k1 = 42;
的问题是,不同的常数有相同的名称,常数的值不同,因为函数不同,但常数的名称,从数学上讲,是相同的,所以用这个解决方案,我最终会在同一作用域中对同一变量进行多个声明。这就是为什么我不能使用名称或这类声明。
你有什么想法可以用一种既兼容c++又兼容C的方式来写这个吗?
在C语言中,对于整数,您可以在数字上加上'U', 'L'或'LL',以几种组合方式使它们成为unsigned
, long
或long long
a = -1LL; // long long
b = -1U; // unsigned
c = -1ULL; // unsigned long long
d = -1LLU; // unsigned long long
e = -1LU; // unsigned long
f = -1UL; // unsigned long
在C中,另一种选择是强制转换。编译器很可能会做正确的事情:)
return (uint32)42 - (int64)10;
但是可能最好的选择,正如ouah在下面的评论中指出的那样,是对整数常量使用宏(C99 Standard 7.18.4)
a = UINT32_C(-1); // -1 of type uint_least32_t
b = INT64_C(42); // 42 of type int_least64_t
这有什么问题吗?
inline T foo(T x)
{
int k1 = 42;
int k2 = 21;
int k3 = 33;
return 1ull * x * k1 * k2 - k3;
}
您对另一个答案的评论表明您不确定使用哪种类型的常量。我看不出用任何类型来表示这个常量有什么问题。
对于计算表达式,您需要考虑中间计算的大小和符号性。在这个例子中,我从1ull
开始使用无符号算术模型2^64
。如果你想用2^32
进行算术建模,那就用1ul
,以此类推。
你能详细说明你所说的"空间浪费"是什么意思吗?听起来好像您认为使用64位整型存在一些问题。你说的是什么样的"空间"?
另外,为了澄清,你不想声明k1
全局的原因是因为k1
在一个函数中具有不同的值,而不是在另一个函数中?(而不是有相同的值,但你认为它应该有不同的数据类型的原因)。
- 如何为具有常量类型的函数正确转换来自 DLsym 的返回值?
- 常量和非常量类型的相同模板专用化
- 另一个:从"常量类型*"到"类型*"的转换无效
- 派生类中函数参数变化的虚函数按常量类型在"function parameter"会破坏虚拟机制吗?
- 模板和常量类型
- 返回对常量指针的引用,指向常量类型
- 错误:常量类型为c++的单元化成员
- 如何在不重复函数的情况下推导出常量和非常量类型
- JUCE - 成员函数不可行:'this'参数具有常量类型
- 未找到采用常量类型的左操作数的'=='运算符
- 重载全常量类型的复制赋值运算符的正确方法是什么?
- 忽略候选模板:无法将"常量类型参数-0-0 *"与"字符"匹配
- C++中的部分常量类型转换
- 常量类型之间的区别
- 提升::任何构造函数 - 常量类型重载分辨率
- 如何声明模板常量类型
- 编译时生成的常量类型 ID
- 转换为常量类型,初始化数组
- 正在获取模板中的非常量类型
- 如何使用元编程过滤常量类型和非常量类型