Ошибка компилятора c2040

description title ms.date f1_keywords helpviewer_keywords ms.assetid

Learn more about: Compiler Error C2040

Compiler Error C2040

11/04/2016

C2040

C2040

74ca3592-1469-4965-ab34-a4815e2fbefe

Compiler Error C2040

‘operator’ : ‘identifier1’ differs in levels of indirection from ‘identifier2’

An expression involving the specified operands has incompatible operand types or implicitly converted operand types. If both operands are arithmetic, or both are nonarithmetic (such as array or pointer), they are used without change. If one operand is arithmetic and the other is not, the arithmetic operand is converted to the type of the nonarithmetic operand.

This sample generates C2040 and shows how to fix it.

// C2040.cpp
// Compile by using: cl /c /W3 C2040.cpp
bool test() {
   char c = '3';
   return c == "3"; // C2446, C2040
   // return c == '3'; // OK
}

Asked
13 years, 5 months ago

Viewed
10k times

Error Message:

What does this mean?

And how do I fix it?

error C2040: ‘==’ : ‘int’ differs in levels of indirection from ‘const char [2]’

Code:

#include <iostream>
#include <cmath>
using namespace std;

int round(double number);
//Assumes number >=0.
//Returns number rounded to the nearest integer.

int main()
{
    double doubleValue;
    char ans;

    do
    {
        cout << "Enter a double value: ";
        cin >> doubleValue;
        cout << "Rounded that number is " <<round(doubleValue)<< endl;
        cout << "Again? (y/n): ";
        cin >> ans;

    }
    //Here is the line generating the problem, while(...);

    while (ans == 'y' || ans == "Y");

    cout << "End of testing.n";

    return 0;
}

//Uses cmath
int round(double number)
{
    return static_cast<int>(floor(number + 0.5));
}

asked Jan 2, 2010 at 8:50

user242229's user avatar

1

You need to single-quote char literals. You did this correctly for the first one but not the second:

while (ans == 'y' || ans == "Y");

This should be:

while (ans == 'y' || ans == 'Y');

Double quotes are for string (const char[]) literals.

answered Jan 2, 2010 at 8:54

Todd Gamblin's user avatar

Todd GamblinTodd Gamblin

58.2k15 gold badges89 silver badges96 bronze badges

2

You have double quotes instead of single ones on this line:

while (ans == 'y' || ans == "Y");

answered Jan 2, 2010 at 8:54

avakar's user avatar

avakaravakar

31.9k9 gold badges65 silver badges102 bronze badges

The capital Y is contained in double quotes, which creates a const char [2] (Y followed by null). You probably ment:

while (ans == 'y' || ans == 'Y');

answered Jan 2, 2010 at 8:55

e8johan's user avatar

e8johane8johan

2,89917 silver badges20 bronze badges

I dont know this is useful or not but it may be like following:

while ((ans == ‘y’) || (ans == ‘Y’));

answered Jan 2, 2010 at 9:05

Pranjali's user avatar

PranjaliPranjali

492 silver badges8 bronze badges

1

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

(даже понимая что массив — указатель на его первый элемент )

не совсем
при такой записи

C++
1
char str[] = "message";

в стеке создается массив и инициализируется строкой «message»
при такой записи

C++
1
char* str = "message";

str указатель на строку(массив) который лежит в неизменяемой памяти, так скажем вшит в текст программы компилятором

при такой записи

C++
1
const char str[] = "message";

не знаю как поведет себя компилятор
попробуй еще так

я пытаюсь локализировать ошибку

может в

C++
1
String::String( const char * str )

const стоит не там

здесь он, если не ошибаюсь, говорит неизменяемый указатель

а может нужно так

C++
1
String::String( char *  const str )

указатель на неизменяемую строку

There are several problems here. First, the C2040 and the C2440 where the types are the same type. Based on what I found in this discussion, parentheses are allowed in a declaration, so the statement:

List(tempPtr);

is apparently equivalent to:

List tempPtr;

Therefore the error is an extremely confusing way of saying you redeclared the variable tempPtr, and you gave it a different type. But note that if you wrote List*(tempPtr) it would say redefinition: different basic types, so it also seems to have to do with the fact that List is not as much of a pointer as Node* (that’s where the «levels of indirection» bit comes from). The C2440 occurs because of the redeclaration. You can confirm this by commenting out List(tempPtr); and seeing that the code will compile. However, the fact that it will compile is not to say it is in any way correct.

Problem #2 is that you don’t show here a constructor taking a Node*, and even if you had one, that wouldn’t be the right way to call it. I’m not entirely sure what you’re trying to do with that.

Problem #3 is that you are leaking Node objects like crazy. When you execute the lines:

Node* tempPtr = new Node;
tempPtr = theList.first;

and

Node* copyNode = new Node;
copyNode = tempPtr;

you are allocating Node objects and then throwing away the pointers to them. If you are trying to copy the Node objects, that isn’t the way to do it. You need a copy constructor there, too.

