Ошибка c2440 инициализация невозможно преобразовать

description title ms.date f1_keywords helpviewer_keywords no-loc ms.assetid

Learn about type conversion errors that cause Compiler Error C2440.

Compiler Error C2440

08/27/2021

C2440

C2440

struct

const

36e6676c-f04f-4715-8ba1-f096c4bf3b44

Compiler Error C2440

initializing‘ : cannot convert from ‘type1‘ to ‘type2
conversion‘ : cannot convert from ‘type1‘ to ‘type2

The compiler can’t implicitly convert from *type1* to *type2*, or can’t use the specified cast or conversion operator.

Remarks

The compiler generates C2440 when it can’t convert from one type to another, either implicitly or by using the specified cast or conversion operator. There are many ways to generate this error. We’ve listed some common ones in the Examples section.

Examples

C++ string literals are const

C2440 can be caused if you attempt to initialize a non-const char* (or wchar_t*) by using a string literal in C++ code, when the compiler conformance option /Zc:strictStrings is set. In C, the type of a string literal is array of char, but in C++, it’s array of const char. This sample generates C2440:

// C2440s.cpp
// Build: cl /Zc:strictStrings /W3 C2440s.cpp
// When built, the compiler emits:
// error C2440: 'initializing' : cannot convert from 'const char [5]'
// to 'char *'
//        Conversion from string literal loses const qualifier (see
// /Zc:strictStrings)

int main() {
   char* s1 = "test"; // C2440
   const char* s2 = "test"; // OK
}

C++20 u8 literals are const char8_t

In C++20 or under /Zc:char8_t, a UTF-8 literal character or string (such as u8'a' or u8"String") is of type const char8_t or const char8_t[N], respectively. This sample shows how compiler behavior changes between C++17 and C++20:

// C2440u8.cpp
// Build: cl /std:c++20 C2440u8.cpp
// When built, the compiler emits:
// error C2440: 'initializing' : cannot convert from 'const char8_t [5]'
// to 'const char *'
// note: Types pointed to are unrelated; conversion requires
// reinterpret_cast, C-style cast or function-style cast)

int main() {
   const char* s1 = u8"test"; // C2440 under /std:c++20 or /Zc:char8_t, OK in C++17
   const char8_t* s2 = u8"test"; // OK under /std:c++20 or /Zc:char8_t, C4430 in C++17
   const char* s3 = reinterpret_cast<const char*>(u8"test"); // OK
}

Pointer to member

You may see C2440 if you attempt to convert a pointer to member to void*. The next sample generates C2440:

// C2440.cpp
class B {
public:
   void  f(){;}

   typedef void (B::*pf)();

   void f2(pf pf) {
       (this->*pf)();
       void* pp = (void*)pf;   // C2440
   }

   void f3() {
      f2(f);
   }
};

Cast of undefined type

The compiler emits C2440 if you attempt to cast from a type that’s only forward declared but not defined. This sample generates C2440:

// c2440a.cpp
struct Base { }; // Defined

struct Derived; // Forward declaration, not defined

Base * func(Derived * d) {
    return static_cast<Base *>(d); // error C2440: 'static_cast' : cannot convert from 'Derived *' to 'Base *'
}

Incompatible calling convention

The C2440 errors on lines 15 and 16 of the next sample are qualified with the Incompatible calling conventions for UDT return value message. A UDT is a user-defined type, such as a class, struct, or union. These kinds of incompatibility errors are caused when the calling convention of a UDT specified in the return type of a forward declaration conflicts with the actual calling convention of the UDT and when a function pointer is involved.

In the example, first there are forward declarations for a struct and for a function that returns the struct. The compiler assumes that the struct uses the C++ calling convention. Next is the struct definition, which uses the C calling convention by default. Because the compiler doesn’t know the calling convention of the struct until it finishes reading the entire struct, the calling convention for the struct in the return type of get_c2 is also assumed to be C++.

The struct is followed by another function declaration that returns the struct. At this point, the compiler knows that the struct’s calling convention is C++. Similarly, the function pointer, which returns the struct, is defined after the struct definition. The compiler now knows the struct uses the C++ calling convention.

To resolve C2440 errors caused by incompatible calling conventions, declare functions that return a UDT after the UDT definition.

// C2440b.cpp
struct MyStruct;

MyStruct get_c1();

struct MyStruct {
   int i;
   static MyStruct get_C2();
};

MyStruct get_C3();

typedef MyStruct (*FC)();

FC fc1 = &get_c1;   // C2440, line 15
FC fc2 = &MyStruct::get_C2;   // C2440, line 16
FC fc3 = &get_C3;

