1

I am having a little bit of trouble understanding the use of pointers. Specifically, I am confused about the following line of code:

char* s = "my String";

I have two questions:

  1. Is this code even legitimate? From watching some of the Harvard CS 50 videos, I would think that it is.

  2. If the answer to (1) is yes, then I am quite confused. I thought the meaning of the statement: "char* s" is that you want to create a new variable called s that is of type char*. This means that s is a pointer to some char variable (and at this point, we don't even know what this char variable is). If this is the case, then the right hand side of the above line of code should be an address in memory, and not a string.

I would be more comfortable with something like:

char s[10] = "my string"; //10 because including extra space for null 0  
char* AddressOfs = &s;

EDIT/UPDATE: Thanks for all the great answers. David K's answer has made things much clearer (I like the step-by-step structure), but I am still a bit confused in some respects.

  1. In step 1 of David K's answer, he said that

    It will reserve 10 bytes of memory somewhere.

But it has to reserve more than just 10 bytes, right? We need 10 bytes for the contents of the string plus 4 bytes for the contents of the address in memory.

  1. Do you agree with the following: So if we stick with the "variables-as-containers" analogy, the line

    char* s = "my string";
    

reserves 14 bytes of storage (10 for the contents of the string and 4 for the address of the contents of the string), but there is only one "container". This container is named s and holds the 4 bytes. The 10 bytes that hold the contents of the string are "container-less", i.e. these 10 bytes are allocated somewhere in memory, but there is no label that we can associate with these 10 bytes. (I'm not saying we have no way of accessing these 10 bytes. I'm just saying that there is no formal variable label that is being applied to these 10 bytes.)

5
  • Try printf("%c", 1["Hello"]). You might be surprised. The swap 1 and the string literal and try again. Note: That is just to make you think - do not use this in your code. You will find the answer here already, so please do not add a new one. Commented Aug 11, 2015 at 21:39
  • in C, an array degrades to the address of the array. In the statement: 'char* s = "my String";' the char string 'my String' +'\0' is placed in a readonly memory segment. and 's' receives a pointer to that char string (I.E. the address of that string) The char string cannot be modified, but can be read. Commented Aug 11, 2015 at 22:19
  • 1) Could use char s[] = "my string"; and s is right-sized to 10. 2) &s is the address of a pointer to an array of 10 char - not the same type as char *. Commented Aug 11, 2015 at 22:22
  • @user3629249 "placed in a readonly memory segment" and "The char string cannot be modified," are not specified by C. Attempting to modify it is undefined behavior. We agree code should not attempt/expect modifying to work. Commented Aug 11, 2015 at 22:25
  • For 3), s is a variable, as such it needs memory (as any normal int would). It happens that it points to an address, but thats just a detail. No additional space is required, if you lose that address, its lost for good, no one keeps track of it. Then, s is a variable (that consumes 4 bytes), that points to a piece of memory that has 10 bytes. Hope this clarifies a bit.
    – Leonardo
    Commented Aug 12, 2015 at 7:11

3 Answers 3

5

If you have this line of code in your source file,

char* s = "my String";

here's what your program will do:

  1. It will reserve 10 bytes of memory somewhere.
  2. It will put the characters of "my String" (including terminating null) in those ten bytes of memory.
  3. It will declare s as a char*.
  4. It will set the value of the pointer, s, to the address of the first byte of those 10 bytes of memory, where the character 'm' resides.

So it really is not very much different from this:

const char s_buffer[10] = "my String";
char* s = &s_buffer[0];

One difference that you might notice is that in the first case, there is no symbol s_buffer that you can make use of separately from s. In the first example, if the very next line is s = "another string" then (at least in principle) you lose the ability to read the particular 10 bytes that s intially pointed to.

6
  • 1
    The first 3 bullets most definitely take place before runtime, i.e., during compilation. The 4th bullet should also take place during compilation, assuming a decent compiler is in use (since the address of the constant string is well known at this point). Perhaps you meant to say "here's what your compiler will do at run time" (its own runtime)... Commented Aug 11, 2015 at 21:45
  • @barakmanos I had in mind that the locations in (virtual) memory actually get "allocated" when the program is loaded. However, a lot of what happens in the first three bullets is decided at compile time, whereas corresponding actions for the second example might only be decided when the program actually runs.
    – David K
    Commented Aug 11, 2015 at 21:49
  • locations in (virtual) memory actually get "allocated" when the program is loaded - that's an OS issue, which is unrelated to (and independent of) the program. In other words, the program "knows" nothing about it. As far as it "concerns", that string is allocated at the RO data section of the executable image. Of course, the actual (physical) address of that string maybe different every time the OS creates a process and loads it into memory. But it's like saying that the program may be running at a different place around the world, depending on where your computer is located. Commented Aug 11, 2015 at 21:55
  • More similar to const char s_buffer[10] = "my String"; Commented Aug 11, 2015 at 21:58
  • @Potatoswatter Thanks, I had momentarily considered the const, but omitted it for some reason. It is a better example as a const string (with corresponding changes to what the programmer can or can't do).
    – David K
    Commented Aug 11, 2015 at 22:19
3

char* s = "my String"; declares a string constant and a pointer to it. It's no less legitimate than using a bare string in, say, a printf call. Note, however, that because you have a pointer to your string you might be tempted to try to modify it -- that is undefined behaviour.

2

In your case

 char* s = "my String"

is legal and valid, because a representation like "my String" is called a string literal and the representation essentially gives the address of the first element in the string, which is again a pointer to a char. So, we can store that in another pointer to a char.

The usability, is mostly same with char s[10] = "my string";, except the fact that in former case, s pointing to a string literal, you cannot (even attempt to) modify it. Trying so will invoke undefined behavior.

2
  • 2
    Would const char *s = "my String" help avoid the potential for accidental UB? Commented Aug 11, 2015 at 21:55
  • @tepples Yes, in some cases, it can help. :) Commented Aug 11, 2015 at 21:57

Not the answer you're looking for? Browse other questions tagged or ask your own question.