Visual Studio 2022'de C++ Uyumluluk geliştirmeleri, davranış değişiklikleri ve hata düzeltmeleri
Visual Studio'da (MSVC) Microsoft C/C++ her sürümde uyumluluk iyileştirmeleri ve hata düzeltmeleri yapar. Bu makalede, ana sürüme ve sonra sürüme göre yapılan önemli iyileştirmeler listelenmiştir. Belirli bir sürümdeki değişikliklere doğrudan atlamak için, bu makalenin üst kısmındaki Bu makaledeki bağlantıları kullanın.
Bu belgede Visual Studio 2022'deki değişiklikler listelenir.
Visual Studio'nun önceki sürümlerindeki değişiklikler için:
Sürüm | Uyumluluk geliştirmeleri bağlantısı |
---|---|
2019 | Visual Studio 2019'da C++ uyumluluğu geliştirmeleri |
2017 | Visual Studio 2017’deki C++ uyumluluk geliştirmeleri |
2003-2015 | Visual C++ 2003 ile 2015 Arasındaki Farklar |
Visual Studio 2022 sürüm 17.12'de uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.12, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Uyumluluk değişiklikleri, hata düzeltmeleri ve performans geliştirmeleri de dahil olmak üzere Standart Şablon Kitaplığı'nda yapılan değişikliklerin ayrıntılı bir özeti için bkz . STL Changelog VS 2022 17.12.
_com_ptr_t::operator bool()
artık açık
Bu, kaynak/ikili hataya neden olan bir değişikliktir.
Örneklerden _com_ptr_t
örtük dönüştürme bool
şaşırtıcı olabilir veya derleyici hatalarına yol açabilir. Örtük dönüştürme işlevleri C++ Çekirdek Yönergeleri (C.164) tarafından önerilmez ve _com_ptr_t
hem hem de bool
Interface*
için örtük dönüştürmeler içerir. Bu iki örtük dönüştürme belirsizliğe yol açabilir.
Bu sorunu gidermeye yardımcı olmak için bool
dönüştürme işlemi artık açık. dönüştürmesi Interface*
değiştirilmez.
Bu yeni davranışı geri çevirmek ve önceki örtük dönüştürmeyi geri yüklemek için bir makro sağlanır. Bu değişikliği geri çevirmek için ile derleyin /D_COM_DISABLE_EXPLICIT_OPERATOR_BOOL
. Kodu örtük dönüştürmelere bağlı olmayacak şekilde değiştirmenizi öneririz.
Örneğin:
#include <comip.h>
template<class Iface>
using _com_ptr = _com_ptr_t<_com_IIID<Iface, &__uuidof(Iface)>>;
int main()
{
_com_ptr<IUnknown> unk;
if (unk) // Still valid
{
// ...
}
bool b = unk; // Still valid.
int v = unk; // Previously permitted, now emits C2240: cannot convert from '_com_ptr_t<_com_IIID<IUnknown,& _GUID_00000000_0000_0000_c000_000000000046>>' to 'int'
}
Sabit ifadeler artık her zaman noexcept
izin verme modunda değil
Bu, kaynak/ikili hataya neden olan bir değişikliktir.
Sabit ifade her zaman noexcept
, potansiyel olarak bir özel durum belirtimi ile bildirilen bir işleve işlev çağrısı dahil olsa bile oldu. Bu ifade C++17'de kaldırıldı, ancak Microsoft Visual C++ derleyicisi bunu tüm C++ dil sürümlerinde modda desteklemeye devam etti /permissive
.
Bu /permissive
mod davranışı kaldırılır. Sabit ifadelere artık özel örtük davranışlar verilmez.
noexcept
İşlevlerdeki constexpr
tanımlayıcıya artık tüm modlarda uyuldu. Bu değişiklik, standart noexcept
davranışı kullanan sonraki temel sorun çözümlerinin doğru uygulanması için gereklidir.
Örneğin:
constexpr int f(bool b) noexcept(false)
{
if (b)
{
throw 1;
}
else
{
return 1;
}
}
void g(bool b)
{
noexcept(f(b)); // false. No change to behavior
noexcept(f(true)); // false. No change to behavior
noexcept(f(false)); // false. Was true in /permissive mode only in previous versions.
}
Visual Studio 2022 sürüm 17.11'de uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.11, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Uyumluluk değişiklikleri, hata düzeltmeleri ve performans geliştirmeleri de dahil olmak üzere Standart Şablon Kitaplığı'nda yapılan değişikliklerin ayrıntılı bir özeti için bkz . STL Changelog VS 2022 17.11.
Ile boş satır yazdırma println
P3142R0 başına artık ile println
boş bir satır oluşturmak kolaydır. Bu özellik ile /std:c++latest
derlenirken kullanılabilir.
Bu değişiklik öncesinde şunu yazdınız: println("");
Şimdi şunu yazacaksınız: println();
.
println();
eşdeğerdirprintln(stdout);
println(FILE* stream);
eşdeğerdirprintln(stream, "\n");
Uygulanan range_formatter
P2286R8 başına artık range_formatter
uygulandı. Bu özellik ile /std:c++latest
derlenirken kullanılabilir.
Visual Studio 2022 sürüm 17.10'da uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.10, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Uyumluluk değişiklikleri, hata düzeltmeleri ve performans geliştirmeleri de dahil olmak üzere Standart Şablon Kitaplığı'nda yapılan değişikliklerin ayrıntılı bir özeti için bkz . STL Changelog VS 2022 17.10.
Açıkça belirtilen dönüş türüyle dönüştürme işleci özelleştirmesi
Bazı durumlarda dönüştürme işleçlerini yanlış özelleştirmek için kullanılan derleyici, eşleşmeyen bir dönüş türüne yol açabilir. Bu geçersiz özelleştirmeler artık gerçekleşmez. Bu, kaynak kodunda hataya neden olan bir değişikliktir.
// Example 1
struct S
{
template<typename T> operator const T*();
};
void test()
{
S{}.operator int*(); // this is invalid now
S{}.operator const int*(); // this is valid
}
// Example 2
// In some cases, the overload resolution result may change
struct S
{
template <typename T> operator T*(); // overload 1
template <typename T> operator const T*(); // overload 2
};
void test()
{
S{}.operator int*(); // this used to call overload 2, now it calls overload 1
}
ve desteği #elifdef
eklendi #elifndef
ve #elifndef
ön işlemci yönergelerini kullanıma sunan #elifdef
WG21 P2334R1 (C++23) ve WG14 N2645 (C++23) desteği eklendi.
veya /std:c++latest
gerektirir/std:clatest
.
Önce:
#ifdef __cplusplus
#include <atomic>
#elif !defined(__STDC_NO_ATOMICS__)
#include <stdatomic.h>
#else
#include <custom_atomics_library.h>
#endif
Sonra:
#ifdef __cplusplus
#include <atomic>
#elifndef __STDC_NO_ATOMICS__
#include <stdatomic.h>
#else
#include <custom_atomics_library.h>
#endif
C'de _Alignas
yapılandırılmış bir türde uygulaması
C dili (C17 ve üzeri) için geçerlidir. Microsoft Visual Studio 17.9'a da eklendi
Visual Studio 2022 sürüm 17.9'dan önceki Visual C++ sürümlerinde, tanımlayıcı bir bildirimde yapılandırılmış bir türün yanında görünürse _Alignas
, ISO-C Standardına göre doğru uygulanmamıştır.
// compile with /std:c17
#include <stddef.h>
struct Outer
{
_Alignas(32) struct Inner { int i; } member1;
struct Inner member2;
};
static_assert(offsetof(struct Outer, member2)==4, "incorrect alignment");
ISO-C Standardına göre, bu kod bir tanılama yaymadan static_assert
derlenmelidir.
yönergesi _Alignas
yalnızca üye değişkenine member1
uygulanır. hizalamasını struct Inner
değiştirmemelidir. Ancak Visual Studio 17.9.1'in öncesinde tanılama "yanlış hizalama" ortaya çıktı. Derleyici, türü içinde 32 baytlık bir uzaklık ile struct Outer
hizalandımember2
.
Bu ikili hataya neden olan bir değişiklik olduğundan, bu değişiklik geçerli olduğunda bir uyarı gönderilir. Uyarı C5274 artık önceki örnek için uyarı düzeyi 1'de gösteriliyor: warning C5274: behavior change: _Alignas no longer applies to the type 'Inner' (only applies to declared data objects)
.
Ayrıca, Visual Studio'nun önceki sürümlerinde, tanımlayıcı anonim bir tür bildiriminin _Alignas
yanında göründüğünde yoksayıldı.
// compile with /std:c17
#include <stddef.h>
struct S
{
_Alignas(32) struct { int anon_member; };
int k;
};
static_assert(offsetof(struct S, k)==4, "incorrect offsetof");
static_assert(sizeof(struct S)==32, "incorrect size");
Daha önce bu kod derlenirken her iki deyim de static_assert
başarısız oldu. Şimdi kod derlenir, ancak aşağıdaki düzey 1 uyarılarını yayar:
warning C5274: behavior change: _Alignas no longer applies to the type '<unnamed-tag>' (only applies to declared data objects)
warning C5273: behavior change: _Alignas on anonymous type no longer ignored (promoted members will align)
Önceki davranışı almak için değerini ile __declspec(align(N))
değiştirin_Alignas(N)
. declspec(align)
türünden farklı _Alignas
olarak geçerlidir.
Geliştirilmiş uyarı C4706
Bu, kaynak kodunda hataya neden olan bir değişikliktir. Daha önce derleyici, atama amaçlandıysa, koşullu ifade içindeki atama hakkında C4706 uyarısını bastırmak için atamayı parantez içinde sarmalama kuralını algılamamıştı. Derleyici artık parantezleri algılar ve uyarıyı bastırır.
#pragma warning(error: 4706)
struct S
{
auto mf()
{
if (value = 9)
return value + 4;
else
return value;
}
int value = 9;
};
Derleyici artık işleve başvurulmadığı durumlarda da uyarıyı yayar. Daha önce, mf
başvurulmadığı bir satır içi işlev olduğundan, bu kod için C4706 uyarısı gösterilmiyordu. Şimdi uyarı yayılıyor:
error C4706: assignment used as a condition
note: if an assignment is intended you can enclose it in parentheses, '(e1 = e2)', to silence this warning
Bu uyarıyı düzeltmek için, amaçlanan buysa bir eşitlik işleci value == 9
kullanın. Ya da atama amaçlanıyorsa, atamayı parantez (value = 9)
içinde kaydırın. Aksi takdirde işlev başvurulmadığından kaldırın.
Visual Studio 2022 sürüm 17.9'da uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.9, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Standart Şablon Kitaplığı'na yapılan değişikliklerin daha geniş bir özeti için bkz . STL Changelog VS 2022 17.9.
C'de _Alignas
yapılandırılmış bir türde uygulaması
Visual Studio 2022 sürüm 17.9'dan önceki Visual C++ sürümlerinde, _Alignas
bir bildirimde bir yapı türünün yanında göründüğünde, ISO-C Standardına göre doğru uygulanmadı. Örneğin:
// compile with /std:c17
#include <stddef.h>
struct Outer
{
_Alignas(32) struct Inner { int i; } member1;
struct Inner member2;
};
static_assert(offsetof(struct Outer, member2)==4, "incorrect alignment");
ISO-C Standardına göre, bu kod bir tanılama yaymadan static_assert
derlenmelidir. yönergesi _Alignas
yalnızca üye değişkenine member1
uygulanır. hizalamasını struct Inner
değiştirmemelidir. Ancak Visual Studio'nun 17.9.1 sürümünden önce tanılama "yanlış hizalama" ortaya çıktı. Derleyici içinde 32 bayt uzaklığıyla struct Outer
hizalanmışmember2
.
Bunu düzeltmek ikili hataya neden olan bir değişikliktir, dolayısıyla davranıştaki bu değişiklik uygulandığında bir uyarı gönderilir. Yukarıdaki kod için Uyarı C5274, "_Alignas
artık 'Inner' türüne uygulanmaz (yalnızca bildirilen veri nesneleri için geçerlidir)" uyarı düzeyi 1 olarak gösterilir.
Visual Studio'nun önceki sürümlerinde, _Alignas
anonim tür bildiriminin yanında göründüğünde yoksayıldı. Örneğin:
// compile with /std:c17
#include <stddef.h>
struct S {
_Alignas(32) struct { int anon_member; };
int k;
};
static_assert(offsetof(struct S, k)==4, "incorrect offsetof");
static_assert(sizeof(struct S)==32, "incorrect size");
Daha önce bu kod derlenirken her iki deyim de static_assert
başarısız oldu. Kod şimdi derlenir, ancak aşağıdaki düzey 1 uyarılarıyla birlikte:
warning C5274: behavior change: _Alignas no longer applies to the type '<unnamed-tag>' (only applies to declared data objects)
warning C5273: behavior change: _Alignas on anonymous type no longer ignored (promoted members will align)
Önceki davranışı istiyorsanız değerini ile __declspec(align(N))
değiştirin_Alignas(N)
. declspec(align)
türünden farklı _Alignas
olarak uygulanabilir.
__VA_OPT__
altında bir uzantı olarak etkinleştirildi /Zc:preprocessor
__VA_OPT__
C++20 ve C23'e eklendi. Eklemeden önce, variadic makroda virgüli zorlamanın standart bir yolu yoktu. Geriye dönük daha iyi uyumluluk sağlamak için, __VA_OPT__
tüm dil sürümlerinde belirteç tabanlı ön işlemci /Zc:preprocessor
altında etkinleştirilir.
Örneğin, bu artık hatasız derlenmiş:
#define LOG_WRAPPER(message, ...) WRITE_LOG(__LINE__, message __VA_OPT__(, __VA_ARGS__))
// Failed to build under /std:c11, now succeeds.
LOG_WRAPPER("Log message");
LOG_WRAPPER("Log message with %s", "argument")
C23 dili
C23 için, derleyici anahtarı kullanılırken /std:clatest
aşağıdakiler kullanılabilir:
Tüm C dil sürümleri için aşağıdakiler kullanılabilir:
C++ Standart Kitaplığı
C++23 özellikleri
formattable
,range_format
,format_kind
veset_debug_format()
P2286R8 Biçimlendirme Aralıklarının bir parçası olarak<mdspan>
P0009R18 başına ve C++23 Standardına uygulanan sonraki ifade değişiklikleri.format()
P2510R3 başına işaretçiler.
Visual Studio 2022 sürüm 17.8'de uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.8, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
/FU
hatayla karşılaşır
C derleyicisi, bir süredir yönetilen derlemeyi /FU
desteklemese bile seçeneği kabul etmek için kullanılır. Şimdi bir hatayla karşılaşır. Bu seçeneği geçen projelerin yalnızca C++/CLI projelerine kısıtlaması gerekir.
C++ Standart Kitaplığı
C++23 adlı modüller std
artık std.compat
ile /std:c++20
derlenirken kullanılabilir.
C++ Standart Kitaplığında yapılan değişikliklerin daha geniş bir özeti için bkz . STL Changelog VS 2022 17.8.
Visual Studio 2022 sürüm 17.7'de uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.7, Microsoft C/C++ derleyicisinde aşağıdaki vurgulanmış uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
C derleyicisine eklendi /std:clatest
Bu anahtar, C++ derleyicisi /std:c++latest
için anahtar gibi davranır. Anahtar, bir sonraki taslak C standardı için önerilen geçerli olan tüm derleyici ve standart kitaplık özelliklerinin yanı sıra devam eden ve deneysel bazı özellikleri etkinleştirir.
C++ Standart Kitaplığı
Kitaplık <print>
artık destekleniyor. Bkz. P2093R14 Biçimlendirilmiş çıktı.
uygulandı views::cartesian_product
.
Standart Şablon Kitaplığı'na yapılan değişikliklerin daha geniş bir özeti için bkz . STL Changelog VS 2022 17.7.
using
Uygunluk
Daha önce yönergesi using
, kullanılmaması gereken durumlarda kullanılan ad alanlarının adlarının görünür kalmasına neden olabilir. Bu, etkin yönerge olmadığında using
bile ad alanında bir ad bulmak için nitelenmemiş ad aramasına neden olabilir.
Yeni ve eski davranışa ilişkin bazı örnekler aşağıda verilmiştir.
Aşağıdaki "(1)" açıklamalarındaki başvurular, ad alanında A
çağrısı f<K>(t)
anlamına gelir:
namespace A
{
template<typename K, typename T>
auto f2(T t)
{
return f<K>(t); // (1) Unqualified lookup should not find anything
}
}
namespace B
{
template<typename K, typename T>
auto f(T t) noexcept
{ // Previous behavior: This function was erroneously found during unqualified lookup at (1)
return A::f2<K>(t);
}
}
namespace C
{
template<typename T>
struct S {};
template<typename, typename U>
U&& f(U&&) noexcept; // New behavior: ADL at (1) correctly finds this function
}
namespace D
{
using namespace B;
void h()
{
D::f<void>(C::S<int>());
}
}
Aynı temel sorun, daha önce derlenmiş kodun artık reddedilmesine neden olabilir:
#include <memory>
namespace Addin {}
namespace Gui
{
using namespace Addin;
}
namespace Addin
{
using namespace std;
}
// This previously compiled, but now emits error C2065 for undeclared name 'allocator'.
// This should be declared as 'std::allocator<T*>' because the using directive nominating
// 'std' is not active at this point.
template <class T, class U = allocator<T*>>
class resource_list
{
};
namespace Gui
{
typedef resource_list<int> intlist;
}
Visual Studio 2022 sürüm 17.6'da uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.6, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Bileşik volatile
atamalar artık kullanım dışı bırakılmıyor
C++20, ile volatile
nitelenen türlere belirli işleçler uygulanarak kullanım dışı bırakıldı. Örneğin, aşağıdaki kod ile cl /std:c++20 /Wall test.cpp
derlendiğinde:
void f(volatile int& expr)
{
++expr;
}
Derleyici üretir test.cpp(3): warning C5214: applying '++' to an operand with a volatile qualified type is deprecated in C++20
.
C++20'de bileşik atama işleçleri (formun @=
işleçleri) kullanım dışı bırakıldı. C++23'te, C++20'de dışlanan bileşik işleçler artık kullanım dışı bırakılmaz. Örneğin, C++23'te aşağıdaki kod bir uyarı üretmezken C++20'de uyarı oluşturur:
void f(volatile int& e1, int e2)
{
e1 += e2;
}
Bu değişiklik hakkında daha fazla bilgi için bkz . CWG:2654
İfadelerde eşitliğin yeniden yazılması hataya neden olan bir değişiklik değildir (P2468R2)
C++20'de P2468R2 derleyiciyi aşağıdaki gibi kodu kabul etmek üzere değiştirdi:
struct S
{
bool operator==(const S&);
bool operator!=(const S&);
};
bool b = S{} != S{};
Derleyici bu kodu kabul eder, bu da derleyicinin aşağıdaki gibi kodlarla daha katı olduğu anlamına gelir:
struct S
{
operator bool() const;
bool operator==(const S&);
};
bool b = S{} == S{};
Derleyicinin 17.5 sürümü bu programı kabul eder. Derleyicinin 17.6 sürümü bunu reddeder. Düzeltmek için, belirsizliği kaldırmak için öğesini ekleyin const
operator==
. Veya aşağıdaki örnekte gösterildiği gibi tanıma karşılık gelen operator!=
bir ekleyin:
struct S
{
operator bool() const;
bool operator==(const S&);
bool operator!=(const S&);
};
bool b = S{} == S{};
Microsoft C/C++ derleyici sürümleri 17.5 ve 17.6 önceki programı kabul edin ve her iki sürümde de çağrılar S::operator==
.
P2468R2'da özetlenen genel programlama modeli, bir türe karşılık gelen operator!=
bir varsa, genellikle yeniden yazma davranışını gizlemesidir. Buna karşılık gelen operator!=
ekleme, daha önce C++17'de derlenmiş kod için önerilen düzeltmedir. Daha fazla bilgi için bkz . Programlama Modeli.
Visual Studio 2022 sürüm 17.4'te uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.4, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Sabit türü olmayan temel alınmamış enum
türleri
Visual Studio'nun Visual Studio 2022 sürüm 17.4'den önceki sürümlerinde, C++ derleyicisi sabit temel türü olmayan temel alınmamış bir numaralandırmanın temel türünü doğru şekilde belirlemedi. altında /Zc:enumTypes
artık standart davranışı doğru şekilde uyguluyoruz.
C++ Standardı, içindeki tüm numaralandırıcıları enum
barındıracak kadar büyük olması için temel alınan bir enum
türünü gerektirir. Yeterince büyük numaralandırıcılar , veya unsigned long long
olarak temel alınan türünü long long
enum
unsigned int
ayarlayabilir. Daha önce, numaralandırıcı değerlerinden int
bağımsız olarak, bu tür enum
türlerin Microsoft derleyicisinde her zaman bir temel türü vardı.
Etkinleştirildiğinde, /Zc:enumTypes
seçenek olası bir kaynak ve ikili hataya neden olan değişikliktir. Düzeltme ikili uyumluluğu etkileyebileceğinden varsayılan olarak kapalıdır ve tarafından /permissive-
etkinleştirilmez. Uyumlu düzeltme etkinleştirildiğinde bazı numaralandırma türleri boyut değiştirir. Bazı Windows SDK üst bilgileri bu tür numaralandırma tanımlarını içerir.
Örnek
enum Unsigned
{
A = 0xFFFFFFFF // Value 'A' does not fit in 'int'.
};
// Previously, failed this static_assert. Now passes with /Zc:enumTypes.
static_assert(std::is_same_v<std::underlying_type_t<Unsigned>, unsigned int>);
template <typename T>
void f(T x)
{
}
int main()
{
// Previously called f<int>, now calls f<unsigned int>.
f(+A);
}
// Previously this enum would have an underlying type of `int`, but Standard C++ requires this to have
// a 64-bit underlying type. Using /Zc:enumTypes changes the size of this enum from 4 to 8, which could
// impact binary compatibility with code compiled with an earlier compiler version or without the switch.
enum Changed
{
X = -1,
Y = 0xFFFFFFFF
};
Sabit bir temel türü olmayan bir enum
tanım içindeki numaralandırıcı türleri
Visual Studio'nun Visual Studio 2022 sürüm 17.4'den önceki sürümlerinde, C++ derleyicisi numaralandırıcı türlerini doğru modellemedi. Sabit sabit listesi kapanış ayracı öncesinde sabit bir temel türü olmayan numaralandırmalarda yanlış bir tür varsayılabilir. altında /Zc:enumTypes
, derleyici artık standart davranışı doğru şekilde uygular.
C++ Standardı, sabit temel alınmamış bir numaralandırma tanımında başlatıcıların numaralandırıcı türlerini belirlediğini belirtir. Veya başlatıcısı olmayan numaralandırıcılar için, önceki numaralandırıcının türüne göre (taşma ekleyerek). Daha önce, bu tür numaralandırıcılara her zaman temel alınan tür için bir yer tutucuyla (genellikle int
) numaralandırmanın çıkarılmış türü verilirdi.
Etkinleştirildiğinde, /Zc:enumTypes
seçenek olası bir kaynak ve ikili hataya neden olan değişikliktir. Düzeltme ikili uyumluluğu etkileyebileceğinden varsayılan olarak kapalıdır ve tarafından /permissive-
etkinleştirilmez. Uyumlu düzeltme etkinleştirildiğinde bazı numaralandırma türleri boyut değiştirir. Bazı Windows SDK üst bilgileri bu tür numaralandırma tanımlarını içerir.
Örnek
enum Enum {
A = 'A',
B = sizeof(A)
};
static_assert(B == 1); // previously failed, now succeeds under /Zc:enumTypes
Bu örnekte numaralandırıcının A
, numaralandırmanın kapanış ayracından önce türü char
olmalıdır, bu nedenle B
kullanılarak sizeof(char)
başlatılmalıdır. Düzeltmeden /Zc:enumTypes
önce, A
temel alınan türü çıkarılmış olan sabit listesi türüne Enum
int
sahipti ve B
veya 4 kullanılarak sizeof(Enum)
başlatıldı.
Visual Studio 2022 sürüm 17.3'te uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.3, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
C: İşaretçiler arasında geliştirilmiş değiştirici uyumluluk denetimi
C derleyicisi, özellikle void*
işaretçiler arasındaki değiştiricileri düzgün karşılaştırmadı. Bu hata ile arasında const int**
int* volatile*
void*
uyumsuzluk ve void*
arasındaki uyumsuzluğun yanlış tanılarına neden olabilir.
Örnek
void fn(void* pv) { (pv); }
int main()
{
int t = 42;
int* pt = &t;
int* volatile * i = &pt;
fn(i); // Now raises C4090
const int** j = &pt;
fn(j); // No longer raises C4090
}
Visual Studio 2022 sürüm 17.2'de uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.2, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Sonlandırılmamış çift yönlü karakter uyarıları
Visual Studio 2022 sürüm 17.2, açıklamalar ve dizelerdeki sonlandırılmamış Unicode çift yönlü karakterler için düzey 3 uyarısı C5255 ekler. Uyarı, Truva Atı Kaynağı: Nicholas Boucher ve Ross Anderson tarafından oluşturulan Görünmez Güvenlik Açıkları başlığı altında açıklanan güvenlik endişesini giderir. Unicode çift yönlü karakterler hakkında daha fazla bilgi için bkz . Unicode® Standart Ek #9: UNICODE ÇIFT YÖNLÜ ALGORITMA.
Uyarı C5255 yalnızca dönüştürmeden sonra Unicode çift yönlü karakterler içeren dosyaları giderir. Bu uyarı UTF-8, UTF-16 ve UTF-32 dosyaları için geçerlidir, bu nedenle doğru kaynak kodlama sağlanmalıdır. Bu değişiklik kaynak hataya neden olan bir değişikliktir.
Örnek (önce/sonra)
Visual Studio'nun Visual Studio 2022 sürüm 17.2'den önceki sürümlerinde, sonlandırılmamış bir çift yönlü karakter uyarı üretmedi. Visual Studio 2022 sürüm 17.2 uyarı C5255 üretir:
// bidi.cpp
int main() {
const char *access_level = "user";
// The following source line contains bidirectional Unicode characters equivalent to:
// if ( strcmp(access_level, "user\u202e \u2066// Check if admin \u2069 \u2066") ) {
// In most editors, it's rendered as:
// if ( strcmp(access_level, "user") ) { // Check if admin
if ( strcmp(access_level, "user // Check if admin ") ) {
printf("You are an admin.\n");
}
return 0;
}
/* build output
bidi.cpp(8): warning C5255: unterminated bidirectional character encountered: 'U+202e'
bidi.cpp(8): warning C5255: unterminated bidirectional character encountered: 'U+2066'
*/
from_chars()
float
tiebreaker
Visual Studio 2022 sürüm 17.2, tiebreaker kurallarında <charconv>
from_chars()
float
yanlış sonuçlar üreten bir hatayı düzeltir. Bu hata, dar bir aralık içinde ardışık float
değerlerin tam orta noktasında olan ondalık dizeleri etkiledi. (En küçük ve en büyük etkilenen değerler sırasıyla ve 131071.98828125
'ydi32768.009765625
.) Tiebreaker kuralı "çift" olarak yuvarlanmak istedi ve "çift" "aşağı" oldu, ancak uygulama yanlışlıkla "yukarı" yuvarladı (double
etkilenmedi).) Daha fazla bilgi ve uygulama ayrıntıları için bkz. microsoft/STL#2366.
Bu değişiklik, belirtilen durum aralığındaki çalışma zamanı davranışını etkiler:
Örnek
// from_chars_float.cpp
#include <cassert>
#include <charconv>
#include <cstdio>
#include <string_view>
#include <system_error>
using namespace std;
int main() {
const double dbl = 32768.009765625;
const auto sv = "32768.009765625"sv;
float flt = 0.0f;
const auto result = from_chars(sv.data(), sv.data() + sv.size(), flt);
assert(result.ec == errc{});
printf("from_chars() returned: %.1000g\n", flt);
printf("This rounded %s.\n", flt < dbl ? "DOWN" : "UP");
}
Visual Studio 2022 sürüm 17.2'nin önceki sürümlerinde:
C:\Temp>cl /EHsc /nologo /W4 /std:c++17 from_chars_float.cpp && from_chars_float
from_chars_float.cpp
from_chars() returned: 32768.01171875
This rounded UP.
Visual Studio 2022 sürüm 17.2 ve sonrasında:
C:\Temp>cl /EHsc /nologo /W4 /std:c++17 from_chars_float.cpp && from_chars_float
from_chars_float.cpp
from_chars() returned: 32768.0078125
This rounded DOWN.
/Zc:__STDC__
C için kullanılabilir hale getirir __STDC__
C standardı, uyumlu bir C uygulamasının olarak 1
tanımlamasını __STDC__
gerektirir. olduğunda POSIX işlevlerini __STDC__
1
kullanıma sunmayan UCRT'nin davranışı nedeniyle, kararlı dil sürümlerinde hataya neden olan değişiklikler yapmadan bu makroyu varsayılan olarak C için tanımlamak mümkün değildir. Visual Studio 2022 sürüm 17.2 ve üzeri, bu makroları tanımlayan bir uyumluluk seçeneği /Zc:__STDC__
ekler. Seçeneğin olumsuz bir sürümü yoktur. Şu anda bu seçeneği C'nin gelecekteki sürümleri için varsayılan olarak kullanmayı planlıyoruz.
Bu değişiklik kaynak hataya neden olan bir değişikliktir. C11 veya C17 modu etkinleştirildiğinde (/std:c11
veya /std:c17
) ve /Zc:__STDC__
belirtildiğinde geçerlidir.
Örnek
// test__STDC__.c
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
int main() {
#if __STDC__
int f = _open("file.txt", _O_RDONLY);
_close(f);
#else
int f = open("file.txt", O_RDONLY);
close(f);
#endif
}
/* Command line behavior
C:\Temp>cl /EHsc /W4 /Zc:__STDC__ test__STDC__.c && test__STDC__
*/
Eksik küme ayraçları için uyarı
Uyarı C5246, bir alt nesnenin toplu olarak başlatılması sırasında küme ayraçlarının eksik olduğunu bildirir. Visual Studio 2022 sürüm 17.2'den önce, uyarı anonim struct
veya union
durumunu işlemedi.
Bu değişiklik kaynak hataya neden olan bir değişikliktir. Varsayılan olmayan C5246 uyarısı etkinleştirildiğinde geçerlidir.
Örnek
Visual Studio 2022 sürüm 17.2 ve sonraki sürümlerinde bu kod artık bir hataya neden oluyor:
struct S {
union {
float f[4];
double d[2];
};
};
void f()
{
S s = { 1.0f, 2.0f, 3.14f, 4.0f };
}
/* Command line behavior
cl /Wall /c t.cpp
t.cpp(10): warning C5246: 'anonymous struct or union': the initialization of a subobject should be wrapped in braces
*/
Bu sorunu çözmek için başlatıcıya küme ayraçları ekleyin:
void f()
{
S s = { { 1.0f, 2.0f, 3.14f, 4.0f } };
}
Visual Studio 2022 sürüm 17.1'de uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.1, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Nonlocal lambda-expressions içinde hatalı biçimlendirilmiş yakalama varsayılanı algılama
C++ Standardı yalnızca blok kapsamındaki bir lambda ifadesinin yakalama varsayılanı olmasına izin verir. Visual Studio 2022 sürüm 17.1 ve sonraki sürümlerde derleyici, yerel olmayan lambda ifadesinde yakalama varsayılanı izin verilmediğinde algılar. C5253 adlı yeni bir düzey 4 uyarısı yayar.
Bu değişiklik kaynak hataya neden olan bir değişikliktir. Yeni lambda işlemcisini kullanan herhangi bir modda geçerlidir: /Zc:lambda
, /std:c++20
veya /std:c++latest
.
Örnek
Visual Studio 2022 sürüm 17.1'de bu kod artık bir hata yayar:
#pragma warning(error:5253)
auto incr = [=](int value) { return value + 1; };
// capture_default.cpp(3,14): error C5253: a nonlocal lambda cannot have a capture default
// auto incr = [=](int value) { return value + 1; };
// ^
Bu sorunu düzeltmek için yakalama varsayılanını kaldırın:
#pragma warning(error:5253)
auto incr = [](int value) { return value + 1; };
C4028 artık işlevden işaretçiye işlemler için C4133'dür
Visual Studio 2022 sürüm 17.1'den önce, derleyici C kodundaki belirli işlev işaretçisi karşılaştırmalarında yanlış bir hata iletisi bildirdi. Aynı bağımsız değişken sayılarına ama uyumsuz türlere sahip iki işlev işaretçisini karşılaştırdığınızda yanlış ileti bildirildi. Şimdi işlev parametresi uyuşmazlığı yerine işaretçiden işleve uyumsuzluktan şikayet eden farklı bir uyarı yayınlıyoruz.
Bu değişiklik kaynak hataya neden olan bir değişikliktir. Kod C olarak derlendiğinde uygulanır.
Örnek
int f1(int);
int f2(char*);
int main(void)
{
return (f1 == f2);
}
// Old warning:
// C4028: formal parameter 1 different from declaration
// New warning:
// C4113: 'int (__cdecl *)(char *)' differs in parameter lists from 'int (__cdecl *)(int)'
Bağımsız olmayan bir hata static_assert
Visual Studio 2022 sürüm 17.1 ve sonraki sürümlerinde, ile static_assert
ilişkili ifade bağımlı bir ifade değilse, derleyici ayrıştırıldığında ifadeyi değerlendirir. İfade olarak değerlendirilirse false
, derleyici bir hata yayar. Daha önce, işlevi bir işlev şablonunun gövdesindeyse static_assert
(veya bir sınıf şablonunun üye işlevinin gövdesindeyse), derleyici bu çözümlemeyi gerçekleştirmezdi.
Bu değişiklik kaynak hataya neden olan bir değişikliktir. veya /Zc:static_assert
ima /permissive-
eden herhangi bir modda geçerlidir. Bu davranış değişikliği, derleyici seçeneği kullanılarak /Zc:static_assert-
devre dışı bırakılabilir.
Örnek
Visual Studio 2022 sürüm 17.1 ve sonraki sürümlerinde bu kod artık bir hataya neden oluyor:
template<typename T>
void f()
{
static_assert(false, "BOOM!");
}
Bu sorunu düzeltmek için ifadeyi bağımlı hale getirin. Örneğin:
template<typename>
constexpr bool dependent_false = false;
template<typename T>
void f()
{
static_assert(dependent_false<T>, "BOOM!");
}
Bu değişiklikle, derleyici yalnızca işlev şablonu f
örneği oluşturulursa hata gösterir.
Visual Studio 2022 sürüm 17.0'da uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.0, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Numaralandırma türü için bit alanı genişliği uyarısı
Bir sabit listesi türünün örneğini bit alanı olarak bildirdiğinizde, bit alanının genişliği numaralandırmanın tüm olası değerlerini barındırmalıdır. Aksi takdirde, derleyici bir tanılama iletisi verir. Şu örneği göz önünde bulundurun: Göz önünde bulundurun:
enum class E : unsigned { Zero, One, Two };
struct S {
E e : 1;
};
Programcı, sınıf üyesinin S::e
açıkça adlandırılmış enum
değerlerden herhangi birini barındırabilmesini bekleyebilir. Numaralandırma öğelerinin sayısı göz önünde bulundurulduğunda, bu mümkün değildir. bitfield açıkça sağlanan değerlerin E
aralığını (kavramsal olarak etki alanıE
) kaplayamaz. Bit alanı genişliğinin numaralandırmanın etki alanı için yeterince büyük olmadığı endişesini gidermek için MSVC'ye yeni bir (varsayılan olarak kapalı) uyarısı eklenir:
t.cpp(4,5): warning C5249: 'S::e' of type 'E' has named enumerators with values that cannot be represented in the given bit field width of '1'.
E e : 1;
^
t.cpp(1,38): note: see enumerator 'E::Two' with value '2'
enum class E : unsigned { Zero, One, Two };
^
Bu derleyici davranışı, tüm /std
ve modları etkileyen bir kaynak ve /permissive
ikili hata değişikliğidir.
veya 0 ile sıralı işaretçi karşılaştırması nullptr
hatası
C++ Standardı yanlışlıkla veya 0 ile nullptr
sıralı bir işaretçi karşılaştırmasına izin verdi. Örneğin:
bool f(int *p)
{
return p >= 0;
}
WG21 kağıt N3478 bu gözetim kaldırıldı. Bu değişiklik MSVC'de uygulanır. Örnek ( ve /diagnostics:caret
) kullanılarak /permissive-
derlendiğinde aşağıdaki hatayı yayar:
t.cpp(3,14): error C7664: '>=': ordered comparison of pointer and integer zero ('int *' and 'int')
return p >= 0;
^
Bu derleyici davranışı, tüm /std
modlarda kullanılarak /permissive-
derlenen kodu etkileyen bir kaynak ve ikili hata değişikliğidir.