class CMyClass {
public:
   explicit CMyClass( int iBar)
      throw()   {
   }

   static CMyClass get_c2();
};

int main() {
   CMyClass myclass = 2;   // C2440
   // try one of the following
   // CMyClass myclass{2};
   // CMyClass myclass(2);

   int *i;
   float j;
   j = (float)i;   // C2440, cannot cast from pointer to int to float
}

Assign zero to interior pointer

C2440 can also occur if you assign zero to an interior pointer:

// C2440c.cpp
// compile with: /clr
int main() {
   array<int>^ arr = gcnew array<int>(100);
   interior_ptr<int> ipi = &arr[0];
   ipi = 0;   // C2440
   ipi = nullptr;   // OK
}

User-defined conversions

C2440 can also occur for an incorrect use of a user-defined conversion. For example, when a conversion operator has been defined as explicit, the compiler can’t use it in an implicit conversion. For more information about user-defined conversions, see User-Defined Conversions (C++/CLI)). This sample generates C2440:

// C2440d.cpp
// compile with: /clr
value struct MyDouble {
   double d;
   // convert MyDouble to Int32
   static explicit operator System::Int32 ( MyDouble val ) {
      return (int)val.d;
   }
};

int main() {
   MyDouble d;
   int i;
   i = d;   // C2440
   // Uncomment the following line to resolve.
   // i = static_cast<int>(d);
}

System::Array creation

C2440 can also occur if you try to create an instance of an array in C++/CLI whose type is a xref:System.Array. For more information, see Arrays. The next sample generates C2440:

// C2440e.cpp
// compile with: /clr
using namespace System;
int main() {
   array<int>^ intArray = Array::CreateInstance(__typeof(int), 1);   // C2440
   // try the following line instead
   // array<int>^ intArray = safe_cast<array<int> ^>(Array::CreateInstance(__typeof(int), 1));
}

Attributes

C2440 can also occur because of changes in the attributes feature. The following sample generates C2440.

// c2440f.cpp
// compile with: /LD
[ module(name="PropDemoLib", version=1.0) ];   // C2440
// try the following line instead
// [ module(name="PropDemoLib", version="1.0") ];

Component extensions down casts

The Microsoft C++ compiler no longer allows the const_cast operator to down cast when you compile source code under /clr.

To resolve this C2440, use the correct cast operator. For more information, see Casting operators.

This sample generates C2440:

// c2440g.cpp
// compile with: /clr
ref class Base {};
ref class Derived : public Base {};
int main() {
   Derived ^d = gcnew Derived;
   Base ^b = d;
   d = const_cast<Derived^>(b);   // C2440
   d = dynamic_cast<Derived^>(b);   // OK
}

Conforming template match changes

C2440 can occur because of conformance changes to the compiler in Visual Studio 2015 Update 3. Previously, the compiler incorrectly treated certain distinct expressions as the same type when identifying a template match for a static_cast operation. Now the compiler distinguishes the types correctly, and code that relied on the previous static_cast behavior is broken. To fix this issue, change the template argument to match the template parameter type, or use a reinterpret_cast or C-style cast.

This sample generates C2440:

// c2440h.cpp

template<int *a>
struct S1 {};

int g;
struct S2 : S1<&g> {
};

int main()
{
    S2 s;
    static_cast<S1<&*&g>>(s); // C2440 in VS 2015 Update 3
    // This compiles correctly:
    // static_cast<S1<&g>>(s);
}

This error can appear in ATL code that uses the SINK_ENTRY_INFO macro defined in <atlcom.h>.

Copy-list-initialization

Visual Studio 2017 and later correctly raise compiler errors related to object creation using initializer lists. These errors weren’t caught in Visual Studio 2015 and could lead to crashes or undefined runtime behavior. In C++17 copy-list-initialization, the compiler is required to consider an explicit constructor for overload resolution, but must raise an error if that overload is actually chosen.

The following example compiles in Visual Studio 2015 but not in Visual Studio 2017.

// C2440j.cpp
struct A
{
    explicit A(int) {}
    A(double) {}
};

int main()
{
    const A& a2 = { 1 }; // error C2440: 'initializing': cannot
                         // convert from 'int' to 'const A &'
}

To correct the error, use direct initialization:

// C2440k.cpp
struct A
{
    explicit A(int) {}
    A(double) {}
};

int main()
{
    const A& a2{ 1 };
}

cv-qualifiers in class construction

