-1

Assume a function with one parameter of const char* type. When I use a string when calling that function, nothing goes wrong! I would expect that you could only input characters included in the ASCII, for example c or dec 68, but it seem otherwise. Take a look at the code below...

void InitFunction(const char* initString)
{
  std::cout << initString;
}

int main()
{
  InitFunction("Hello!");
}

When you run the code, no problem, warnings, or errors appear. I did some more testing on this as you can see from the following...

void InitFunction(char initString)
{
  std::cout << initString;
}

int main()
{
  InitFunction("Hello!");    // compiler error on this line
}

This compiles with an error since Hello! cannot be converted into char. I tried another test, but instead used const char as the function parameter type. The code still compiles with an error. But when I add * to the function parameter type, then everything compiles fine! It appears to me that the const is also necessary.

To my understanding of pointers, the function is asking for a pointer, and the pointer is identified as being a character. But this raises three problems for me.

  • First, Hello! is not in the form of a pointer. I would expect at least to have to use the reference operator (&).

  • Second, Hello! is not a char type.

  • And third, why do we need to include the const?

Am I missing something here? Do pointers and characters work in ways that I don't know?

Richard Chambers
  • 16,643
  • 4
  • 81
  • 106

2 Answers2

2

"Hello!" is a const char array of characters. Arrays are treated like a pointer, they decay to a pointer when used in a function call as an argument. The C++ standard specifies this in order to be compatible with the way that the C language standard specifies arrays are to be treated.

By the way this array decay to a pointer happens with other cases where an array is being used where a pointer or the address operator could be used such as an assignment statement. See also Arrays are Pointers?

So "Hello!" will be put into the argument list of InitFunction() as a pointer which points to where the compiler has stored the array of characters with the terminating zero character added. When the compiler generates the code for the function call, the pointer to the array of characters used as an argument to the function is const char *, a pointer to a char which is const and should not be changed.

When you have the function prototype as InitFunction(const char *), the compiler is fine with a function call such as InitFunction("Hello!");. What you are doing is providing a const char * that points to "Hello!".

However if you remove the const then since "Hello!" is a const the compiler complains. The compiler complains because a const variable is being used in a function call whose argument list is non-const indicating that the function may change what the pointer is pointing to. Since "Hello!" is not supposed to be changed, since it is const, the compiler issues an error.

If you remove the asterisk, change const char * to const char, then since "Hello!" is a char array which the compiler then decays into a pointer to the first element of the array, the compiler complains as you are trying to use a pointer for an argument that is not a pointer. In this alternative the problem is the actual data type, char versus char * is the problem.

The following lines of code would also be acceptable:

const char *p = "Hello!";  // create a pointer to an series of characters
char x1[] = "Hello!";      // create an array of char and initialize it.
char *p2 = x1;             // create a pointer to char array and initialize it.
char *p3 = x1 + 2;         // create a pointer to char array and initialize it with address of x1[2].

InitFunction (p);    // p is a const char *
InitFunction (x1);   // x1 decays to a char *
InitFunction (p2);   // p2 is a char *
InitFunction (p3);   // p3 is a char *

InitFunction (x1 + 3);  // called with address of x1[3].

Note also C++ has an actual character string type, string, that results in a dynamic character text string whose underlying physical memory layout normally includes a pointer to an array of characters. The C style array of characters that is labeled a string is not the same thing as the C++ string type.

Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
  • 1
    Well done, just a little fuzzy on the array-pointer conversion thing. While "*[arrays] decay to a pointer when used in a function call as an argument*" is perfectly true, it is not the whole truth. Arrays are converted to a pointer *on access* subject to the four exceptions contained in [C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)](http://port70.net/~nsz/c/c11/n1570.html#6.3.2.1p3). That will help prevent the lingering question of "Where else do arrays decay to a pointer?" – David C. Rankin Sep 09 '19 at 01:13
  • @DavidC.Rankin thank you for your comment with the reference to the C standard. It motivated me to look further for what amounts to a similar question within Stackoverflow that contains a number of answers with quite a bit of elaboration. – Richard Chambers Sep 09 '19 at 15:30
  • Yes, I always try and re-emphasize the issues I can remember having the "Now how the heck does that really work?" questions about. (and there are still a lot of them by the way...) – David C. Rankin Sep 09 '19 at 18:35
1

the function is asking for a pointer

Correct.

and the pointer is identified as being a character

No, a pointer is a not a character. A pointer is a pointer. This pointer points to one or more characters, i.e. an array of characters. And that's exactly what your string literal is.

First, Hello! is not in the form of a pointer.

Yes, it is. The string literal "Hello!" has type const char[7] and this decays to a pointer.

I would expect at lest to have to use the reference operator (&).

That's the address-of operator. You don't always need it to get a pointer. Example: this.

Second, Hello! is not a char type.

No, but each constituent character is.

And third, why do we need to include the const?

Because the string literal "Hello!" has type const char[7]. Dropping the const would violate const-correctness and is therefore not permitted.

This throws an error since Hello! cannot be converted into char.

That's right. A char is one byte. The string "Hello!" is not one byte. It is a string.


A C-string is typically/conventionally/usually provided in const char* form.

You should read the chapter in your book about this subject as it's a fundamental of the language. It has nothing to do with ASCII (text encodings are irrelevant to storing a sequence of bytes).

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Oh okay. I understand. So "Hello" would be treated as a string, but it can also work as an array of characters? –  Sep 07 '19 at 18:03
  • @FuzzySquid What's the difference between the two? A string _is_ an array of characters. Always has been. – Lightness Races in Orbit Sep 07 '19 at 18:09
  • Oh okay. One last thing though, what do you mean `const char[7]` "decays" to a pointer? –  Sep 07 '19 at 18:12
  • 1
    It means you can pass an array of `T`s to a function that is looking for a pointer-to-`T`*s. There is a built-in compatibility rule. If you use a recommended book it will explain this. (Watch out: some bad books incorrectly claim that "arrays are pointers", because their authors have been confused by this compatibility rule.) – Lightness Races in Orbit Sep 07 '19 at 18:14