10

I know the difference between:

char *a = "string";
char p[] = "string";

from *a, it acts as the following...

     +-----+     +---+---+---+---+---+---+---+ 
  a: |  *======> | s | t | r | i | n | g |\0 |    
     +-----+     +---+---+---+---+---+---+---+ 

If I want to create another variable say

char *b;

and I hope it copies all contents in pointer a points to instead of pointing to the a's content.

     +-----+     +---+---+---+---+---+---+---+      
  a: |  *======> | s | t | r | i | n | g |\0 |    
     +-----+     +---+---+---+---+---+---+---+ 
  b: |  *======> | s | t | r | i | n | g |\0 |    
     +-----+     +---+---+---+---+---+---+---+ 

How to do this ?

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Sam
  • 4,521
  • 13
  • 46
  • 81
  • do you want to do this at runtime or compile-time? – Marco A. Oct 16 '14 at 08:32
  • @MarcoA. at runtime. thanks – Sam Oct 16 '14 at 08:32
  • awesome art +1 for that makes it very clear. – codermaster Oct 16 '14 at 08:33
  • 2
    You need to allocate memory large enough to hold the string, and make `b` point to that memory. Then you copy the string. How to allocate depends on the language, but once allocated the same function to copy a string can be used (please do some searching). Though, in C++ you should try to avoid C-style strings and pointers as much as possible, and use e.g. [`std::string`](http://en.cppreference.com/w/cpp/string/basic_string) instead. – Some programmer dude Oct 16 '14 at 08:34
  • @BLUEPIXY if you do that@ `b = strdup(a); /*stuff here*/ delete[] a;` (It is `delete[]` right?) I'd prefer to allocate on the stack like in the accepted answer personally. – Baldrickk Oct 16 '14 at 13:03
  • @Baldrickk `free(b);`, `a` is string literal. – BLUEPIXY Oct 16 '14 at 13:17
  • ah yes, I meant `b` (typo). and it is `free` because it is a `C` function, right? This is one of those functions I've not actually used myself because things like `std::string` exist. – Baldrickk Oct 16 '14 at 13:51
  • possible duplicate of [copy char\* to char\*](http://stackoverflow.com/questions/3256454/copy-char-to-char) – BartoszKP Oct 16 '14 at 16:01
  • Why did cool ASCII art made everyone forgot to look around to find tons of answers to this, and similar questions on SO? :o – BartoszKP Oct 16 '14 at 16:19

5 Answers5

8

In C++, you can do

const size_t n = strlen(a);   // excludes null terminator
char *b = new char[n + 1]{};  // {} zero initializes array
std::copy_n(a, n, b);

Live Example

However I recommend using std::string over C-style string since it is

  • deals with \0-embedded strings correctly
  • safe
  • easy to use
legends2k
  • 31,634
  • 25
  • 118
  • 222
7

In C, you can allocate a new buffer b, and then copy your string there with standard library functions like this:

b = malloc((strlen(a) + 1) * sizeof(char));
strcpy(b,a);

Note the +1 in the malloc to make room for the terminating '\0'. The sizeof(char) is redundant, but I use it for consistency.

In C++, you should use the safer and more elegant std::string:

std::string b {a};
Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • Doesn't this end in the following error: `invalid conversion from 'void*' to 'char*'` because of `malloc` return type? – Javi Marzán Nov 05 '20 at 16:05
  • 1
    @JaviMarzán It would in C++, but not in C. Some even consider casting the return of `malloc` an antipattern in C, see https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc. (And in C++, you should generally not be using `malloc` to begin with.) – Baum mit Augen Nov 05 '20 at 20:22
4

a's content, as you posted, points to a read-only memory location set up by the compiler. If you want to have another one at compile-time with distinct values you'll have to define one yourself:

char *a = "string";
char *b = "string"; // Nb. This might point to the same location as a

Notice that according to §2.14.5, whether these two pointers will point or not to the same memory location is implementation defined

Whether all string literals are distinct (that is, are stored in nonoverlapping objects) is implementation defined.

Otherwise go for a heap-stored location like:

size_t len = strlen(a); // Doesn't include null-terminator character
char *b = new char[len+1];
memcpy(b, a, len); // Assumes plain ASCII string
b[len] = '\0';

I would go for std::strings anyway.

Marco A.
  • 43,032
  • 26
  • 132
  • 246
1

You can use the non-standard (but available on many implementations) strdup function from <string.h>:

char *b;
strdup(b, a);
...
free(b);

or you can reserve space with malloc and then strcpy:

char *b;
b = malloc(strlen(a) + 1);
strcpy(b, a);
...
free(b);
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
1

The contents of a is what you have labelled as * in your diagram. a is your little box, and the contents of a are what is in the box!

The "string" is NOT the contents of a. It's somewhere else in memory, and a contains the address of that string.

Copying the contents of a to b would end up doing this:

   +-----+     +---+---+---+---+---+---+---+      
a: |  *======> | s | t | r | i | n | g |\0 |    
   +-----+  /  +---+---+---+---+---+---+---+ 
b: |  *====/
   +-----+     

To achieve what you have drawn in your second diagram, you need to take a copy of all the data which a is pointing to. This is not straightforward because how do you decide when to stop copying? There's no general way, but if you have predetermined that you just want to copy a string, then you can use a function which copies a string.

The common but non-standard strdup function will allocate new space and copy a string. Otherwise, you can allocate space (in any of the usual ways of allocating space in C) and then copy the string over to the allocated space.

M.M
  • 138,810
  • 21
  • 208
  • 365