In Visual Studio 2015, the compiler sometimes incorrectly ignores the cv-qualifier when generating a class object via a constructor call. This defect can potentially cause a crash or unexpected runtime behavior. The following example compiles in Visual Studio 2015 but raises a compiler error in Visual Studio 2017 and later:

struct S
{
    S(int);
    operator int();
};

int i = (const S)0; // error C2440

To correct the error, declare operator int() as const.

Столкнулся с ошибкой при выделении памяти под структуру в Си. Вот строчка, на которую указывает ошибка компиляции:

RGBTRIPLE* StringPixels = malloc((abs(biCopy.biWidth) * sizeof(RGBTRIPLE)));

RGBTRIPLE это структура для пикселей:

typedef struct
{
    BYTE rgbtBlue;
    BYTE rgbtGreen;
    BYTE rgbtRed;
} RGBTRIPLE;

Если кому не понятно, могу кинуть полный код. Сам код пробую скомпилировать на VS 2012.

αλεχολυτ's user avatar

αλεχολυτ

28.4k10 золотых знаков57 серебряных знаков118 бронзовых знаков

задан 31 июл 2016 в 17:36

Max_Advanced's user avatar

Max_AdvancedMax_Advanced

3111 золотой знак3 серебряных знака12 бронзовых знаков

malloc возвращает указатель типа void * для последующего использования его необходимо явно привести в нужный тип, например так:

RGBTRIPLE* StringPixels = (RGBTRIPLE*) malloc((abs(biCopy.biWidth) * sizeof(RGBTRIPLE)));

ответ дан 31 июл 2016 в 17:37

pavel's user avatar

1

Ваша проблема в том, что Вы компилируете сишный код компилятором c++. В c допускается неявное преобразование void* (который возвращает malloc) в T*, а вот в c++ это уже запрещено.

Поэтому, если код именно сишный, нужно и исходник компилировать как сишный. Для Visual Studio для этого обычно достаточно изменить расширение файла на .c.

Если же требуется обеспечить сборку в режиме c++, то требуется явное приведение типов, о котором уже сказано в другом ответе.

ответ дан 31 июл 2016 в 17:52

αλεχολυτ's user avatar

αλεχολυταλεχολυτ

28.4k10 золотых знаков57 серебряных знаков118 бронзовых знаков

Вот тут
Ошибка error C2440: инициализация: невозможно преобразовать «void *» в «char *»
//char *mem = malloc(strlen(str) + 1);

static inline char * strdup(const char *str)
{
	char *mem = malloc(strlen(str) + 1);
	strcpy(mem, str);

	return mem;
}

А вот тут
Ошибка error C2440: инициализация: невозможно преобразовать «void *» в «node_t *»
//node_t *node = malloc(sizeof(node_t));

void push(stack_t **top, const char *str)
{
	node_t *node = malloc(sizeof(node_t));

	node->str = strdup(str);
	node->next = NULL;

	if (!empty(top))
	{
		node->next = *top;
	}

	*top = node;
}

Аццкий Прогер

21 / 10 / 5

Регистрация: 07.01.2013

Сообщений: 222

1

16.07.2013, 20:55. Показов 5880. Ответов 7

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Задание, сделать класс динамического массива шаблонным. Вот, вроде бы сделал, но наткнулся на ошибку, что не так?
Код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include<iostream>
#include<conio.h>
using namespace std;
 
 
template <class T>
class Dynamic_array
{
private:
    T iSize, iStep, iCurInd;
    T * pArray;
    void Add_Mem(); 
public:
    Dynamic_array() : iSize(2), iStep(2), iCurInd(0), pArray( new T * [iSize] )
    {
        for( T i=0; i<iSize; ++i )
            pArray[i] = NULL;
    }
    
    ~Dynamic_array()
    {
        for( T i=0; i<iSize+1; ++i )
            delete pArray[i];
        delete pArray;
    }
    void Add();
    void Show();
};
 
template <class T>
void Dynamic_array <T> :: Add_Mem()
{
    cout << "nAdding memory..." << endl;
    T * pTemp = new T * [iSize+iStep];
    for( T i=0; i<(iSize+iStep); ++i )
        pTemp[i] = NULL;
    for( T i=0; i<iSize; ++i )
        pTemp[i] = pArray[i];
    delete [] ppAr;
    pArray = pTemp;
    iSize += iStep;
}
template <class T>
void Dynamic_array <T> :: Add()
{
    if( iCurInd==iSize )
        Add_Mem();
    pArray[iCurInd++] = new T;  
}
 
