我正在研究一个恰好SIZE_MAX在几个地方使用的现有C++代码库.我做了一些重构,现在SIZE_MAX没有在其中一个模块中定义.当Travis-CI尝试在Linux上构建项目时出现此问题.它在重构之前工作正常,但是跟踪包含哪些精确的头文件很困难.
为了在本地复制问题,我安装了一个带有默认gcc的Ubuntu VM,并且能够重现它.以下是相关来源:
#include <stddef.h>
int main()
{
size_t a = SIZE_MAX;
}
Run Code Online (Sandbox Code Playgroud)
命令行很简单:
g++ a.cpp
Run Code Online (Sandbox Code Playgroud)
错误是:
a.cpp: In function ‘int main()’:
a.cpp:5:16: error: ‘SIZE_MAX’ was not declared in this scope
Run Code Online (Sandbox Code Playgroud)
系统信息:
$ uname -a
Linux quartz 3.11.0-15-generic #25~precise1-Ubuntu SMP Thu Jan 30 17:39:31 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Run Code Online (Sandbox Code Playgroud)
我曾尝试包括cstdint,stdint.h,limits.h,inttypes.h,stdio.h,stdlib.h,,可能有一些人,我想不出我需要哪些特定的头文件SIZE_MAX.
重要的是要注意我正在编写的程序编译正常SIZE_MAX …
有没有什么办法让printf一个size_t没有任何第一投射,或产生编译器警告?(我总是编译-Wall.)
所以我在一个程序中有一个普通的for循环通过一个对象向量(对象是我定义的类型,如果相关的话):
for(int k = 0; k < objects.size(); k++){ ... }
Run Code Online (Sandbox Code Playgroud)
...当我编译时,我得到这个警告:
warning: comparison between signed and unsigned integer expressions
Run Code Online (Sandbox Code Playgroud)
这是有道理的,因为我认为size()一个向量返回一个size_t.但为什么重要呢?不是一定数量的元素(甚至是内存块)是一个可以计算的整数吗?更重要的是,由于我的程序有多个这样的循环并且发生了很多段错误,这可能是它的一部分吗?
有没有办法转换std::string成size_t?问题是size_t平台可靠类型(虽然它是结果sizeof).所以,我无法保证转换string为unsigned long或unsigned int将正确执行.
编辑:一个简单的例子是:
std::cout<< "Enter the index:";
std::string input;
std::cin >> input;
size_t index=string_to_size_t(input);
//Work with index to do something
Run Code Online (Sandbox Code Playgroud) C标准保证int能够存储每个可能的数组大小.至少,这是我从阅读§6.5.2.1,第1小节(数组下标约束)中理解的内容:
其中一个表达式应具有类型''指向对象类型的指针'',另一个表达式应具有整数类型,结果具有类型''type''.
既然我们将ints用作数组下标,为什么我们应该用它size_t来确定数组的大小?
为什么strlen()回报size_t什么时候int就够了?
size_t即使数组的大小不足以超过int的大小,我在索引数组时也需要始终使用它吗?
这不是我何时应该使用的问题size_t。我只想知道,例如,一个程序是否具有2GB的可用内存(所有这些字段都可以由int32索引),但是此内存(虚拟内存)已分配给“字段” 14GB-计算机的16GB内存。
在这种情况下,如果我使用int32而不是size_t(或unsigned long int)来索引内存,它将总是失败吗?
也许问题更多是关于虚拟内存,而不是指针。
在32位和64位Linux平台上转换/转换int为size_tC99 的正确方法是什么?
例:
int hash(void * key) {
//...
}
int main (int argc, char * argv[]) {
size_t size = 10;
void * items[size];
//...
void * key = ...;
// Is this the right way to convert the returned int from the hash function
// to a size_t?
size_t key_index = (size_t)hash(key) % size;
void * item = items[key_index];
}
Run Code Online (Sandbox Code Playgroud) 我最近了解到,引入size_t是为了帮助面向未来的代码,防止本机位数增加和可用内存增加.具体的使用定义似乎是存储某些东西的大小,通常是一个数组.
我现在必须想知道这种未来的证明应该走多远.当迭代数组的下一个任务使用一个unsigned intas作为索引数组时,使用面向未来并且大小适当的size_t定义数组长度毫无意义:
void (double* vector, size_t vectorLength) {
for (unsigned int i = 0; i < vectorLength; i++) {
//...
}
}
Run Code Online (Sandbox Code Playgroud)
事实上,在这种情况下,我可能希望语法严格地将unsigned int上变换为关系运算符的size_t.
这是否意味着迭代器变量i应该只是一个size_t?
这是否意味着任何程序中的任何整数必须在功能上确定是否它将被用作数组索引?
它意味着使用编程开发索引然后应该创建size_t类型的一个新的结果值,特别是如果逻辑依赖于潜在符号的整数值逻辑的任何代码?即
double foo[100];
//...
int a = 4;
int b = -10;
int c = 50;
int index = a + b + c;
double d = foo[(size_t)index];
Run Code Online (Sandbox Code Playgroud)
当然,由于我的代码逻辑创建了一个固定的边界,因此向上转换为size_t不会提供额外的保护.
std::size_t通常用于数组索引和循环计数.根据定义,std::size_t是sizeof运算符以及sizeof...运算符和alignof运算符的结果的无符号整数类型(自C++ 11起).它在以下标题中定义:
<cstddef><cstdio><cstdlib><cstring><ctime><cwchar>据我了解,这些运算符返回的类型是实现定义的.
我想要的是定义一个自定义size_t,以避免从.cpp我的文件中的上述任何标题中提取不必要的东西,因为在我的文件中我只需要std::size_t.
在C++ 11及更高版本中,我认为我可以使用以下别名:
using size_t = decltype(sizeof(1));
Run Code Online (Sandbox Code Playgroud)
但是,我想以size_t便携/跨平台的方式为C++ 11之前的编译器定义一种类型.
那么有一种可移植的方式来定义size_t前C++ 11吗?
注意:有人建议这个问题重复Can I Compare int with size_t direct in C? ,但这里的问题特别询问如何将 size_t 与负值进行比较。因此,应该重新开放。(此外,它还引发了很多深思熟虑的讨论!)
我正在盯着一些库代码(我正在看着你,Microchip),声明返回size_t:
size_t SYS_FS_FileWrite(SYS_FS_HANDLE handle, const void *buf, size_t nbytes);
Run Code Online (Sandbox Code Playgroud)
这被记录为错误时返回 -1。但是size_t一个无符号值。那么,在理论上和/或实践中,以下行为是否允许?
if (SYS_FS_FileWrite(handle, buf, nbytes) == -1) {
report_errror();
}
Run Code Online (Sandbox Code Playgroud)