Miglioramenti della conformità C++, modifiche del comportamento e correzioni di bug in Visual Studio 2022

Microsoft C/C++ in Visual Studio (MSVC) apporta miglioramenti alla conformità e correzioni di bug in ogni versione. Questo articolo elenca i miglioramenti significativi apportati dalla versione principale, quindi in base alla versione. Per passare direttamente alle modifiche per una versione specifica, usare i collegamenti In questo articolo .

Questo documento elenca le modifiche in Visual Studio 2022.

Per le modifiche apportate a Visual Studio 2019, vedere Miglioramenti della conformità di C++ in Visual Studio 2019.
Per le modifiche apportate a Visual Studio 2017, vedere Miglioramenti della conformità di C++ in Visual Studio 2017.
Per le modifiche apportate alle versioni precedenti, vedere Novità di Visual C++ da 2003 a 2015.

Miglioramenti della conformità in Visual Studio 2022 versione 17.9

Visual Studio 2022 versione 17.9 contiene i miglioramenti di conformità, le correzioni di bug e le modifiche di comportamento seguenti nel compilatore Microsoft C/C++.

Per un riepilogo più ampio delle modifiche apportate alla libreria dei modelli standard, vedere STL Changelog VS 2022 17.9.

Applicazione di _Alignas in un tipo strutturato in C

Nelle versioni di Visual C++ precedenti a Visual Studio 2022 versione 17.9, quando _Alignas appare accanto a un tipo di struttura in una dichiarazione, non è stato applicato correttamente in base allo standard ISO-C. Ad esempio:

// 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");

In base allo standard ISO-C, questo codice deve essere compilato senza generare static_assert una diagnostica. La _Alignas direttiva si applica solo alla variabile member1membro . Non deve modificare l'allineamento di struct Inner. Tuttavia, prima della versione 17.9.1 di Visual Studio, la diagnostica "allineamento non corretto" è stata generata. Il compilatore è allineato member2 a un offset di 32 byte all'interno di struct Outer.

Correzione di questa modifica binaria che causa un'interruzione binaria, pertanto quando viene applicata questa modifica al comportamento viene generato un avviso. Per il codice precedente, l'avviso C5274, "_Alignas non si applica più al tipo "Inner" (si applica solo agli oggetti dati dichiarati)" viene ora generato al livello di avviso 1.

Nelle versioni precedenti di Visual Studio, _Alignas è stato ignorato quando appare accanto a una dichiarazione di tipo anonimo. Ad esempio:

// 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");

In precedenza, entrambe static_assert le istruzioni non sono riuscite durante la compilazione di questo codice. Il codice ora viene compilato, ma con gli avvisi di livello 1 seguenti:

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)

Se si vuole il comportamento precedente, sostituire _Alignas(N) con __declspec(align(N)). A differenza di _Alignas, declspec(align) può essere applicato a un tipo.

__VA_OPT__ è abilitato come estensione in /Zc:preprocessor

__VA_OPT__ è stato aggiunto a C++20 e C23. Prima dell'aggiunta, non c'era un modo standard per elidere una virgola in una macro variadic. Per garantire una migliore compatibilità con le versioni precedenti, __VA_OPT__ è abilitata nel preprocessore /Zc:preprocessor basato su token in tutte le versioni del linguaggio.

Ad esempio, questa operazione viene compilata senza errori:

#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")

Linguaggio C23

Per C23, quando si usa l'opzione del /std:clatest compilatore sono disponibili le opzioni seguenti:

typeof
typeof_unqual

Di seguito sono disponibili tutte le versioni del linguaggio C:

__typeof__
__typeof_unqual__

libreria standard C++

Funzionalità di C++23

  • formattable, range_format, format_kinde set_debug_format() come parte di intervalli di formattazione P2286R8
  • <mdspan> per P0009R18 e le successive modifiche di formulazione applicate allo standard C++23.
  • format() puntatori per P2510R3.

Miglioramenti della conformità in Visual Studio 2022 versione 17.8

Visual Studio 2022 versione 17.8 contiene i miglioramenti di conformità, le correzioni di bug e le modifiche di comportamento seguenti nel compilatore Microsoft C/C++.

/FU genera un errore

Il compilatore C usato per accettare l'opzione /FU , anche se non supporta la compilazione gestita per qualche tempo. Ora genera un errore. I progetti che passano questa opzione devono limitarlo solo ai progetti C++/CLI.