template <class T>
void Dynamic_array <T> :: Show()
{
    if (Add())
        cout<<"Add successful"<<endl;
}
 
 
int main()
{
    Dynamic_array<int> d;
    d.Add();
    d.Show();   
 
    if (_CrtDumpMemoryLeaks() != 0)
        cout<< "Oops!" << endl; 
 
    _getch();
    cout << endl;
    return 0;
}



0



:)

Эксперт С++

4773 / 3267 / 497

Регистрация: 19.02.2013

Сообщений: 9,046

16.07.2013, 22:08

2

Аццкий Прогер, судя по названию класса, должен быть динамический массив. Но, судя по коду, например, деструктора, складывается впечатление, что это какая-то матрица.
1. Почему iSize, iStep, iCurInd имеют тип T? Должен быть обычный интегральный тип (int или size_t например).
2. В инициализаторе конструктора тип поля pArray не соответствует инициализируемому значению. Лишняя *.
3. Деструктор не понятный для массива.
4. Метод Add(), скорее всего, должен принимать аргумент, которым будет инициализировано добавляемое значение.
5. И т.д….



0



21 / 10 / 5

Регистрация: 07.01.2013

Сообщений: 222

16.07.2013, 22:54

 [ТС]

3

Цитата
Сообщение от Tulosba
Посмотреть сообщение

Аццкий Прогер, судя по названию класса, должен быть динамический массив. Но, судя по коду, например, деструктора, складывается впечатление, что это какая-то матрица.
1. Почему iSize, iStep, iCurInd имеют тип T? Должен быть обычный интегральный тип (int или size_t например).
2. В инициализаторе конструктора тип поля pArray не соответствует инициализируемому значению. Лишняя *.
3. Деструктор не понятный для массива.
4. Метод Add(), скорее всего, должен принимать аргумент, которым будет инициализировано добавляемое значение.
5. И т.д….

1. согласен, тут вполне и инта хватит.
2. Тоже так подумал, но потом компилятор выдал другую ошибку: C2440: инициализация: невозможно преобразовать «int *» в «int» — вот такую.
3. что именно там не понятно? объясни свою мысль пожалуйста.
4. В обычной ситуации, так оно и было бы, но функция адд нужна, чтобы был своеобразный доступ к скрытой в привате функции адд_мем.
5. И т.д.

поясните, что делаю не так, я только начал изучать С++. И ясно дело, еще многое не понимаю.



0



alsav22

5496 / 4891 / 831

Регистрация: 04.06.2011

Сообщений: 13,587

16.07.2013, 23:53

4

Как-то так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include<iostream>
#include<conio.h>
using namespace std;
 
template <class T>
class Dynamic_array
{
private:
    int iSize, iStep, iCurInd;
    T * pArray;
    bool Add_Mem(); 
public:
    Dynamic_array() : iSize(2), iStep(2), iCurInd(0), pArray(new T [iSize])
    {
        for( int i = 0; i < iSize; ++i )
            pArray[i] = 0;
    }
    
    ~Dynamic_array()
    {
        delete pArray;
    }
    bool Add(T);
    void Show();
};
 
template <class T>
bool Dynamic_array <T> :: Add_Mem()
{
    cout << "nAdding memory..." << endl;
    T * pTemp = new T [iSize + iStep];
    if (pTemp == 0) return false;
    for( int i = 0; i < (iSize + iStep); ++i )
        pTemp[i] = 0;
    for( int i = 0; i < iSize; ++i )
        pTemp[i] = pArray[i];
    delete [] pArray;
    pArray = pTemp;
    iSize += iStep;
    return true;
}
 
template <class T>
bool Dynamic_array <T> :: Add(T a)
{
    if( iCurInd == iSize ) 
        if (!Add_Mem()) return false;
 
    pArray[iCurInd++] = a;
    cout << "Add successful" << endl;
    return true;
}
 
template <class T>
void Dynamic_array <T> :: Show()
{
    for (int i = 0; i < iCurInd; ++i)
        cout << pArray[i] << ' ';
        
}
 
 
int main()
{
    Dynamic_array<int> d;
    for (int i = 0; i < 10; ++i)
        d.Add(i);
   
    d.Show(); 
    
    if (_CrtDumpMemoryLeaks() != 0)
        cout<< "Oops!" << endl; 
 
    _getch();
    cout << endl;
    return 0;
}



1



Аццкий Прогер

21 / 10 / 5

Регистрация: 07.01.2013

Сообщений: 222

17.07.2013, 00:04

 [ТС]

5

Спасибо, некоторые свои промахи я понял. Ваш пример помог.

