Hello I’m using Visual Studio c++ 2010
I’m having a problem with this code ( it’s taken from C language code ) :
MEMBLOCK* create_memblock (HANDLE hProc, MEMORY_BASIC_INFORMATION *meminfo)
{
MEMBLOCK *mb = malloc(sizeof(MEMBLOCK));
if (mb)
{
mb->hProc = hProc;
mb->addr = meminfo->BaseAddress;
mb->size = meminfo->RegionSize;
mb->buffer = malloc(meminfo->RegionSize);
mb->next = NULL;
}
return mb;
}
I’m having these errors :
error C2440: 'initializing' : cannot convert from 'void *' to 'MEMBLOCK *' error C2440: '=' : cannot convert from 'PVOID' to 'unsigned char *' error C2440: '=' : cannot convert from 'void *' to 'unsigned char *'
I’m kinda newbie. Can you please provide a converted code for this that actually works with c++.
Thank you
dragosht
3,2352 gold badges23 silver badges32 bronze badges
asked Aug 7, 2014 at 15:35
3
Since you’re programming in C++, you should not use the old C function malloc
. Instead I would recommend that you use the C++ new
construct:
MEMBLOCK *mb = new MEMBLOCK;
answered Aug 7, 2014 at 15:42
In C++ You may not assign a pointer of type void *
to a pointer of some other type. So for example instead of writing
MEMBLOCK *mb = malloc(sizeof(MEMBLOCK));
You have to write
MEMBLOCK *mb = ( MEMBLOCK * )malloc(sizeof(MEMBLOCK));
Also you have to change other statements where there is the same problem. It seems these statements are
mb->addr = ( unsigned char * )meminfo->BaseAddress;
mb->buffer = ( unsigned char * )malloc(meminfo->RegionSize);
It is a good example of that you always should use an explicit casting even in C. That makes the code more safe and clear.
dnlkng
8291 gold badge10 silver badges16 bronze badges
answered Aug 7, 2014 at 15:38
Vlad from MoscowVlad from Moscow
302k26 gold badges189 silver badges335 bronze badges
1
malloc()
returns void*
, and C++ does not automatically cast void*
to a different pointer type. So you have to cast the return value:
MEMBLOCK *mb = (MEMBLOCK*) malloc(sizeof(MEMBLOCK));
Try:
MEMBLOCK* create_memblock (HANDLE hProc, MEMORY_BASIC_INFORMATION *meminfo)
{
MEMBLOCK *mb = (MEMBLOCK*)malloc(sizeof(MEMBLOCK));
if (mb)
{
mb->hProc = hProc;
mb->addr = meminfo->BaseAddress;
mb->size = meminfo->RegionSize;
mb->buffer = malloc(meminfo->RegionSize);
mb->next = NULL;
}
return mb;
}
Azeem
11.2k4 gold badges27 silver badges40 bronze badges
answered Aug 7, 2014 at 15:38
Sava B.Sava B.
1,0071 gold badge10 silver badges21 bronze badges
1
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 |
|
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.
Это отличается от аналогичных вопросов, потому что я устанавливаю значение указателя на адрес, вместо того, чтобы пытаться назначить несовместимый тип … Я думаю.
template <class Type>
class ArrayStack
{
private:
int sz; // stack size
int asz; // array size (implementation)
Type* start; // address of first element
Type arr[]; // Might need to intialize each element to 0!?
public:
ArrayStack() { sz = 0; arr[0] = 0; asz = 0; start = &arr; }
/* other code... */
};
-1
Решение
start = arr;
должен сделать свое дело.
- Вы можете назначить массив указателю, и указатель будет установлен на начало массива.
Кроме того, спецификация пустого массива:
Type arr[];
Не уверен, что это значит. Вероятно, так же, как:
Type arr[0];
Более нормально:
Type arr[asz];
Конечно, размер массива должен быть постоянным.
0
Другие решения
Предложить использование std::vector<Type> arr
вместо Type arr[]
,
template <class Type>
class ArrayStack
{
private:
int sz; // stack size
int asz; // array size (implementation)
// Type* start; // address of first element
// Don't need this at all.
// You can use &arr[0] any time you need a pointer to the
// first element.
std::vector<Type> arr;
public:
// Simplified constructor.
ArrayStack() : sz(0), asz(0), arr(1, 0) {}
/* other code... */
};
0
87
28 апреля 2009 года
Kogrom
2.7K / / 02.02.2008
Лучше все-таки изучить указатели. Особо не вникал — поправил чтоб только заработало:
Код:
#include <iostream>
#include <string>
using namespace std;
class String //user-defined string type
{
protected:
enum { SZ = 80 }; //size of all String objects
char str[SZ]; //holds a C-string
public:
String() //no-arg constructor
{ str[0] = »; }
String( char s[] ) //1-arg constructor
{ strcpy(str, s); } // convert C-string to String
void display() const //display the String
{ cout << str; }
operator char*() //conversion operator
{ return str; } //convert String to C-string
};
// Если длина ‘s’ больше 79, копируем только 80 символов
// Если меньше просто копируем s в str
class Pstring: public String
{
public:
Pstring():String()
{}
Pstring( char s[] )
{
if (strlen(s)>SZ-1)
{
for (int j=0; j<SZ-1; j++)
{
str[j]=s[j];
str[j+1]=»;
}
}
else
{
strcpy(str, s);
}
}
String& left(Pstring st, int n)
{
for (int i=0; i<=n; i++)
{
str = st.str;
str[i+1]=»;
}
return *this;
}
String& mid(Pstring st, int s, int n)
{
int u=0;
int start = s-1; // 9-1=8
int end = (n+start)-1; // 18+8=26
for (int i=start; i<=end; i++)
{
str = st.str;
str[i+1]=»;
u++;
}
return *this;
}
String& right(Pstring st, int n)
{
int u = 0;
//int len = strlen(st.str); // 54 — кол-во символов (54=»)
int start = strlen(st.str)-n; // 49 — первый копируемый символ ‘U’ser
int end = strlen(st.str)-1; // 53 — последный ‘.’
for (int i=start; i<=end; i++) // start=48, end=53;
{
str = st.str;
str[u+1]=»;
u++;
}
return *this;
}
};
////////////////////////////////////////////////////////////////
int main()
{
Pstring s1 = «It is a pleasure to welcome you as a new Premium User.»; // кол-во символов 54 (0…53)
Pstring s2,s3,s4;
s2.left(s1,7).display();
cout << endl;
s3.mid(s1,9,18).display();
cout << endl;
s4.right(s1,5).display();
cout << endl;
return 0;
}
Ошибка C2440 в C++
C2440 — это ошибка компиляции, которая возникает при создании объекта класса с помощью недопустимых аргументов конструктора. Эта ошибка может быть вызвана различными причинами, но обычно она появляется, когда типы аргументов не соответствуют типам параметров конструктора.
Прежде чем мы углубимся в причины возникновения ошибки, давайте рассмотрим некоторые термины, используемые в C++.
Класс — это пользовательский тип данных, который может содержать поля (переменные) и методы (функции). Объект — это экземпляр класса, который может быть создан с помощью конструктора класса.
Конструктор — это специальный метод класса, который выполняется при создании объекта класса. Конструкторы могут иметь параметры, которые используются для инициализации полей объекта.
Например, допустим, у нас есть класс «Person», который имеет два поля: имя и возраст. Мы можем создать конструктор, который принимает два аргумента — имя (строку) и возраст (целое число) — и использует их для инициализации соответствующих полей класса:
class Person { public: // Конструктор класса Person(string name, int age) { this->name = name; this->age = age; } // Поля класса string name; int age; };
Мы можем создать объект класса «Person» с помощью конструктора, передав ему имя и возраст:
Person john("John Doe", 30);
В этом случае мы создаем объект «john» типа «Person», инициализированный именем «John Doe» и возрастом 30.
Теперь, когда мы разобрались с основами, давайте вернемся к ошибке C2440.
Причины ошибки C2440
Ошибка C2440 может быть вызвана различными причинами, но обычно она возникает, когда типы аргументов конструктора не соответствуют типам параметров конструктора.
Допустим, у нас есть класс «Rectangle», который имеет два поля: ширину и высоту. Мы можем создать конструктор, который принимает два аргумента — ширину (целое число) и высоту (целое число) — и использует их для инициализации соответствующих полей класса:
class Rectangle { public: // Конструктор класса Rectangle(int width, int height) { this->width = width; this->height = height; } // Поля класса int width; int height; };
Мы можем создать объект класса «Rectangle» с помощью конструктора, передав ему ширину и высоту:
Rectangle rect(10, 20);
В этом случае мы создаем объект «rect» типа «Rectangle», инициализированный шириной 10 и высотой 20.
Однако если мы попытаемся создать объект класса «Rectangle», передав ему недопустимые аргументы, мы получим ошибку C2440.
Например, если мы попытаемся создать объект «rect» типа «Rectangle», передав ему строку вместо целочисленного значения для ширины:
Rectangle rect("10", 20);
Мы получим ошибку C2440:
error C2440: 'initializing': cannot convert from 'const char [3]' to 'int'
Эта ошибка говорит нам о том, что компилятор не может преобразовать тип «const char [3]» (строку) в тип «int» (ширина).
Как избежать ошибки C2440
Чтобы избежать ошибки C2440, вам нужно передавать в конструктор класса правильные типы аргументов. Если ваш конструктор принимает целочисленное значение, вы должны передавать целочисленное значение. Если ваш конструктор принимает строку, вы должны передавать строку.
Если у вас есть класс, который содержит несколько конструкторов с разными параметрами, убедитесь, что вы вызываете правильный конструктор, передавая ему правильные аргументы.
Если вы используете внешние библиотеки, убедитесь, что вы правильно подключили эти библиотеки и что вы используете правильные типы данных, определенные в этих библиотеках.
В заключение, ошибка C2440 — это проблема, которая может возникнуть в любом проекте на C++, но она может быть легко избежана, если вы следуете правильным практикам программирования и передаете в конструктор класса правильные типы аргументов. Если у вас все еще возникают проблемы с этой ошибкой, почитайте документацию к компилятору и стандарту языка C++, чтобы более полно понять, что именно вызывает ошибку.
i am getting a C2440 compiler error when i build my program but cant figure out how to fix it
Here is the line it comes up on:
if((*Iter)->classID != classID && (*Iter)->getX() == (int)pos.x && (int)(*Iter)->getY == (int)pos.y)
PLEASE HELP!!!
Billy ONeal
104k58 gold badges317 silver badges552 bronze badges
asked May 20, 2011 at 1:34
1
Looks like you’re missing ()
in your getY
call:
(int)(*Iter)->getY
should probably be (int)(*Iter)->getY()
answered May 20, 2011 at 1:37
Demian BrechtDemian Brecht
21.1k5 gold badges42 silver badges46 bronze badges
6
I guess its this part(*Iter)->getX() == (int)pos.x
and perhaps it needs to be (int)(*Iter)->getX() == (int)pos.x
. This is just a shot in the dark based on the (int)(*Iter)->getY == (int)pos.y
part of the expression. More code/context would be really helpful though. And as Demian Brecht pointed out, perhaps the ()
is missing on this part of the expression as well.
answered May 20, 2011 at 2:30
BhargavBhargav
9,8891 gold badge19 silver badges29 bronze badges
Это отличается от аналогичных вопросов, потому что я устанавливаю значение указателя на адрес, вместо того, чтобы пытаться назначить несовместимый тип … Я думаю.
template <class Type>
class ArrayStack
{
private:
int sz; // stack size
int asz; // array size (implementation)
Type* start; // address of first element
Type arr[]; // Might need to intialize each element to 0!?
public:
ArrayStack() { sz = 0; arr[0] = 0; asz = 0; start = &arr; }
/* other code... */
};
-1
Решение
start = arr;
должен сделать свое дело.
- Вы можете назначить массив указателю, и указатель будет установлен на начало массива.
Кроме того, спецификация пустого массива:
Type arr[];
Не уверен, что это значит. Вероятно, так же, как:
Type arr[0];
Более нормально:
Type arr[asz];
Конечно, размер массива должен быть постоянным.
0
Другие решения
Предложить использование std::vector<Type> arr
вместо Type arr[]
,
template <class Type>
class ArrayStack
{
private:
int sz; // stack size
int asz; // array size (implementation)
// Type* start; // address of first element
// Don't need this at all.
// You can use &arr[0] any time you need a pointer to the
// first element.
std::vector<Type> arr;
public:
// Simplified constructor.
ArrayStack() : sz(0), asz(0), arr(1, 0) {}
/* other code... */
};
0