libreria standard C++

I moduli denominati std C++23 e std.compat sono ora disponibili durante la compilazione con /std:c++20.

Per un riepilogo più ampio delle modifiche apportate alla libreria standard C++, vedere STL Changelog VS 2022 17.8.

Miglioramenti della conformità in Visual Studio 2022 versione 17.7

Visual Studio 2022 versione 17.7 contiene i seguenti miglioramenti di conformità evidenziati, correzioni di bug e modifiche del comportamento nel compilatore Microsoft C/C++.

Aggiunta /std:clatest al compilatore C

Questa opzione si comporta come l'opzione /std:c++latest per il compilatore C++. L'opzione abilita tutte le funzionalità del compilatore e della libreria standard attualmente implementate proposte per lo standard C successivo, nonché alcune funzionalità in corso e sperimentali.

libreria standard C++

La <print> libreria è ora supportata. Vedere P2093R14 output formattato.

Implementazione di views::cartesian_product.

Per un riepilogo più ampio delle modifiche apportate alla libreria dei modelli standard, vedere STL Changelog VS 2022 17.7.

using Conformità

In precedenza, la using direttiva poteva causare la visibilità dei nomi degli spazi dei nomi usati quando non dovrebbero. Ciò potrebbe causare la ricerca di un nome non qualificato in uno spazio dei nomi anche quando non è attiva alcuna using direttiva.

Ecco alcuni esempi del comportamento nuovo e precedente.
I riferimenti nei commenti seguenti a "(1)" indicano la chiamata a f<K>(t) nello spazio dei nomi A:

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>()); 
    } 
} 

Lo stesso problema sottostante può causare il rifiuto del codice compilato in precedenza:

#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;
}

Miglioramenti della conformità in Visual Studio 2022 versione 17.6

Visual Studio 2022 versione 17.6 contiene i miglioramenti di conformità, le correzioni di bug e le modifiche del comportamento seguenti nel compilatore Microsoft C/C++.

Assegnazioni composte volatile non più deprecate

C++20 deprecato applicando determinati operatori ai tipi qualificati con volatile. Ad esempio, quando il codice seguente viene compilato con cl /std:c++20 /Wall test.cpp:

void f(volatile int& expr)
{
   ++expr;
}

Il compilatore produce test.cpp(3): warning C5214: applying '++' to an operand with a volatile qualified type is deprecated in C++20.

In C++20 gli operatori di assegnazione composta (operatori del formato @=) sono stati deprecati. In C++23 gli operatori composti esclusi in C++20 non sono più deprecati. Ad esempio, in C++23 il codice seguente non genera un avviso, mentre in C++20:

void f(volatile int& e1, int e2)
{
   e1 += e2;
}

Per altre informazioni su questa modifica, vedere CWG:2654

La riscrittura dell'uguaglianza nelle espressioni è minore di una modifica di rilievo (P2468R2)

In C++20 P2468R2 modificato il compilatore in modo da accettare codice come:

struct S
{
    bool operator==(const S&);
    bool operator!=(const S&);
};
bool b = S{} != S{};

Il compilatore accetta questo codice, il che significa che il compilatore è più rigoroso con il codice, ad esempio:

struct S
{
  operator bool() const;
  bool operator==(const S&);
};

bool b = S{} == S{};

La versione 17.5 del compilatore accetta questo programma. La versione 17.6 del compilatore lo rifiuta. Per correggerlo, aggiungere const a operator== per rimuovere l'ambiguità. In alternativa, aggiungere un oggetto corrispondente operator!= alla definizione, come illustrato nell'esempio seguente:

struct S
{
  operator bool() const;
  bool operator==(const S&);
  bool operator!=(const S&);
};

bool b = S{} == S{};

Le versioni del compilatore Microsoft C/C++ 17.5 e 17.6 accettano il programma precedente e le chiamate S::operator== in entrambe le versioni.

Il modello di programmazione generale descritto in P2468R2 è che, se è presente un oggetto corrispondente operator!= per un tipo, in genere elimina il comportamento di riscrittura. L'aggiunta di un corrispondente operator!= è la correzione consigliata per il codice compilato in precedenza in C++17. Per altre informazioni, vedere Modello di programmazione.

Miglioramenti della conformità in Visual Studio 2022 versione 17.4

