一、遇到的问题
今天写程序的时候代码运行崩溃,提示format specifier doesn’t match argument type。因为我刚刚接触C++,所以在这个问题上花了不少的时间。
代码如下:
void MyApp::wrong()
{
std::vector<int> test;
test.push_back(1);
test.push_back(2);
test.push_back(3);
wxLogDebug("length is %d", test.size());
for (int i = 0; i < test.size(); i++)
{
wxLogDebug("do something");
}
}
代码非常的简单,但是一旦编译运行,就会出断言错误提示。最终发现原来vector<T>.size()返回的不是int类型,而是size_t类型,所以在wxLogDebug()中因为存在着断言,发现类型不同就报错了。而后面for()循环里面虽然不报错,那是因为for()循环里面相当于是对int < size_t进行判断,没有断言语句所以不报错,并不是因为真的没有错误。
(int < size_t)这个判断语句虽然在多数情况下都可以正确的执行,但安全起见,还是应该重新定义,改成for (size_t i=0; i<test.size(); i++)这样比较稳妥。
再回过头看wxLogDebug()里面正确的写法,就是使用%zu代替%d,这样格式化字符串的时候接受的参数类型就是size_t了。所以最终代码正确写法如下:
void MyApp::right()
{
std::vector<int> test;
test.push_back(1);
test.push_back(2);
test.push_back(3);
wxLogDebug("length is %zu", test.size()); // 改动1
for (size_t i = 0; i < test.size(); i++) // 改动2
{
wxLogDebug("do something");
}
}
二、size_t和int有什么不同?
上面遇到的问题并不复杂,只是因为以前没有碰到过,所以浪费了一些时间。接下来的问题更令我感兴趣:size_t和int有什么不同吗?既然说size_t是无符号、且与当前系统最大可用内存匹配数,为什么不能直接用unsigned int代替呢?
原因是为了令代码在不同的平台上移植时更加的方便。size_t的确就是unsigned int,但具体是int16、int32还是int64并不一定,在不同的处理器、不同的系统上,size_t表示的范围是不同的。
例如在32位系统上,size_t是unsigned int32,而在64位系统上它的范围则是unsigned int64。
std::vector<T>.size()返回的虽然是size_t类型,但是更多的情形下,size_t并不是为了存储索引数值、而是为了存储内存地址,这个时候内存的地址最大能寻址到多少,size_t就能够跟随到多少。
虽然我们也可以直接定一个unsigned long int,也就是“无符号int64”,这样也可以确保在不同的系统下存储的数值都不会产生溢出,但是如果是在32位系统上编译这样的程序,就会产生严重的浪费,所有用到的变量,都有至少16位是永远用不到的,这是浪费存储空间、浪费内存、且效率低下的。
因而使用size_t更加的灵活,并且免除了我们在不同系统上编译代码时要考虑分配多少位给变量,完全交由编译器在预处理阶段自行根据系统的位数、预处理好了。