108

In C, I have two char arrays:

char array1[18] = "abcdefg";
char array2[18];

How to copy the value of array1 to array2 ? Can I just do this: array2 = array1?

moooeeeep
  • 31,622
  • 22
  • 98
  • 187
user2131316
  • 3,111
  • 12
  • 39
  • 53
  • 3
    `strcpy` or `memcpy`. – Alok Save May 20 '13 at 08:38
  • 1
    `char array1[18] = {"abcdefg"};` is not a proper char array. – aragaer May 20 '13 at 08:39
  • Use strcpy(array2,array1) function – Rohan May 20 '13 at 08:40
  • Do you wish to copy the "string" of it (until the "\0") and ignore the rest? or do you wish to copy all the array (18 chars) regardless of the content? – Roee Gavirel May 20 '13 at 08:43
  • 1
    While it does work as char array (just happens to work) it should either be declared as `char array1[18] = "abcdefg";` or `char array1[18] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', '\0'};` – aragaer May 20 '13 at 08:43
  • 14
    @aragaer 6.7.9 (14): "An array of character type may be initialized by a character string literal or UTF−8 string literal, **optionally enclosed in braces**." `char array1[18] = {"abcdefg"};` is unusual, but 100% pukka. – Daniel Fischer May 20 '13 at 10:19
  • @DanielFischer Oh. Never seen that myself. Also in my book (KR in russian) there's no mention about optional braces for that kind of initialization. – aragaer May 20 '13 at 10:38
  • but can we do the initialiation of char array like this:char array1[18] = "abcdefg";? – user2131316 May 20 '13 at 15:09
  • Does memcpy(..) handles the memory (I mean maloc and realoc inside it)? – Coldsteel48 Dec 16 '13 at 23:23

14 Answers14

106

You can't directly do array2 = array1, because in this case you manipulate the addresses of the arrays (char *) and not of their inner values (char).

What you, conceptually, want is to do is iterate through all the chars of your source (array1) and copy them to the destination (array2). There are several ways to do this. For example you could write a simple for loop, or use memcpy.

That being said, the recommended way for strings is to use strncpy. It prevents common errors resulting in, for example, buffer overflows (which is especially dangerous if array1 is filled from user input: keyboard, network, etc). Like so:

// Will copy 18 characters from array1 to array2
strncpy(array2, array1, 18);

As @Prof. Falken mentioned in a comment, strncpy can be evil. Make sure your target buffer is big enough to contain the source buffer (including the \0 at the end of the string).

aymericbeaumet
  • 6,853
  • 2
  • 37
  • 50
  • 1
    http://blogs.msdn.com/b/michael_howard/archive/2004/11/02/251296.aspx strncpy() is actually evil too. Also see http://stackoverflow.com/questions/2114896/why-is-strlcpy-and-strlcat-considered-to-be-insecure – Prof. Falken May 20 '13 at 08:44
  • why we can not just do array2 = array1? – user2131316 May 20 '13 at 09:08
  • 2
    @user2131316: This is because of the way array names are semantically converted into pointer values. I explain this in my answer. – jxh May 20 '13 at 09:23
  • It confused me that you mention `array1=array2`, which implies that array1 gets the new value, but your code does it the other way round. Just in case anybody else falls for this. – lucidbrot Apr 06 '17 at 09:47
  • strncat would always provide a nul-terminated result without buffer overrun. See [this](https://stackoverflow.com/a/1258577/4123703). – Louis Go Nov 25 '20 at 07:07
  • Thanks this is what I was looking for particularly the extra 1 char buffer to contain the /0 – JonoJames Mar 26 '21 at 03:13
45

If your arrays are not string arrays, use: memcpy(array2, array1, sizeof(array2));

airstrike
  • 2,270
  • 1
  • 25
  • 26
kAmol
  • 1,297
  • 1
  • 18
  • 29
  • Wouldn't sizeof() return the size of the pointer (i.e. the word size on your machine) ? – Wecherowski Nov 24 '19 at 10:10
  • 4
    @Wecherowski: When you pass an array to a function, it degrades to a pointer. Within that function, you cannot use `sizeof()` to determin the size of the array then. Otherwise `sizeof()` works fine for that task. –  Mar 30 '20 at 15:01
31

If you want to guard against non-terminated strings, which can cause all sorts of problems, copy your string like this:

char array1[18] = {"abcdefg"};
char array2[18];

size_t destination_size = sizeof (array2);

strncpy(array2, array1, destination_size);
array2[destination_size - 1] = '\0';

That last line is actually important, because strncpy() does not always null terminate strings. (If the destination buffer is too small to contain the whole source string, sntrcpy() will not null terminate the destination string.)

The manpage for strncpy() even states "Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated."

The reason strncpy() behaves this somewhat odd way, is because it was not actually originally intended as a safe way to copy strings.

Another way is to use snprintf() as a safe replacement for strcpy():

snprintf(array2, destination_size, "%s", array1);

(Thanks jxh for the tip.)

Daniel Causebrook
  • 469
  • 1
  • 8
  • 20
Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
  • 3
    Note that `snprintf()` does not have the problem that `strncpy()` does. – jxh May 20 '13 at 08:58
  • Does't this generate a warning? strncpy accepts const char as source. – kon psych Sep 19 '15 at 20:05
  • @konpsych that should not generate a warning. – Prof. Falken Sep 19 '15 at 21:49
  • @Prof.Falken Are there reasons to use one vs. the other? – Rahav Jun 27 '22 at 19:30
  • 1
    @Rahav, *snprintf()* is easier to use correctly than *strncpy()* – Prof. Falken Jun 27 '22 at 20:58
  • Do you expect meaningful performance differences? – Rahav Jun 27 '22 at 21:51
  • 1
    @Rahav, impossible to tell without testing, but *a)* these operation are fast on modern hardware anyway. *b)* for very tiny strings maybe strncpy() could be faster, for larger strings the actual copying in memory will dominate time taken and both should be about the same in speed is my guess. Todays compilers and libraries are also incredible at optimising and what used to be hard to guess, is now very very hard to guess. Just measure / profile if you want to be sure. In actual use there will almost never be a meaningful difference is my best guess. – Prof. Falken Jun 28 '22 at 11:09
