0

I know you cant do this with a normal char.

    char line1 = "hello";

but you can do this with a pointer to a char type

    char* line2 = "hello";

I wanted to know why this is, what happens in the second line of code? Why is the second initialization possible? Is line2 pointing to the first index of hello? does it create some kind of array and fill it in with hello? I used this in a c string class for a programming class and I am still confused about what goes on in the second line of code.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
Hugo Perea
  • 465
  • 4
  • 15
  • 1
    It would be nice to mark the answer that helped you as accepted, you know... site rules and all that stuff like "be nice to others".. – Marco A. Sep 05 '15 at 21:44
  • Do not edit your question to state it has been answered, but accept the answer. – too honest for this site Sep 05 '15 at 22:03
  • And pick a language. C is not C++ and vice-versa. – too honest for this site Sep 05 '15 at 22:04
  • and watch out for the `char* line2 = "hello";` this is dangerous because it's assigning a constant string to a non constant pointer. Writing to that pointer later will likely cause the program to go boom with a memory access error. C++ will complain and using that sort of trick in a function call can result in some interesting compiler error messages of the "No function overload for parameter X" type. – user4581301 Sep 05 '15 at 22:38

4 Answers4

3

The compiler ensures that the null-terminated string"hello" you specified exists somewhere in memory, and initializes the pointer to point to the beginning of that string.

Alex Shtoff
  • 2,520
  • 1
  • 25
  • 53
  • Is this sort of what the strcpy() function would do?..besides making a pointer point to it. It does not place it on the heap though since it doesn't use "new". So it only "exists" temporary while the function where it is runs? or something like that. – Hugo Perea Sep 05 '15 at 21:28
  • 1
    No, it is not. The compiler is free to decide where it puts this string, however it is usually done through the Operating System facilities. Specifically, the string is embedded into the executable and loaded by the OS into memory. The compiler then just makes the pointer point to that piece of memory. – Alex Shtoff Sep 05 '15 at 21:31
  • 1
    It's worth noting that changing the characters of that string is __undefined behavior__. That's why (at least in C++), converting string literals to `char*` is deprecated. You should always use `const char*` when initializing pointers with string literals. – Emil Laine Sep 05 '15 at 21:56
1

When you write

char *line1 = "something";

line1 is created as a pointer on the stack (if in the automatic scope) and gets initialized to point to the literal string "something" (with a null terminator). To be precise the "something" string has type char[10] including the null terminator and the array decays to a pointer to the first element in this particular instance.

The data where that string is stored is the data section of your compiled executable and it is read-only (i.e. writing to it would probably trigger an access violation).

Community
  • 1
  • 1
Marco A.
  • 43,032
  • 26
  • 132
  • 246
  • I don't think that the literal is necessarily created on the stack. When the executable is loaded into memory, the pointer probably just points to the location of the string. – PC Luddite Sep 05 '15 at 21:48
  • I never wrote that a literal is created on the stack. I wrote `The data where that string is stored is the data section of your compiled executable` – Marco A. Sep 05 '15 at 21:49
  • No worries! Glad we straightened that out – Marco A. Sep 05 '15 at 21:50
1

In C and C++, when you make a string literal, there is implicitly created a variable of type char[] with static storage duration to hold it. The string will be null-terminated as is consistent with C style.

The line

char* line2 = "hello";

is roughly equivalent to

static char __string_literal_line2[] = "hello";
// At top of program or something

...
char * line2 = __string_literal_line2;

So the char[] implicitly decays to a char* when you do it this way.

A wrinkle in this is that the array really is "const" in some sense and it is undefined behavior to try to modify it, but the C standard explicitly permits you to assign it to a char * anyways, so that legacy code that is not const-correct will still compile, and to be compatible C++ also permits this.

It's sometimes really convenient if you are doing compile-time programming to take advantage of the "true form" of the string literal. For instance in this code sample:

Passing constexpr objects around

class str_const {
    const char * const p_;
    const std::size_t sz_;
public:
    template <std::size_t N>
    constexpr str_const( const char( & a )[ N ] )
    : p_( a ), sz_( N - 1 ) {}

    ...
};

The str_const object can now be constructed as a constexpr at compile time from a string literal, and it will know the size of the string literal, even though normally you need to iterate or use C library functions to determine that. That's because it receives the string literal as a char[] rather than as a char *, and it can bind to the length of the array as part of the template deduction. So these expressions are legal, and the str_const object knows the lengths of the strings at compile-time:

str_const("foo");
str_const("foobar");
str_const("foobarbaz");
Community
  • 1
  • 1
Chris Beck
  • 15,614
  • 4
  • 51
  • 87
  • 1
    "C explicitly permits you..." should probably be accompanied with some sort of cautionary text, since it's a hack so that const-incorrect legacy code doesn't need to be updated, rather than a feature that new code should use. (and IIRC it only works with *literals*; your example code shouldn't compile) –  Sep 05 '15 at 21:58
0
char test[] = "Hello" // adds H e l l o \0 in the stack 

When you do someting like f("Hello"), it reserves memory to store H e l l O \0 When you do

char *test = "Hello";

It stores Hello too somewhere and initialize test to the memory case where the 'H' is stored.

Basically pointers are 4 bytes integers. You should try to a program asking a password and verifying like this :

if(password == "mypassword")

and your job is to find "mypassword" in the generated binary.

x4rkz
  • 513
  • 4
  • 19
  • Oh I see what where I got messed up, I forgot that line1 would need to be an array of characters......... that's why it doesn't work lol. I was overthinking and brought memory into it. Does the pointer create a static memory variable? – Hugo Perea Sep 05 '15 at 21:36
  • "Basically pointers are 4 bytes integers" — usually 8 bytes nowadays, but that's not defined by the standard so you should not count on it. – Emil Laine Sep 05 '15 at 21:59