This is not everything that goes into a correct copy constructor for your List class, but it covers some of the biggest problems with the code you’ve posted, and especially this seems to be why you are getting those two errors.

Я получаю несколько ошибок компилятора, которые происходят из моего Copy-Constructor. Я понимаю, что первая ошибка происходит из-за несовместимых типов операндов, я просто не уверен в лучшем способе написания этого кода. И вторая ошибка, в которой я совсем не уверен. Почему бы не '=' быть в состоянии преобразовать из Узла * в Узел *?

Любая помощь или направление будут оценены.

Спасибо!

// Copy-Constructor
List::List(const List& theList)
{
Node* tempPtr = new Node;
tempPtr = theList.first;

//error C2040: 'tempPtr' : 'List' differs in levels of indirection from 'Node *'
List(tempPtr);

while (tempPtr != NULL)
{
Node* copyNode = new Node;

//error C2440: '=' :cannot convert from 'Node *' to 'Node *'
copyNode = tempPtr;

tempPtr = tempPtr->getNext();
nodeListTotal++;
}
}

Ниже мой конструктор и деструктор.

List::List():first(0), last(0), nodeListTotal(0)
{
}

// Destructor
List::~List()
{
Node* currentNode = first;

while(currentNode != NULL)
{
Node* temp = currentNode;
currentNode = currentNode->getNext();
delete temp;
}
}

0

Решение

Здесь есть несколько проблем. Во-первых, C2040 и C2440, где типы одного типа. На основании того, что я нашел в этой дискуссии, круглые скобки разрешены в объявлении, поэтому утверждение:

List(tempPtr);

по-видимому, эквивалентно:

List tempPtr;

Следовательно, ошибка — это очень запутанный способ сказать, что вы объявили переменную tempPtrи вы дали ему другой тип. Но учтите, что если вы написали List*(tempPtr) было бы сказать redefinition: different basic typesтак что это также, похоже, связано с тем, что List не столько указатель, сколько Node* (вот откуда берется «уровень косвенности»). C2440 происходит из-за повторного объявления. Вы можете подтвердить это, комментируя List(tempPtr); и увидев, что код скомпилируется. Однако тот факт, что он будет компилироваться, вовсе не означает, что это правильно.

Проблема № 2 в том, что вы не показываете здесь конструктор, принимающий Node*и даже если бы у вас был один, это не будет правильным способом назвать это. Я не совсем уверен, что вы пытаетесь сделать с этим.

Проблема № 3 в том, что вы протекаете Node объекты как сумасшедшие. Когда вы выполняете строки:

Node* tempPtr = new Node;
tempPtr = theList.first;

а также

Node* copyNode = new Node;
copyNode = tempPtr;

вы распределяете Node объекты, а затем выбрасывая указатели на них. Если вы пытаетесь скопировать Node объекты, это не способ сделать это. Вам тоже нужен конструктор копирования.

Это не все, что входит в правильный конструктор копирования для вашего List класс, но он покрывает некоторые из самых больших проблем с кодом, который вы разместили, и, особенно, кажется, именно поэтому вы получаете эти две ошибки.

0

Другие решения

Ситуация выглядит как сочетание какого-то недопонимания с вашей стороны и ошибки компилятора.

Формально заявление

 List(tempPtr);

должен интерпретироваться компилятором как объявление

 List tempPtr;

В спецификации языка 6.8 (C ++ 03) четко указано, что неоднозначность между объявлением и функциональным выражением приведена в пользу или объявлении. Это означает, что у вас есть недопустимая переопределение переменной tempPtr, Вы уже заявили tempPtr раньше с другим типом.

Тем не менее, сообщение об ошибке, выдаваемое компилятором, похоже, предполагает, что компилятор интерпретировал его как функциональное выражение приведения (вместо объявления). Это выражение пытается создать безымянный временный объект типа List из указателя tempPtr типа Node *, Этот временный объект (если он успешно создан) будет немедленно уничтожен. Тем не менее, класс List не имеет конструктора, который может построить его из Node * указатель. Это то, что говорит вам компилятор. Твой класс List имеет только один однопараметрический конструктор, который принимает const List &в то время как вы поставили Node *, Компилятор говорит вам, что не может конвертировать Node * в List чтобы вызвать этот конструктор.

Тем не менее, независимо от того, как кто-то интерпретирует это утверждение (выражение или объявление), это не имеет смысла в контексте вашего кода. Это сломано в любом случае. Итак, в основном, вопрос в том, что на Земле вы пытаетесь делать с этим List(tempPtr); линия? Каково было ваше намерение?

Вторая ошибка, вероятно, вызвана первой.

0

Понравилась статья? Поделить с друзьями:
  • Ошибка компилятора 1af8
  • Ошибка компетенции это
  • Ошибка компаса рекурсивная вложенность
  • Ошибка инициализации микрофона тарков
  • Ошибка инициализации видеокарты rdr 2