38

What is the difference between these two in terms of memory allocation.

char *p1 = "hello"; 
char p2[] = "hello";
Koray Tugay
  • 22,894
  • 45
  • 188
  • 319
blitzkriegz
  • 9,258
  • 18
  • 60
  • 71
  • 17
    The first should be `const char*`! – rubenvb Jan 13 '11 at 13:21
  • `p1` takes 4 or 8 bytes (required to store a memory address) which is platform dependent. `p2` takes 6 bytes (= 5 bytes for string `hello` + 1 byte for null terminating character). – RBT Sep 22 '16 at 06:12

4 Answers4

41

The first one creates a pointer variable (four or eight bytes of storage depending on the platform) and stores a location of a string literal there, The second one creates an array of six characters (including zero string terminator byte) and copies the literal there.

You should get a compiler warning on the first line since the literal is const.

Nikolai Fetissov
  • 82,306
  • 11
  • 110
  • 171
  • Where exactly is the string literal stored? Is it in heap? – blitzkriegz Jan 13 '11 at 13:19
  • 13
    The string literal is commonly stored in a region of memory separate from both the stack and the (`new`/`delete`-managed) heap. Depending on your platform, this region may be copy-protected, so writing to it will crash the program. – Fred Foo Jan 13 '11 at 13:22
  • If I'm not wrong `p2` is also nothing but a pointer variable. Isn't it? So allocation of _four or eight bytes of storage depending on the platform_ should happen in case of `p2` as well. This piece of code `p1 = p2; printf("%c" , *(p1 + 4));` prints `o`. So the only difference left is that fact that there is a null terminating character in case of declaration of `p2`. – RBT Sep 21 '16 at 01:34
9

The first one is a non-const pointer to const (read-only) data, the second is a non-const array.

Paul R
  • 208,748
  • 37
  • 389
  • 560
  • So is char *p1 = "hello" equivalent to char const *p1 = "hello"? – blitzkriegz Jan 13 '11 at 13:18
  • 3
    @Mahatma: yes, and this is also the same as the more readable and intuitive version: `const char *p1 = "hello"`. – Paul R Jan 13 '11 at 13:19
  • 2
    @Mahatma: yes, but the first is dangerous: without a `const` qualification, there is no compiler protection against attempting to modify the string literal, giving undefined behaviour. – Mike Seymour Jan 13 '11 at 13:22
  • Will there be a null terminating character in case of both `p1` and `p2` declarations? – RBT Sep 21 '16 at 01:40
  • 1
    @RBT: yes, the string literal initialiser guarantees that. – Paul R Sep 21 '16 at 06:33
  • 1
    Ok. Cool. So that means the two code blocks that asker has posted have absolutely no difference in the number of number of bytes allocated (memory taken by string + null terminating character) and both have a pointer variable each which points to starting of the allocated string. The difference you have suggested is bang on target. I couldn't digest the accepted answer on this thread thoroughly. I come from a C# background and couldn't differentiate between string literal (the read-only const thingy) and array of characters :(. – RBT Sep 21 '16 at 06:46
  • 1
    You got it! ;-) – Paul R Sep 21 '16 at 06:47
6

Since the first one is a non-const pointer to const (read-only) data, the second is a non-const array, as Paul said, you can write:

p2[2]='A'; //changing third character - okay

But you cannot write:

p1[2]='A';//changing third character - runtime error!
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 2
    The second case is actually worse than a compilation error; the compiler will most likely accept it, giving undefined runtime behaviour. – Mike Seymour Jan 13 '11 at 13:25
  • 2
    That's not true- he won't get a compile error as the string literal isn't const. He will however get UB. – Puppy Jan 13 '11 at 13:33
  • 2
    That's not fixed. That code produces UB, which is not a run-time error. It is undefined behaviour. Now, in reality on most platforms, you will get a run-time error (SIGSEGV on Unix variants, Access Violation on Windows). However, the Standard says nothing about this and since he didn't mention his platform, you can't assume it. – Puppy Jan 13 '11 at 14:06
  • @Nawaz Will there be a null terminating character in case of both p1 and p2 declarations? Also will _the additional allocation of four or eight bytes of storage depending on the platform_ would happen in case of p2 as well (same as p1) because p2 is also a pointer in the end? – RBT Sep 21 '16 at 01:43
  • @RBT: 1) **yes**, both `p1` and `p2` will be null-terminating. 2) `p1` takes exactly `sizeof(p1)` bytes of memory which stores the address of the first element of *static* array (as defined by the string literal `"hello"`). However, `p2` is *an array*, **not a pointer**, created out of the string-literal `"hello"`..and it takes `sizeof(p2)` bytes of memory. Note also that `sizeof(p1)` and `sizeof(p2)` could be different, and in this case, it would be a different for sure. – Nawaz Sep 21 '16 at 11:28
  • .... I also see what you might possibly mean by *"additional allocation"*. There is no "additional allocation" as such. The string literal `"hello"` resides in some other memory, and that is *not* a part of `p1` in any way. `p1` just happens to points to it. Nothing more than that. Let me know if that clarified your doubt. – Nawaz Sep 21 '16 at 11:33
  • Yes. `p1`'s "hello" will reside on some other memory area as it can't be modified there after which is possible in case of heap allocation.I'm just trying to understand the number of bytes consumed in two cases assuming these are the only lines of code in my console C application. For p1 - bytes pertaining to size of pointer+5 bytes for string +1 byte for null terminating character. For p2 - 5 bytes for string + 1 byte for null terminating character. That's why I was saying that p1 being a pointer causes _additional memory allocation_ which is not the case for p2 which will get stored on stack – RBT Sep 22 '16 at 02:48
  • @RBT: For `p1`, it is just the size of the pointer (which is either `4` or `8`). Nothing else. For `p2`, it is `6` bytes. In case of `p1`, there is **no** *additional memory allocation*. Take another example: `int x = 10; int *y=&x;`. Here the size of `y` is just the size of the pointer (which is either `4` or `8`). There is no additional/other allocation for `y`. – Nawaz Sep 22 '16 at 04:50
  • I was trying to compare as per OP who asked `difference between these two in terms of memory allocation` which is why I'm saying p2 is taking 6 bytes (character array) and p1 - (`4` or `8` bytes for pointer storing a memory address) + the read-only string literal pointed by p1 (6 bytes). Space taken by a pointer to store address or a read-only string literal which goes to a specialized program area are also sort of memory allocation. Isn't it? or I'm getting the verbiage wrong. Pardon me if I'm talking silly as I'm from C# world trying to learn C. – RBT Sep 22 '16 at 05:37
  • 1
    @RBT: It is technically **wrong** to say that the memory of *"read-only string literal pointed to be p1"* is part of `p1`. Take this example, `char const *x = "Rasik"; char const *y = "Rasik";`. Now print the address of both `x` and `y`; they will be same (see [demo](http://coliru.stacked-crooked.com/a/4ce53e7f1ebab29c)). What does that mean? You **cannot** say `"Rasik"` is part of memory allocated to both `x` and `y`. **That is wrong**. `"Rasik"` is a different object.... and `x` and `y` points to *that* object. There can be more pointers pointing the same object. Makes sense now? – Nawaz Sep 22 '16 at 05:45
  • ... as for your C# background, I think I know that. I had worked for 1E for 1 month ;). And yes, C#/Java/Python/etc makes few concepts of C++ really difficult to understand. – Nawaz Sep 22 '16 at 05:47
  • @RBT, @Nawaz, they call C++ difficult. C# thread function can be static or non-static (how). Lambdas have no capture specification. There is no `const` in C#. There is nothing equivalent to `static_assert` - impossible. They enjoy with run-time exceptions. Only 1 left with 1e ;) – Ajay Sep 22 '16 at 06:03
  • @Ajay: Well, C# has been made *simple* by cutting of lots of features that C++ has. C++ is *the* most complicated language (and there is a rationale for it), is a known fact. – Nawaz Sep 22 '16 at 06:56
0

The first line is assigning a string(an array of characters) to a constant (meaning you cant change the value without getting a segmentation fault) array of characters , char* essentially points to a character ( or array of bytes if its was allocated multiple character ) in memory. In the second line you are creating an array of characters ( think the same thing as the first as ,they both point to a place in memory where everything is located) , but this time , you can change the values being held within without getting a segmentation fault , as it is non-constant .

user17231236
  • 13
  • 1
  • 3