Visual Studio 2022 versione 17.4 contiene i miglioramenti di conformità, le correzioni di bug e le modifiche di comportamento seguenti nel compilatore Microsoft C/C++.

Tipi sottostanti di senza ambito enum senza tipo fisso

Nelle versioni di Visual Studio precedenti a Visual Studio 2022 versione 17.4, il compilatore C++ non ha determinato correttamente il tipo sottostante di un'enumerazione senza ambito senza tipo di base fisso. In /Zc:enumTypesè ora possibile implementare correttamente il comportamento standard.

Lo standard C++ richiede che il tipo sottostante di un oggetto enum sia sufficientemente grande da contenere tutti gli enumeratori in tale enum. Gli enumeratori sufficientemente grandi possono impostare il tipo sottostante di enum su unsigned int, long longo unsigned long long. In precedenza, tali enum tipi avevano sempre un tipo sottostante di int nel compilatore Microsoft, indipendentemente dai valori dell'enumeratore.

Se abilitata, l'opzione /Zc:enumTypes è una potenziale modifica di origine e di interruzione binaria. È disattivata per impostazione predefinita e non è abilitata da /permissive-, perché la correzione potrebbe influire sulla compatibilità binaria. Alcuni tipi di enumerazione modificano le dimensioni quando la correzione conforme è abilitata. Alcune intestazioni di Windows SDK includono tali definizioni di enumerazione.

Esempio

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
};

Tipi di enumeratori all'interno di una enum definizione senza tipo sottostante fisso

Nelle versioni di Visual Studio precedenti a Visual Studio 2022 versione 17.4, il compilatore C++ non ha modellato correttamente i tipi di enumeratori. Potrebbe presupporre un tipo non corretto nelle enumerazioni senza un tipo sottostante fisso prima della parentesi graffa di chiusura dell'enumerazione. In /Zc:enumTypesil compilatore implementa ora correttamente il comportamento standard.

Lo standard C++ specifica che all'interno di una definizione di enumerazione senza tipo sottostante fisso, gli inizializzatori determinano i tipi di enumeratori. In alternativa, per gli enumeratori senza inizializzatore, per il tipo dell'enumeratore precedente (che rappresenta l'overflow). In precedenza, tali enumeratori venivano sempre assegnati al tipo dedotto dell'enumerazione, con un segnaposto per il tipo sottostante (in intgenere ).

Se abilitata, l'opzione /Zc:enumTypes è una potenziale modifica di origine e di interruzione binaria. È disattivata per impostazione predefinita e non è abilitata da /permissive-, perché la correzione potrebbe influire sulla compatibilità binaria. Alcuni tipi di enumerazione modificano le dimensioni quando la correzione conforme è abilitata. Alcune intestazioni di Windows SDK includono tali definizioni di enumerazione.

Esempio

enum Enum {
    A = 'A',
    B = sizeof(A)
};

static_assert(B == 1); // previously failed, now succeeds under /Zc:enumTypes

In questo esempio l'enumeratore A deve avere un tipo char prima della parentesi graffa di chiusura dell'enumerazione, pertanto B deve essere inizializzata usando sizeof(char). Prima della correzione, A aveva un /Zc:enumTypes tipo Enum di enumerazione con un tipo intsottostante dedotto ed B è stato inizializzato usando sizeof(Enum), o 4.

Miglioramenti della conformità in Visual Studio 2022 versione 17.3

Visual Studio 2022 versione 17.3 contiene i miglioramenti di conformità, le correzioni di bug e le modifiche del comportamento seguenti nel compilatore Microsoft C/C++.

C: Controllo della compatibilità dei modificatori migliorato tra puntatori

Il compilatore C non ha confrontato correttamente i modificatori tra puntatori, in particolare void*. Questo difetto potrebbe comportare una diagnosi errata dell'incompatibilità tra e void* e la compatibilità tra const int**int* volatile* e void*.

Esempio

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
}

Miglioramenti della conformità in Visual Studio 2022 versione 17.2

Visual Studio 2022 versione 17.2 contiene i miglioramenti di conformità, le correzioni di bug e le modifiche del comportamento seguenti nel compilatore Microsoft C/C++.

Avvisi di caratteri bidirezionali non terminati