Цитата
Сообщение от alsav22
Посмотреть сообщение

Как-то так:

C++
1
2
3
4
    ~Dynamic_array()
    {
        delete pArray;
    }

Но, тут вот есть минус, при таком диструкторе происходит утечка памяти, но и мой вариант не помогает. Как быть?



1



Kuzia domovenok

4023 / 3280 / 920

Регистрация: 25.03.2012

Сообщений: 12,269

Записей в блоге: 1

17.07.2013, 00:08

6

Цитата
Сообщение от Аццкий Прогер
Посмотреть сообщение

~Dynamic_array()
* * {
* * * * delete pArray;
* * }

C++
1
delete[] pArray;



1



alsav22

5496 / 4891 / 831

Регистрация: 04.06.2011

Сообщений: 13,587

17.07.2013, 00:42

7

Цитата
Сообщение от Аццкий Прогер
Посмотреть сообщение

при таком диструкторе происходит утечка памяти

Это я просмотрел. Тут ошибка. Нужно

Цитата
Сообщение от Kuzia domovenok
Посмотреть сообщение

delete[] pArray;

Добавлено через 3 минуты
При таком деструкторе утечки нет.

Добавлено через 7 минут
А для проверки утечек, нужно так сделать:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include<iostream>
#include<conio.h>
using namespace std;
 
template <class T>
class Dynamic_array
{
private:
    int iSize, iStep, iCurInd;
    T * pArray;
    bool Add_Mem(); 
public:
    Dynamic_array() : iSize(2), iStep(2), iCurInd(0), pArray(new T [iSize])
    {
        for( int i = 0; i < iSize; ++i )
            pArray[i] = 0;
    }
    
    ~Dynamic_array()
    {
        delete [] pArray;
    }
    bool Add(T);
    void Show();
};
 
template <class T>
bool Dynamic_array <T> :: Add_Mem()
{
    cout << "nAdding memory..." << endl;
    T * pTemp = new T [iSize + iStep];
    if (pTemp == 0) return false;
    for( int i = 0; i < (iSize + iStep); ++i )
        pTemp[i] = 0;
    for( int i = 0; i < iSize; ++i )
        pTemp[i] = pArray[i];
    delete [] pArray;
    pArray = pTemp;
    iSize += iStep;
    return true;
}
 
template <class T>
bool Dynamic_array <T> :: Add(T a)
{
    if( iCurInd == iSize ) 
        if (!Add_Mem())
        {
            cout << "Memory allocation error!" << endl;
            return false;
        }
 
    pArray[iCurInd++] = a;
    cout << "Add successful" << endl;
    return true;
}
 
template <class T>
void Dynamic_array <T> :: Show()
{
    for (int i = 0; i < iCurInd; ++i)
        cout << pArray[i] << ' ';
        
}
 
 
int main()
{
    {
    
        Dynamic_array<int> d;
        for (int i = 0; i < 10; ++i)
            d.Add(i);
   
        d.Show(); 
    
    }
    
    if (_CrtDumpMemoryLeaks() != 0)
        cout<< "Oops!" << endl; 
    else cout << "nNo memory leaks!" << endl;
    _getch();
    cout << endl;
    return 0;
}



1



21 / 10 / 5

Регистрация: 07.01.2013

Сообщений: 222

17.07.2013, 00:54

 [ТС]

8

Цитата
Сообщение от alsav22
Посмотреть сообщение

При таком деструкторе утечки нет.

Спасибо! Теперь разобрался.



0



I tried to compile this and got mistakes such as:

Error   4   error C2440: 'initializing' : cannot convert from 'void *' to 'char *'  

This code is taken from here. Why doesn’t it work?

DWORD dwRead=0;

char *lpData = (VOID*)GlobalAlloc(GMEM_FIXED, MAX_READ),

BlackVegetable's user avatar

asked Feb 27, 2013 at 6:57

user2114177's user avatar

You appear to be compiling with a C++ compiler, so you’ll need an explicit cast:

char *lpData = (char *)GlobalAlloc(GMEM_FIXED, MAX_READ);

answered Feb 27, 2013 at 7:01

nneonneo's user avatar

nneonneonneonneo

170k36 gold badges307 silver badges377 bronze badges

1

Понравилась статья? Поделить с друзьями:
  • Ошибка c240201 kia какой электромотор
  • Ошибка c2402 kia sportage 2
  • Ошибка c23 suzuki gsx r
  • Ошибка c2280 предпринята попытка ссылки на удаленную функцию
  • Ошибка c2276 недопустимая операция с выражением привязанной функции члена