12

As others have noted, strings are copied with strcpy() or its variants. In certain cases, you could use snprintf() as well.

You can only assign arrays the way you want as part of a structure assignment:

typedef struct { char a[18]; } array;
array array1 = { "abcdefg" };
array array2;

array2 = array1;

If your arrays are passed to a function, it will appear that you are allowed to assign them, but this is just an accident of the semantics. In C, an array will decay to a pointer type with the value of the address of the first member of the array, and this pointer is what gets passed. So, your array parameter in your function is really just a pointer. The assignment is just a pointer assignment:

void foo (char x[10], char y[10]) {
    x = y;    /* pointer assignment! */
    puts(x);
}

The array itself remains unchanged after returning from the function.

This "decay to pointer value" semantic for arrays is the reason that the assignment doesn't work. The l-value has the array type, but the r-value is the decayed pointer type, so the assignment is between incompatible types.

char array1[18] = "abcdefg";
char array2[18];
array2 = array1; /* fails because array1 becomes a pointer type,
                    but array2 is still an array type */

As to why the "decay to pointer value" semantic was introduced, this was to achieve a source code compatibility with the predecessor of C. You can read The Development of the C Language for details.

jxh
  • 69,070
  • 8
  • 110
  • 193
8

You cannot assign arrays, the names are constants that cannot be changed.

You can copy the contents, with:

strcpy(array2, array1);

assuming the source is a valid string and that the destination is large enough, as in your example.

unwind
  • 391,730
  • 64
  • 469
  • 606
4

it should look like this:

void cstringcpy(char *src, char * dest)
{
    while (*src) {
        *(dest++) = *(src++);
    }
    *dest = '\0';
}
.....

char src[6] = "Hello";
char dest[6];
cstringcpy(src, dest);
zett42
  • 25,437
  • 3
  • 35
  • 72
Boris
  • 266
  • 2
  • 5
  • 1
    Your `cstringcpy` function does not null terminate the destination array. – chqrlie Dec 13 '16 at 00:25
  • didnt get it. please provide your "fix". – Boris Dec 13 '16 at 07:45
  • @zett42: note that this `cstringcpy` function is almost exactly semantically equivalent to `strcpy`, with the same shortcomings, namely no check for buffer overflow. – chqrlie Jun 21 '17 at 06:49
2

I recommend to use memcpy() for copying data. Also if we assign a buffer to another as array2 = array1 , both array have same memory and any change in the arrary1 deflects in array2 too. But we use memcpy, both buffer have different array. I recommend memcpy() because strcpy and related function do not copy NULL character.

akhil
  • 732
  • 3
  • 13
1
array2 = array1;

is not supported in c. You have to use functions like strcpy() to do it.

MOHAMED
  • 41,599
  • 58
  • 163
  • 268
1

c functions below only ... c++ you have to do char array then use a string copy then user the string tokenizor functions... c++ made it a-lot harder to do anythng

