如何在gcc中构建long long
,类似于通过int
构建int()
以下在gcc中失败(4.6.3 20120306)(但以MSVC为例)。
myFunctionCall(someValue, long long());
错误expected primary-expression before 'long'
(列位置表示第一个长点是位置)。
一个简单的改变
myFunctionCall(someValue, (long long)int());
工作正常 - 即构建int
并投射到long long
- 表示gcc不喜欢long long
ctor。
总结下面@birryree的精彩解释:
long long()
,可能不符合标准long long
相当于文字0LL
,因此请使用myFunctionCall(someValue, 0LL)
typedef long_long_t long long
然后使用long_long_t()
uint64_t
,如果您在任何平台上的64位类型之后,而不是 64的类型比特,但可能在不同的平台上有所不同。答案 0 :(得分:5)
我希望得到关于预期行为的确切答案,所以我posted a question on comp.lang.c++.moderated
并得到了一些很好的答案。 所以感谢Johannes Schaub, Alf P. Steinbach(均来自SO)和Francis Glassborrow获取一些信息
这不是GCC中的错误 - 实际上它会突破多个编译器 - GCC 4.6,GCC 4.7和Clang如果尝试这种语法就会抱怨像primary expression expected before '('
这样的类似错误:
long long x = long long();
某些基元有空格,如果由于绑定需要使用构造函数样式初始化,则不允许这样做(long()
已绑定,但long long()
有空闲long
) 。其中包含空格的类型(如long long
)不能使用type()
- 构造形式。
MSVC在这里更宽松,虽然技术上非标准兼容(并且它不是你可以禁用的语言扩展)。
您可以选择其他选项:
使用0LL
代替尝试long long()
作为您的值 - 它们会产生相同的值。
这也是大多数代码的编写方式,因此对于阅读代码的其他人来说,这是最容易理解的。
根据您的评论,您似乎真的想要long long
,因此您可以typedef
自己始终保证您拥有long long
类型,如下所示:
int main() {
typedef long long MyLongLong;
long long x = MyLongLong(); // or MyLongLong x = MyLongLong();
}
使用模板来解决需要明确命名的问题:
template<typename TypeT>
struct Type { typedef TypeT T(); };
// call it like this:
long long ll = Type<long long>::T();
正如我在评论中提到的,您可以使用别名类型,例如int64_t
(来自<cstdint>
),跨越常见平台的是typedef long long int64_t
。这比此列表中的先前项目更依赖于平台。
int64_t
是一个64位的固定宽度类型,通常在linux-x86和windows-x86等平台上有多宽long long
。 long long
至少为64位宽,但可以更长。如果您的代码只能在某些平台上运行,或者您确实需要固定宽度类型,那么这可能是一个可行的选择。
感谢C ++新闻组,我学会了一些其他方法来做你想做的事情,但不幸的是它们只是在C ++ 11领域(并且MSVC10也不支持,只有非常新的编译器)无论哪种方式):
{}
方式:
long long ll{}; // does the zero initialization
使用Johannes所指的C ++ 11中的'bord工具'std::common_type<T>
#include <type_traits>
int main() {
long long ll = std::common_type<long long>::type();
}
()
与0
初始化之间是否存在真正的差异?你在评论中这样说:
我不认为默认ctor总是返回零 - 更典型的行为是保持内存不变。
嗯,对于原始类型,这根本不是真的。
来自 ISO C ++ Standard / 2003 的第8.5节(没有2011,抱歉,但此信息没有太大变化):
默认初始化
T
类型的对象意味着:- 如果
T
是非POD类类型(第9节),则调用T的默认构造函数(如果T没有可访问的默认值,则初始化是错误的 构造函数);- 如果
T
是数组类型,则每个元素都是 缺省初始化;- 否则,该对象为零初始化。
最后一个句子在这里最重要,因为long long
,unsigned long
,int
,float
等都是标量/ POD类型,因此调用这样的事情:
int x = int();
完全相同:
int x = 0;
以下是代码中实际发生的更具体的示例:
#include <iostream>
template<typename T>
void create_and_print() {
T y = T();
std::cout << y << std::endl;
}
int main() {
create_and_print<unsigned long long>();
typedef long long mll;
long long y = mll();
long long z = 0LL;
int mi = int();
}
用以下内容编译:
g++ -fdump-tree-original construction.cxx
我在生成的树转储中得到了这个:
;; Function int main() (null)
;; enabled by -tree-original
{
typedef mll mll;
long long int y = 0;
long long int z = 0;
int mi = 0;
<<cleanup_point <<< Unknown tree: expr_stmt
create_and_print<long long unsigned int> () >>>>>;
<<cleanup_point long long int y = 0;>>;
<<cleanup_point long long int z = 0;>>;
<<cleanup_point int mi = 0;>>;
}
return <retval> = 0;
;; Function void create_and_print() [with T = long long unsigned int] (null)
;; enabled by -tree-original
{
long long unsigned int y = 0;
<<cleanup_point long long unsigned int y = 0;>>;
<<cleanup_point <<< Unknown tree: expr_stmt
(void) std::basic_ostream<char>::operator<< ((struct __ostream_type *) std::basic_ostream<char>::operator<< (&cout, y), endl) >>>>>;
}
因此,从上面生成的代码树中,注意我的所有变量都只是用0
初始化,即使我使用构造函数式的默认初始化,就像使用int mi = int()
一样。 GCC将生成恰好int mi = 0
的代码。
我的模板函数只是尝试对typename T
传递的某些内容进行默认构建,其中T = unsigned long long
也只生成0
- 初始化代码。
总之,如果你想默认构造原始类型/ POD,就像使用0
一样。