Derleyici uyarısı (düzey 2) C4146
unsigned türüne uygulanan birli eksi işleci, sonuç hala imzasız
İmzasız türler yalnızca negatif olmayan değerleri barındırabilir, bu nedenle birli eksi (olumsuzlama) genellikle işaretsiz bir türe uygulandığında anlamlı olmaz. hem işlenen hem de sonuç negatif değil.
Açıklamalar
Negatif bir tamsayı değişmez değerini ifade ettiğinizde, -
değerin önünde bir tekli olumsuzlama işleci olarak ayrıştırılır. Derleyici, sayısal değeri ayrıştırdıktan sonra işlecini uygular. Sayısal değer işaretsiz tamsayı türünün aralığına uyuyorsa ancak karşılık gelen imzalı tamsayı türüne uymuyorsa, derleyici değeri işaretsiz olarak yorumlar. İmzasız bir değer, tekli olumsuzlama işleci tarafından değiştirilmez.
Bu uyarı genellikle -2147483648 veya long long
en düşük int
değer olan -9223372036854775808 değerini ifade etmeye çalıştığınızda oluşur. Bu değerler sırasıyla -2147483648 veya -9223372036854775808ll olarak yazılamaz. Bunun nedeni, derleyicinin ifadeyi iki aşamada işlemesidir: önce sayısal değeri ayrıştırıyor, ardından olumsuzlama işlecini uyguluyor. Örneğin, derleyici -2147483648 ayrıştırdığında şu adımları izler:
2147483648 sayısı değerlendirilir. 2147483647 en büyük
int
değerinden büyük olduğundan, ancak yine de birunsigned int
değerine sığdığından, 2147483648 türü olurunsigned int
.İşaretsiz değere birli eksi uygulanır ve imzasız sonuç da 2147483648 olur.
Sonucun imzasız türü beklenmeyen davranışlara neden olabilir. Sonuç bir karşılaştırmada kullanılırsa, örneğin diğer işlenen bir olduğunda imzasız bir int
karşılaştırma kullanılabilir.
C4146'dan <limits.h>
veya C++ eşdeğeri <climits>
olan kullanarak INT_MIN
LLONG_MIN
önleyebilirsiniz. Bu değerlerin imzalı türleri vardır.
/sdl
(Ek Güvenlik Denetimlerini Etkinleştir) derleyici seçeneği bu uyarıyı bir hataya yükseltir.
Örnek
Aşağıdaki örnek, derleyici C4146 uyarısı oluşturduğunda gerçekleşebilecek beklenmeyen davranışı gösterir:
// C4146.cpp
// compile with: /W2
#include <iostream>
void check(int i)
{
if (i > -9223372036854775808ll) // C4146
std::cout << i << " is greater than the most negative long long int.\n";
}
int main()
{
check(-100);
check(1);
}
Bu örnekte, değişmez değer bir ll
son eke sahip olsa ve olumsuzlama işleci uygulanmış olsa bile derleyici -9223372036854775808ll işaretinin kaldırıldığını dikkate alır. Karşılaştırma yapmak <
için derleyici sessizce olarak olarak imzalı i
olarak unsigned long long int
yükselter. Beklenen ikinci satır olan 1 is greater than the most negative long long int
, false olduğundan ((unsigned long long int)1) > 9223372036854775808ull
yazdırılmaz.
Örneği düzeltmek için - 9223372036854775808ll değerini ekleyin <climits>
ve olarak LLONG_MIN
değiştirin.