Visual Studio 2022 versione 17.2 aggiunge l'avviso di livello 3 C5255 per i caratteri bidirezionali Unicode senza nome nei commenti e nelle stringhe. L'avviso risolve un problema di sicurezza descritto in Trojan Source: Invisible Vulnerabilities di Nicholas Boucher e Ross Anderson. Per altre informazioni sui caratteri bidirezionali Unicode, vedere Unicode Standard Annex #9: UNICODE BIDIRECTIONAL ALGORITHM.For more information on Unicode bidirectional characters, see Unicode® Standard Annex #9: UNICODE BIDIRECTIONAL ALGORITHM.

Avviso C5255 indirizza solo i file che, dopo la conversione, contengono caratteri bidirezionali Unicode. Questo avviso si applica ai file UTF-8, UTF-16 e UTF-32, pertanto è necessario specificare la codifica di origine appropriata. Questa modifica è una modifica che causa un'interruzione di origine.

Esempio (prima/dopo)

Nelle versioni di Visual Studio precedenti a Visual Studio 2022 versione 17.2 un carattere bidirezionale non ha generato un avviso. Visual Studio 2022 versione 17.2 genera l'avviso C5255:

// 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 versione 17.2 corregge un bug nelle <charconv>from_chars()float regole tiebreaker che generano risultati non corretti. Questo bug ha interessato stringhe decimali che si trovavano al punto medio esatto dei valori consecutivi float , all'interno di un intervallo ristretto. I valori interessati più piccoli e più grandi sono rispettivamente 32768.009765625 e 131071.98828125. La regola del tiebreaker voleva arrotondare a "even" e "even" era "down", ma l'implementazione arrotondata erroneamente "up" (double non è stata influenzata. Per altre informazioni e dettagli sull'implementazione, vedere microsoft/STL#2366.

Questa modifica influisce sul comportamento di runtime nell'intervallo di casi specificato:

Esempio

// 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");
}

Nelle versioni precedenti a Visual Studio 2022 versione 17.2:

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.

In Visual Studio 2022 versione 17.2 e successive:

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__ rende __STDC__ disponibile per C

Lo standard C richiede che un'implementazione C conforme definisca __STDC__ come 1. A causa del comportamento di UCRT, che non espone le funzioni POSIX quando __STDC__ è 1, non è possibile definire questa macro per C per impostazione predefinita senza introdurre modifiche di rilievo alle versioni del linguaggio stabile. Visual Studio 2022 versione 17.2 e successive aggiungono un'opzione /Zc:__STDC__ di conformità che definisce questa macro. Non esiste alcuna versione negativa dell'opzione. Attualmente, si prevede di usare questa opzione per impostazione predefinita per le versioni future di C.

Questa modifica è una modifica che causa un'interruzione di origine. Si applica quando la modalità C11 o C17 è abilitata /std:c11 o /std:c17, insieme a /Zc:__STDC__.

Esempio

// 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__

*/

Avviso per parentesi graffe mancanti

Avviso C5246 segnala parentesi graffe mancanti durante l'inizializzazione aggregata di un oggetto secondario. Prima di Visual Studio 2022 versione 17.2, l'avviso non gestiva il caso di un anonimo struct o union.

Questa modifica è una modifica che causa un'interruzione di origine. Si applica quando è abilitato l'avviso C5246 disattivato per impostazione predefinita.

Esempio

In Visual Studio 2022 versione 17.2 e successive questo codice genera ora un errore:

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
*/

Per risolvere questo problema, aggiungere parentesi graffe all'inizializzatore:

void f()
{
   S s = { { 1.0f, 2.0f, 3.14f, 4.0f } };
}

Miglioramenti della conformità in Visual Studio 2022 versione 17.1

Visual Studio 2022 versione 17.1 contiene i miglioramenti di conformità, le correzioni di bug e le modifiche del comportamento seguenti nel compilatore Microsoft C/C++.

Rilevare l'impostazione predefinita di acquisizione in formato non corretto nelle espressioni lambda non locali

Lo standard C++ consente solo a un'espressione lambda nell'ambito del blocco di avere un'impostazione predefinita di acquisizione. In Visual Studio 2022 versione 17.1 e successive, il compilatore rileva quando un'impostazione predefinita di acquisizione non è consentita in un'espressione lambda non locale. Genera un nuovo avviso di livello 4, C5253.

Questa modifica è una modifica che causa un'interruzione di origine. Si applica in qualsiasi modalità che usa il nuovo processore lambda: /Zc:lambda, /std:c++20o /std:c++latest.

Esempio

