2

Beginning programmer here...

I'm writing a very simply program for my computer science class and I ran into an issue that I'd like to know more about. Here is my code:

#include <iostream>

using namespace std;

int main(int argc, const char * argv[])
{
    char courseLevel;

    cout << "Will you be taking graduate or undergraduate level courses (enter 'U'"
            " for undergraduate,'G' for graduate.";
    cin >> courseLevel;

    if (courseLevel == "U")
    {
        cout << "You selected undergraduate level courses.";
    }

    return 0;
}

I'm getting two error messages for my if statement: 1) Result of comparison against a string literal is unspecified (use strncmp instead). 2) Comparison between pointer and integer ('int' and 'const char*').

I seem to have resolved the issue by enclosing my U in single quotes, or the program at least works anyway. But, as I stated, I'd simply like to understand why I was getting the error so I can get a better understanding of what I'm doing.

hakre
  • 193,403
  • 52
  • 435
  • 836
Mike P
  • 419
  • 1
  • 7
  • 16

3 Answers3

5

You need to use single quotes instead.

In C, (and many other languages) a character constant is a single character1 contained in single quotes:

'U'

While a string literal is any number of characters contained in double quotes:

"U"

You declared courseLevel as a single character: char courseLevel; So you can only compare that to another single char.

When you do if (courseLevel == "U"), the left side is a char, while the right side is a const char* -- a pointer to the first char in that string literal. Your compiler is telling you this:

Comparison between pointer and integer ('int' and 'const char*')


So your options are:

if (courseLevel == 'U')       // compare char to char

Or, for sake of example:

if (courseLevel == "U"[0])    // compare char to first char in string

  1. Note for completeness: You can have mulit-character constants:

    int a = 'abcd'; // 0x61626364 in GCC

But this is certainly not what you're looking for.

Community
  • 1
  • 1
Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • Ahh, that's simple enough. Makes sense. I didn't realize that enclosing something in quotes denotes a string and enclosing it in single quotes denotes a char. That's the explanation I was looking for. Thanks! – Mike P Feb 07 '13 at 05:24
  • 1
    Being pedantic, `'abcd'` is not a multi-byte character constant. It's a **multicharacter literal**. `L'a'` is a multi-byte character constant; it represents a multi-byte character whose type is `wchar_t`. – Pete Becker Feb 07 '13 at 13:23
  • GCC calls it a "multi-character constant", which I changed it to. – Jonathon Reinhart Feb 07 '13 at 15:04
3

Rapptz is right, but I think some more elaboration should help...

courseLevel == "U"

In C and C++, double-quotes create string literals - which are arrays of characters finishing with a numerical-0 ASCII-NUL terminating sentinel character so programs can work out where the text ends. So, you basically are asking if a character is equal to an array of characters... they just can't be compared. Similar questions that are valid are:

  • does this character variable hold a specific character value: courseLevel == 'U'
  • does this character variable appear in a specific array: strchr(courseLevel, "U")
  • does this character variable match the first element in a specific array: courseLevel == "U"[0]

Of course, the first one of these is the one that makes intuitive sense in your program.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
1

The reason why you get an error is because string literals in C and C++ end with a null terminated character \0 while single characters don't. So when you compare to a char to a string literal you're comparing the character literal to a char array {'U','\0'}.

Rapptz
  • 20,807
  • 5
  • 72
  • 86
  • If you say so. Sorry I guess. – Rapptz Feb 07 '13 at 05:11
  • +1 this is relevant background – Tony Delroy Feb 07 '13 at 05:18
  • @JonathonReinhart I really don't know what to edit, sorry :( – Rapptz Feb 07 '13 at 05:33
  • @JonathonReinhart: "for argument's sake that we're dealing with DOS strings which are $ terminated" - not relevant as the question is clearly about C string literals, which are always NUL terminated - Rapptz has even restated that context in his answer. (And strictly speaking he's not comparing "a pointer to that array"... an array-to-pointer conversion would be attempted in resolving the comparison (and failed) but the rhs type is definitely array-of-char.) – Tony Delroy Feb 07 '13 at 05:36
  • @JonathonReinhart: that's still not correct though... consider that in C++ `template void f(const char (&)[N]) { ... }` can be called with a character array - that's an example of a function argument where an array isn't passed by pointer. Similarly, an `operator==` for a user defined type doesn't have to rely on the array-to-pointer standard conversion. Anyway, I'm not going to argue about it further - I've read that part of the Standard carefully many times, if you care you'll do so too. – Tony Delroy Feb 07 '13 at 05:44
  • @TonyD Why then is the compiler giving him a warning `Comparison between pointer and integer ('int' and 'const char*')` ? – Jonathon Reinhart Feb 07 '13 at 05:46
  • @JonathonReinhart: probably because it's the last Standard Conversion that particular compiler attempted before it failed, and it (poorly) issued an error about that last-ditch attempt rather than the underlying comparison. – Tony Delroy Feb 07 '13 at 05:57
  • Fair enough - but then how does one compare two "array-of-chars"? Certainly they are compared by their addresses (ie. as pointers). In a (C) test program, I just confirmed that (because of string interning) `"foo"=="foo"`, but of course, `"foo"!="foo\0"`. – Jonathon Reinhart Feb 07 '13 at 06:31
  • @JonathonReinhart: yes, the only conversion that works for two arrays is to compare after that Standard Conversion to pointers. As per C++11 2.14.5/12, "foo" may legally compare equal to "foo\0", as the compiler is allowed to find a suitable substring within another literal... similarly "afoo"+1 == "foo" may be true on some compilers. Same in C++03 (and C from memory). – Tony Delroy Feb 07 '13 at 07:59