#include <iostream>
#include <fstream>
#include <cstring>
#define TRUE 1
#define FALSE 0
typedef int Bool;
using namespace std;
Bool PalTrueFalse(char str[]);
int main(void)
{
char string[1000], ch;
int i = 0;
cout<<"Enter a message: ";

while((ch = getchar()) != '\n') //grab users input string untill 
{                               //Enter is pressed
    if (!isspace(ch) && !ispunct(ch)) //Cstring functions checking for
    {                                //spaces and punctuations of all kinds
        string[i] = tolower(ch); 
        i++;
    }
}
string[i] = '\0';  //hitting null deliminator once users input
cout<<"Your string: "<<string<<endl; 
if(PalTrueFalse(string)) //the string[i] user input is passed after
                        //being cleaned into the null function.
    cout<<"is a "<<"Palindrome\n"<<endl;
else
   cout<<"Not a palindrome\n"<<endl;
return 0;
}

Bool PalTrueFalse(char str[])
{
int left = 0;
int right = strlen(str)-1;
while (left<right)
{
   if(str[left] != str[right]) //comparing most outer values of string
       return FALSE;          //to inner values.
   left++;
   right--;
}
return TRUE;
}
1

Well, techincally you can…

typedef struct { char xx[18]; } arr_wrap;

char array1[18] = "abcdefg";
char array2[18];

*((arr_wrap *) array2) = *((arr_wrap *) array1);

printf("%s\n", array2);     /* "abcdefg" */

but it will not look very beautiful.

…Unless you use the C preprocessor…

#define CC_MEMCPY(DESTARR, SRCARR, ARRSIZE) \
    { struct _tmparrwrap_ { char xx[ARRSIZE]; }; *((struct _tmparrwrap_ *) DESTARR) = *((struct _tmparrwrap_ *) SRCARR); }

You can then do:

char array1[18] = "abcdefg";
char array2[18];

CC_MEMCPY(array2, array1, sizeof(array1));

printf("%s\n", array2);     /* "abcdefg" */

And it will work with any data type, not just char:

int numbers1[3] = { 1, 2, 3 };
int numbers2[3];

CC_MEMCPY(numbers2, numbers1, sizeof(numbers1));

printf("%d - %d - %d\n", numbers2[0], numbers2[1], numbers2[2]);     /* "abcdefg" */

(Yes, the code above is granted to work always and it's portable)

madmurphy
  • 1,451
  • 11
  • 20
0

for integer types

#include <string.h>    

int array1[10] = {0,1,2,3,4,5,6,7,8,9};
int array2[10];


memcpy(array2,array1,sizeof(array1)); // memcpy("destination","source","size")
D0rm1nd0
  • 1,333
  • 1
  • 15
  • 19
0

You cannot assign arrays to copy them. How you can copy the contents of one into another depends on multiple factors:

For char arrays, if you know the source array is null terminated and destination array is large enough for the string in the source array, including the null terminator, use strcpy():

#include <string.h>

char array1[18] = "abcdefg";
char array2[18];

...

strcpy(array2, array1);

If you do not know if the destination array is large enough, but the source is a C string, and you want the destination to be a proper C string, use snprinf():

#include <stdio.h>

char array1[] = "a longer string that might not fit";
char array2[18];

...

snprintf(array2, sizeof array2, "%s", array1);

If the source array is not necessarily null terminated, but you know both arrays have the same size, you can use memcpy:

#include <string.h>

char array1[28] = "a non null terminated string";
char array2[28];

...

memcpy(array2, array1, sizeof array2);
chqrlie
  • 131,814
  • 10
  • 121
  • 189
0

None of the above was working for me.. this works perfectly name here is char *name which is passed via the function

  1. get length of char *name using strlen(name)
  2. storing it in a const variable is important
  3. create same length size char array
  4. copy name 's content to temp using strcpy(temp, name);

use however you want, if you want original content back. strcpy(name, temp); copy temp back to name and voila works perfectly

    const int size = strlen(name);
    char temp[size];
    cout << size << endl;
    strcpy(temp, name);
0

You can't copy directly by writing array2 = array1.

If you want to copy it manually, iterate over array1 and copy item by item as follows -

int i;
for(i=0;array1[i]!='\0';i++){
 array2[i] = array1[i]; 
}
array2[i]='\0'; //put the string terminator too

If you are ok to use string library, you can do it as follows -

strncpy ( array2, array1, sizeof(array2) );
Musa
  • 3,944
  • 4
  • 21
  • 27