In Visual Studio 2022 versione 17.1 questo codice genera ora un errore:

#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; };
//              ^

Per risolvere questo problema, rimuovere l'impostazione predefinita di acquisizione:

#pragma warning(error:5253)

auto incr = [](int value) { return value + 1; };

C4028 è ora C4133 per le operazioni da funzione a puntatore

Prima di Visual Studio 2022 versione 17.1, il compilatore ha segnalato un messaggio di errore errato in determinati confronti puntatore a funzione nel codice C. Il messaggio non corretto è stato segnalato quando sono stati confrontati due puntatori a funzione con lo stesso numero di argomenti, ma tipi incompatibili. A questo punto, viene generato un avviso diverso che segnala l'incompatibilità da puntatore a funzione anziché la mancata corrispondenza dei parametri di funzione.

Questa modifica è una modifica che causa un'interruzione di origine. Si applica quando il codice viene compilato come C.

Esempio

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)'

Errore in un oggetto non indipendente static_assert

In Visual Studio 2022 versione 17.1 e successive, se l'espressione associata a non static_assert è un'espressione dipendente, il compilatore valuta l'espressione quando viene analizzata. Se l'espressione restituisce false, il compilatore genera un errore. In precedenza, se l'oggetto static_assert era all'interno del corpo di un modello di funzione (o all'interno del corpo di una funzione membro di un modello di classe), il compilatore non eseguirà questa analisi.

Questa modifica è una modifica che causa un'interruzione di origine. Si applica in qualsiasi modalità che implica /permissive- o /Zc:static_assert. Questa modifica del comportamento può essere disabilitata usando l'opzione del /Zc:static_assert- compilatore.

Esempio

In Visual Studio 2022 versione 17.1 e successive questo codice genera ora un errore:

template<typename T>
void f()
{
   static_assert(false, "BOOM!");
}

Per risolvere questo problema, rendere dipendente l'espressione. Ad esempio:

template<typename>
constexpr bool dependent_false = false;

template<typename T>
void f()
{
   static_assert(dependent_false<T>, "BOOM!");
}

Con questa modifica, il compilatore genera un errore solo se viene creata un'istanza del modello f di funzione.

Miglioramenti della conformità in Visual Studio 2022 versione 17.0

Visual Studio 2022 versione 17.0 contiene i miglioramenti di conformità, le correzioni di bug e le modifiche del comportamento seguenti nel compilatore Microsoft C/C++.

Avviso sulla larghezza del campo di bit per il tipo di enumerazione

Quando si dichiara un'istanza di un tipo di enumerazione come campo di bit, la larghezza del campo di bit deve contenere tutti i valori possibili dell'enumerazione. In caso contrario, il compilatore genera un messaggio di diagnostica. Si consideri questo esempio: Prendere in considerazione:

enum class E : unsigned { Zero, One, Two };

struct S {
  E e : 1;
};

Un programmatore potrebbe aspettarsi che il membro S::e della classe possa contenere uno qualsiasi dei valori denominati enum in modo esplicito. Dato il numero di elementi di enumerazione, non è possibile. Il campo di bit non può coprire l'intervallo di valori forniti in modo esplicito di E (concettualmente, il dominio di E). Per risolvere il problema che la larghezza del campo di bit non è sufficiente per il dominio dell'enumerazione, viene aggiunto un avviso nuovo (disattivato per impostazione predefinita) a MSVC:

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 };
                                     ^

Questo comportamento del compilatore è una modifica di origine e interruzione binaria che influisce su tutte le /std modalità e /permissive .

Errore nel confronto del puntatore ordinato rispetto nullptr a o 0

Lo standard C++ ha consentito inavvertitamente un confronto del puntatore ordinato rispetto nullptr a o 0. Ad esempio:

bool f(int *p)
{
   return p >= 0;
}

Il documento WG21 N3478 ha rimosso questa supervisione. Questa modifica viene implementata in MSVC. Quando l'esempio viene compilato usando /permissive- (e /diagnostics:caret), genera l'errore seguente:

t.cpp(3,14): error C7664: '>=': ordered comparison of pointer and integer zero ('int *' and 'int')
    return p >= 0;
             ^

Questo comportamento del compilatore è una modifica che causa un'interruzione binaria e di origine che influisce sul codice compilato usando /permissive- in tutte le /std modalità.

Vedi anche

Conformità del linguaggio Microsoft C/C++