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 geçmek için Bu makaledeki bağlantıları kullanın.

Bu belgede Visual Studio 2022'deki değişiklikler listelenir.

Visual Studio 2019'daki değişiklikler için bkz . Visual Studio 2019'da C++ uyumluluk geliştirmeleri.
Visual Studio 2017'deki değişiklikler için bkz . Visual Studio 2017'de C++ uyumluluğu geliştirmeleri.
Eski sürümlerdeki değişiklikler için bkz . Visual C++ Yenilikler 2003 ile 2015 arasında.

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 member1uygulanır. hizalamasını struct Innerdeğ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 Outerhizalanmış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ı _Alignasolarak 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:

typeof
typeof_unqual

Tüm C dil sürümleri için aşağıdakiler kullanılabilir:

__typeof__
__typeof_unqual__

C++ Standart Kitaplığı

C++23 özellikleri

  • formattable, range_format, format_kindve set_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++20derlenirken 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 volatilenitelenen 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.cppderlendiğ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 constoperator== . 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:enumTypesartık standart davranışı doğru şekilde uyguluyoruz.

C++ Standardı, içindeki tüm numaralandırıcıları enumbarı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 longolarak temel alınan türünü long longenumunsigned intayarlayabilir. 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 Enumintsahipti 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ış "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 1tanımlamasını __STDC__ gerektirir. olduğunda POSIX işlevlerini __STDC__1kullanı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:c17ile /Zc:__STDC__birlikte uygulandığında 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 uniondurumunu 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++20veya /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_assertima /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.

Ayrıca bkz.

Microsoft C/C++ dil uyumluluğu