Can do this char* x;x = "XXX"; but not this char x[n];x="XXX"; why?

if i do this :->
1
2
char *a = "XXX"; //valid
char a[n] = "ZZZ"; //valid as long as n>3 //char a[] = "ZZZ....." is valid too 

but if i do this ,
1
2
3
4
5
6
7
char *a;
a = "XXXX" ; //still valid

//but not this

char a[n];
a = "XXX" ; //error :  

but why really?both of them are actually character pointers pointing to the first character ...why the first one is valid but not the second one?
char *a = "XXX"; //valid

While most compilers allow this, it actually shouldn't be valid (you'd need a const char* pointer)


both of them are actually character pointers pointing to the first character


Nope!

char a[n]; is an array.
char *a; is a pointer.

Both are two very different things, and the difference is what explains the different behavior here.

1
2
3
4
5
6
7
const char* ptr = "XXX";  // <- here, 'ptr' just points to string data which exists elsewhere

char buf[] = "ZZZ";  // <-  here, 'buf' is an array that actually holds the string data.

ptr = "YYY";  // <- OK because you're just changing the pointer to point to something else

buf = "AAA";  // <-  Error because you're trying to reassign an array, which C++ does not allow 



The thing that might be tripping you up is that arrays can be implicitly cast to pointers to their first element. So in most cases you can treat array names as if they were pointers -- even though they're not.
Yeah,that's what I was thinking .... i thought in the case of char array , the array name is also a pointer.So,the thing is I have to treat the char array as an ordinary array ...
1
2
3
char arr[10] = {'a','b','c'} ;
//or
 arr[i] = char c ;

and another thing is that, pointer to a char can be a string (an array of char)
so,i see that the array thing and pointer is deeply related here
1
2
3
4
5
6
7
8
9
10
    
char* a ="Hello";
cout<<&a[0]<<nln;
cout<<*(&a[0])<<nln;

cout<<&a[1]<<nln;
cout<<*(&a[1])<<nln;

cout<<&a[2]<<nln;
cout<<*(&a[2])<<nln;

and i got output:
Hello
H
ello
e
llo
l
So,the string is somehow address and data both.I'm really confused now.
And thanks for your answer :-)
Last edited on
The bottom line is you can't initialise an array with 4 characters if the array's size isn't large enough.

And then there's the const stuff that Disch pointed out.
and another thing is that, pointer to a char can be a string (an array of char)
so,i see that the array thing and pointer is deeply related here


There are a lot of similarities between arrays and pointers. Particularly, pointers are designed in a way which allows them to be used as if they pointed to array data. Likewise, array names can be implicitly cast to be pointers to their first element. This means you can use [] on pointers, and * on arrays.

So yeah, it's confusing.

It's easier to see if you use something that actually highlights the distinction between array names and pointers... like sizeof:

1
2
3
4
5
6
7
8
9
const char* ptr = "A longer string";
char buf[20] = "A longer string";

cout << sizeof(ptr) << endl;  // <- likely prints 4 or 8 depending on your system.
   // since 'ptr' is a pointer, it prints the size of a pointer... NOT the size of the data
   //  that is being pointed to.

cout << sizeof(buf) << endl;  // <- prints 20, the size of the array.  Since 'buf' is an
   //  array name and not a pointer... it will give you the size of the array. 



But again you can use [] or * on both the array and the pointer to get a single char:

1
2
3
4
char x = buf[0]; // x == 'A'
x = ptr[0];  // x == 'A'
x = *buf;  // same as x = buf[0]
x = *ptr;  // same as x = ptr[0] 


And once you have a char, you can use & to get a pointer to that char, just as you can with any other value:

1
2
3
4
5
char* p2 = &x;  // p2 is a pointer that points to 'x'

// however you would NOT want to send p2 to cout to print it as a string, because it does not
//  point to null-terminated string data -- it only points to a single character.  So it would print
//  a whole much of garbage after the initial 'A' character.  See below 





So,the string is somehow address and data both.I'm really confused now.


A pointer is just an address. Period. Always.

The thing that's weird here is the << operator... not pointers. The << operator treats char* pointers specially. Since they usually point to string data -- the << operator assumes that when you give it a char* pointer you are intending to print the string data being pointed to and are not trying to print the pointer itself.


You can think of the << operator having 2 versions for pointers:

1) One that takes a void* pointer, which prints a pointer normally
2) One that takes a char* pointer, which assumes it points to string data and prints that data


1
2
3
4
5
6
7
8
9
10
11
12
const char* str = "example";
const void* ptr = str;

if(str == ptr)  // <- this comparison is true... so the below line will print
    cout << "These two pointers contain the same address." << endl;
    
cout << ptr << endl;  // << is given a void pointer, so it just prints the address normally.

cout << str << endl;  // << is given a char pointer. So it thinks "hey, this must point to string data"
        // so instead of printing the address, it instead follows the pointer and begins printing string
        // data contained at that address until it reaches a null character.  As a result, the
        //  "example" string is printed. 




Your code example worked similar:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
char* a ="Hello";  // <- Again, this should be const char*, but whatever
     
cout<<&a[0]<<nln;     // <- let's walk through this:
/*
    a     = char*   (as we defined it above)
    a[0]  = char    (this takes 1 single character (the 'H') from that pointer
    &a[0] = char*   (this give us a pointer to the 'H')
    
    So really:   &a[0] == a
    They're both pointers, they both point to the exact same address, and they both are of the exact same
      type  (char*).   So when you give this pointer to cout with the << operator... it has a char pointer
      so it's like "this must be string data!" and it will print "Hello" as you expect.
*/

cout<<*(&a[0])<<nln;
/*
    a        = char*     (points to 'H')
    a[0]     = char      ('H')
    &a[0]    = char*     (points to 'H')
    *(&a[0]) = char      ('H')
    
    Also note that:   *(&a[0]) == a[0]
        
    Here, we just have a single character, 'H'.  We no longer have a pointer.
    
    When you give this to cout with the << operator... we're not giving it a pointer.  So it doesn't think we're giving it
    string data.  Instead, we're just giving it a single character, which it will print as a single character.
    
    So this will just print 'H' as you'd expect.
*/



cout<<&a[1]<<nln;
/*
    Same idea.  Note that    &a[1] == a+1
    This is still of type char*, but it no longer points to the 'H'.  Now, it points to the 'e'.
    
    So when we send this to cout, it will print string data starting from 'e' until it reaches the
    null terminator at the end.  Resulting in "ello"
*/

cout<<*(&a[1])<<nln;
/*
    *(&a[1]) == a[1]
    
    Again, this is of type char (not of type char*).  So this is NOT a pointer, but is just a single
    character.  And again, this is the 'e' instead of the 'H' now.  So when we print this it'll just
    print 'e' as you'd expect
*/
Topic archived. No new replies allowed.