![](/img/trans.png)
[英]warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
[英]What is wrong with my For loops? i get warnings: comparison between signed and unsigned integer expressions [-Wsign-compare]
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
int main() {
vector<double> vector_double;
vector<string> vector_string;
...
while (cin >> sample_string)
{
...
}
for(int i = 0; i <= vector_string.size(); i++)
{
....
}
for (int i = 0; i < vector_double.size(); i++)
....
return 0;
}
為什么
-Wsign-compare
會出現警告?
正如警告的名稱及其文本所暗示的那樣,問題在於您正在比較有符號和無符號整數。 一般認為這是一次事故。
為了避免此警告,您只需確保<
(或任何其他比較運算符)的兩個操作數都是有符號的或都是無符號的。
我怎樣才能做得更好?
寫的慣用方式for
環路來初始化計數器,並在第一條語句的限制:
for (std::size_t i = 0, max = vec.size(); i != max; ++i)
這節省了每次迭代時重新計算size()
時間。
您也可以(並且可能應該)使用迭代器而不是索引:
for (auto it = vec.begin(), end = vec.end(); it != end; ++it)
auto
是std::vector<int>::iterator
的簡寫。 迭代器適用於任何類型的容器,而索引將您限制為 C 數組、 deque
和vector
。
這是因為來自 vector 類的 .size() 函數不是 int 類型而是 vector::size_type 類型
使用那個或auto i = 0u
並且消息應該消失。
我通常是這樣解決的:
for(int i = 0; i <= (int)vector_string.size(); i++)
我使用 C 風格的static_cast<int>()
因為它比 C++ static_cast<int>()
更短、更易讀,並且完成了同樣的事情。
這里存在溢出的可能性,但前提是您的向量大小大於最大的int
,通常為 2147483647。我一生中從未有過這么大的向量。 如果使用更大向量的可能性size_type
那么建議size_type
的答案之一會更合適。
我不擔心在循環中重復調用size()
,因為它可能是對不引入開銷的成員變量的內聯訪問。
您收到此警告是因為 C++ 中容器的大小是無符號類型,混合有符號/無符號類型是危險的。
我通常做的是
for (int i=0,n=v.size(); i<n; i++)
....
在我看來,這是使用索引的最佳方式,因為對索引(或容器的大小)使用無符號類型是一個邏輯錯誤。
僅當您關心位表示並且打算在溢出時使用模 (2**n) 行為時,才應使用無符號類型。 僅僅因為值永遠不是負數而使用無符號類型是無稽之談。
例如,將無符號類型用於大小或索引的典型錯誤是
// Draw all lines between adjacent points
for (size_t i=0; i<pts.size()-1; i++)
drawLine(pts[i], pts[i+1]);
當點數組為空時,上面的代碼是 UB,因為在 C++ 中0u-1
是一個巨大的正數。
C++ 使用無符號類型作為容器大小的原因是因為來自 16 位計算機的歷史遺產(並且 IMO 給出了帶有無符號類型的 C++ 語義,即使在當時也是錯誤的選擇)。
int
默認是有符號的——它相當於寫了signed int
。 您收到警告的原因是size()
返回一個vector::size_type
,它很可能是無符號的。
這具有潛在危險,因為signed int
和unsigned int
持有不同范圍的值。 signed int
可以保存–2147483648
到2147483647
之間的值,而unsigned int
可以保存0
到4294967295
之間的值(假設int
是 32 位)。
您的變量i
是一個整數,而返回Allocator::size_type
的 vector 的size
成員函數很可能返回一個size_t
,它幾乎總是作為某種大小的無符號整數實現。
使您的int i
為size_type i
。
std::vector::size()
將返回size_type
,它是一個unsigned int
因為 size 不能為 -ve。
警告顯然是因為您將有符號整數與無符號整數進行比較。
在這么多答案之后回答,但沒有人注意到循環結束..所以,這是我的完整答案:
i
的類型更改為unsigned
、 auto
(對於 C++11)或std::vector< your_type >::size_type
for
循環將出現段錯誤,如果您使用i
作為索引 - 您必須從0
循環到size-1
,包括。 所以,改成for( std::vector< your_type >::size_type i = 0; i < vector_xxx.size(); ++i )
<
,而不是<=
;我的建議是不要將<=
與.begin() - 1
,因為您可以有一個 0 大小的向量,並且您會遇到問題:))。iterator
。 這將使以后更容易更改容器類型(當然,如果您不需要數字的確切位置)。 所以,我會這樣寫:for( std::vector< your_type >::iterator iter = vector_XXX.begin();
iter != vector_XXX.end();
++iter )
{
//..
}
為我聲明 'size_t i' 效果很好。
std::cout << -1U << std::endl;
std::cout << (unsigned)-1 << std::endl;
4294967295
std::cout << 1 << std::endl;
std::cout << (signed)1 << std::endl;
1
std::cout << (unsigned short)-1 << std::endl;
65535
std::cout << (signed)-1U << std::endl;
std::cout << (signed)4294967295 << std::endl;
-1
取消對索引變量的簽名
unsigned int index;
index < vecArray.size() // size() would never be negative
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.