HOWTO · Arduino

Arduino Strcpy Function

Use strcpy() with Arduino character arrays, size destination buffers, and compare bounded-copy options.

On this page

Use strcpy(destination, source) to copy a null-terminated C string, including its terminating \0. The destination must have room for every source character plus that terminator. For example, "Hello World" needs 12 bytes. This function works with character arrays, not Arduino String objects; do not use it when the source and destination overlap.

Understand strcpy() and Null-Terminated Strings

A C string is a sequence of characters followed by a null byte (\0). strcpy() takes a writable destination pointer and a source pointer to such a string. It copies through the source terminator and returns the destination pointer. The source may be declared const char *; the destination must be writable.

The function does not receive the destination capacity, so it cannot check whether the array is large enough. If there is not enough room for all characters and the terminator, the program has undefined behavior. A run that appears to work does not make an undersized copy safe. Also distinguish a C string such as char name[] from an Arduino String object, which uses a different interface.

Copy a String with strcpy() Safely

This complete sketch copies the 11 characters in "Hello World" and its terminating \0 into a 12-byte array, then prints the copied string over Serial. The host-side Serial stand-in below lets the same setup() logic run as a self-contained example; on an Arduino board, the core supplies Serial and calls setup().

#include <cstring>
#ifndef ARDUINO
#include <iostream>
struct SerialPort {
    void begin(unsigned long) {}
    void println(const char* value) { std::cout << value << '\n'; }
} Serial;
#endif

const char source[] = "Hello World";
char destination[sizeof(source)]; // 12 bytes: 11 characters plus \0

void setup() {
    Serial.begin(9600);
    std::strcpy(destination, source);
    Serial.println(destination);
}

void loop() {
    // The copy is performed once in setup().
}

#ifndef ARDUINO
int main() {
    setup();
    return 0;
}
#endif
Hello World

For this fixed source, sizeof(source) includes the terminator, so the destination capacity is 12 bytes. For a pointer to text, sizeof(pointer) is only the pointer size; calculate the required capacity from the string length plus one instead. Keep source and destination as separate, non-overlapping storage. The following host C example demonstrates the same known-string copy in the configured runtime.

#include <stdio.h>
#include <string.h>

int main(void) {
    const char source[] = "Hello World";
    char destination[sizeof(source)];

    strcpy(destination, source);
    puts(destination);
    return 0;
}
Hello World

Compare strncpy() and strlcpy()

strncpy(destination, source, count) copies at most count bytes. If the source ends before count, it pads the remaining destination bytes with null bytes. If the source has at least count bytes, it does not append a terminator. Therefore, a destination filled to its capacity by strncpy() must not be passed to string functions until termination is established. For a destination array with capacity greater than zero, one common pattern is to copy at most capacity - 1 bytes and then set destination[capacity - 1] = '\0'. This produces a terminated, possibly truncated string; it does not by itself validate the source or prevent unrelated memory errors.

strlcpy(destination, source, size) takes the total destination capacity, including room for \0, and when size is greater than zero it terminates the destination. It truncates when needed and returns the length of the full source, which can be compared with size to detect truncation. Availability is not universal: check that the selected Arduino core and toolchain provide strlcpy() before using it. If they do not, use a supported routine or a carefully sized copy strategy.

Copy Serial Input into a Character Array

This sketch reads at most 31 bytes into a 32-byte input array, writes a terminator at the returned byte count, copies the resulting C string into a separate 32-byte destination, and prints it. It uses Arduino’s Serial API on a board. In the host run below, a small stand-in supplies the sample line Hello World so the copy logic is runnable without hardware.

#include <cstddef>
#include <cstring>
#ifndef ARDUINO
#include <iostream>
struct SerialPort {
    void begin(unsigned long) {}
    void setTimeout(unsigned long) {}
    void println(const char* value) { std::cout << value << '\n'; }
    std::size_t readBytesUntil(char delimiter, char* buffer, std::size_t capacity) {
        const char sample[] = "Hello World";
        std::size_t count = 0;
        while (count < capacity && sample[count] != '\0' && sample[count] != delimiter) {
            buffer[count] = sample[count];
            ++count;
        }
        return count;
    }
} Serial;
#endif

const std::size_t INPUT_CAPACITY = 32;
char inputBuffer[INPUT_CAPACITY];
char destination[INPUT_CAPACITY];

void setup() {
    Serial.begin(9600);
    Serial.setTimeout(1000);
    Serial.println("Enter a line:");

    std::size_t bytesRead = Serial.readBytesUntil('\n', inputBuffer, INPUT_CAPACITY - 1);
    inputBuffer[bytesRead] = '\0';
    std::strcpy(destination, inputBuffer);
    Serial.println(destination);
}

void loop() {
    // This one-shot input example runs once in setup().
}

#ifndef ARDUINO
int main() {
    setup();
    return 0;
}
#endif
Enter a line:
Hello World

readBytesUntil() stops when it reads \n, when the 1000 ms timeout expires, or after 31 bytes. The returned size_t count is at most 31, so writing inputBuffer[bytesRead] = '\0' stays within the 32-byte array; the destination has the same capacity and therefore holds the copied bytes and terminator. If a line reaches the 31-byte limit before its newline, the rest of that line may remain available for a later read. A timeout can also return a partial line. The newline delimiter is consumed when found, but a preceding \r is not removed by this code and may appear at the end of the printed string; trim it explicitly if the application needs that behavior.

Choose a Copy Function and Check Buffer Capacity

Before copying, identify whether the value is an Arduino String or a null-terminated character array. For C strings, calculate capacity in bytes, including one byte for \0; for UTF-8 text, character count and byte count can differ. Use strcpy() only when the full source length is known to fit. Use strncpy() only with an explicit plan for termination and padding, or use strlcpy() where the target provides it and check its return value for truncation. For Serial data, cap the read at the input array’s capacity, terminate at the returned byte count, and size every later destination for the resulting string.