-4

I got quite confused about what is what. Would you please tell me what each variables type is?

char foo[] = "bar";
char *bar = nullptr;
char const *qux = nullptr;

Aditionally, what is the type of "bar"?

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Swordfish
  • 12,971
  • 3
  • 21
  • 43
  • the type is the thing you say they are... "bar" is const char[] which degrades into const char *, and is legal as an initializer for char[4] – Grady Player Oct 16 '18 at 02:42
  • See [string_literal](https://en.cppreference.com/w/cpp/language/string_literal) – rsy56640 Oct 16 '18 at 02:43
  • 1
    @songyuanyao If you could write that as an answer and also explain which type `"bar`" is of, i could accept that as answer. – Swordfish Oct 16 '18 at 02:45
  • @songyuanyao Please write an answer. The comment you made is exactly the answer I am looking for. (let the confusion be my problem ;) ) – Swordfish Oct 16 '18 at 02:48
  • 2
    This could all be answered by any basic C tutorial. – Ken White Oct 16 '18 at 02:49
  • 1
    @KenWhite If you can point me to one (regardless if C or C++) that points out the differences between string literals, `char`-arrays and pointers to `char` correctly ... kudos to you. – Swordfish Oct 16 '18 at 02:50
  • 1
    @GradyPlayer: No, `"bar"` does not decay to `const char*` in that context (when it's used to initialize an array). In C, the contexts in which array-to-pointer decay does *not* occur are (a) the operand of `sizeof`, (b) the operand of unary `&`, and (c) a string literal used to initialize an array object. (There may be other cases in C++.) – Keith Thompson Oct 16 '18 at 03:09
  • @KeithThompson "(There may be other cases in C++.)" Can't think of any. – Swordfish Oct 16 '18 at 03:10
  • 1
    @downvoters WhyTF deserves this question 4 downvotes!?!?!?!? Whats f...erdammtnochmal wrong with it?? – Swordfish Oct 16 '18 at 03:31

2 Answers2

2

The type of foo is char[4], i.e. a character array containing 4 chars (including the trailing null character '\0'.)

String literals can be used to initialize character arrays. If an array is initialized like char str[] = "foo";, str will contain a copy of the string "foo".

The type of bar is char *, qux is char const *, just as you declared.

"bar" is string literal with type const char[4], i.e. an array containing 4 const chars (also including the trailing null character '\0'.)

The null character ('\0', L'\0', char16_t(), etc) is always appended to the string literal: thus, a string literal "Hello" is a const char[6] holding the characters 'H', 'e', 'l', 'l', 'o', and '\0'.

Here's a helper class which could give the exact type at compile-time (the idea is borrowed from Effective.Modern.C++ written by Scott Meyers).

template <typename>
struct TD;

then use it like

TD<decltype(foo)> td1;
TD<decltype("bar")> td2;
TD<decltype(bar)> td3;
TD<decltype(qux)> td4;

e.g. from clang you'll get error message containing type information like:

prog.cc:12:23: error: implicit instantiation of undefined template 'TD<char [4]>'
    TD<decltype(foo)> td1;
                      ^
prog.cc:13:25: error: implicit instantiation of undefined template 'TD<char const (&)[4]>'
    TD<decltype("bar")> td2;
                        ^
prog.cc:14:23: error: implicit instantiation of undefined template 'TD<char *>'
    TD<decltype(bar)> td3;
                      ^
prog.cc:15:23: error: implicit instantiation of undefined template 'TD<const char *>'
    TD<decltype(qux)> td4;
                      ^    

BTW: Because string literals are treated as lvalues, and decltype yields type of T& for lvalues, so the above message from clang gives the type of "bar" as an lvalue-reference to array, i.e. char const (&)[4].

Swordfish
  • 12,971
  • 3
  • 21
  • 43
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
-1

The variable foo is a character array. Sort of.

Somewhere in the memory of your computer the compiler has organised things so that it contains the bytes [ 0x62, 0x61, 0x72, 0x00 ] "bar\0". The compiler added the trailing \0 (0x00) for you, to mark the end of the string. Let's say the compiler put these bytes at memory address 0x00001000 - the 4096th byte.

So even though we think of foo as a character array, the variable foo is actually the address of the first element of those four bytes, so foo = 0x00001000.

The variable bar is a pointer, which is just a number. The number it holds is the address in memory of whatever it is "pointing at". Initially you set bar to be nullptr, so (probably) bar = 0x00000000.

It's quite OK to say:

bar = foo;

Which would mean that bar now points at foo. Since we said the bytes for foo were stored at some location in memory (an "address"), that number is just copied into bar. So now bar = 0x00001000 too.

The variable qux is a pointer to a constant variable. This is a special compiler note so it can generate an error if you try to modify what it's pointing at.

It's OK to code:

qux = foo;
qux = bar;

Since all these things are pointers to characters.

Kingsley
  • 14,398
  • 5
  • 31
  • 53
  • What do you mean by "The variable foo is a character array. Sort of." Sort of? – Swordfish Oct 16 '18 at 03:17
  • "The compiler added the trailing \0 (0x00) for you, to mark the end of the string." The compiler adds a `'\0'` to foo? What about the `"bar"`? – Swordfish Oct 16 '18 at 03:19
  • @Swordfish - I write "sort of" because I went on to describe what it is, and it's not a `character array`, it the address of the first element of that character array in the machine's memory. So in effect, it's a pointer. The `bar` variable is purely a pointer, no memory bytes are allocated for it by the compiler. – Kingsley Oct 16 '18 at 03:21
  • Under that circumstances, go read songyuanyao's answer. He is right, you are wrong. – Swordfish Oct 16 '18 at 03:23
  • First you talk about a variable: "The `bar` variable is purely a pointer, no memory bytes are allocated for it by the compiler." and now about a literal: "`TD td2;`" That doesn't make much sense, since a literal can't be declared. – Swordfish Oct 16 '18 at 03:29
  • @Swordfish - Songyuanyao's is referring to the `bar` variable in his answer, not your question. The variable `bar` in your question does not generate a string in memory, it points to nullptr / NULL / 0. – Kingsley Oct 16 '18 at 03:34
  • Sorry, got confused with `foo` and `bar`. "I write 'sort of' because I went on to describe what it is, and it's not a character array, it the address of the first element of that character array in the machine's memory." is still plain wrong. – Swordfish Oct 16 '18 at 03:37