char[] vs std::string: what a C string actually is

Short answer: a C-style string is just a char array with one extra byte at the end holding '\0'. That single convention is why strlen exists, why strcpy can overflow, and why std::string was invented.

The whole story in one picture

char s[6] = "hi";     // 6 slots, but only 3 are meaningful

index:   0     1     2     3     4     5
       +-----+-----+-----+-----+-----+-----+
value: | 'h' | 'i' | '\0'|  ?  |  ?  |  ?  |
       +-----+-----+-----+-----+-----+-----+
                      ^
                      the terminator: how every C function knows where text ends

The last three slots are uninitialized garbage; the string ends where '\0' says it does. Nothing stores a length.

Creating and printing

#include <iostream>
using namespace std;

int main() {
    char s[20] = "hi";
    s[0] = 'H';                 // index into it like any array
    cout << s << endl;          // Hi

    char empty[20];             // uninitialized: no terminator yet!
    empty[0] = 'o';
    empty[1] = 'k';
    empty[2] = '\0';            // now it is a valid string
    cout << empty << endl;
    return 0;
}

Forgetting the terminator is the number-one C-string bug: printing an array without one walks past your data until it happens to hit a zero byte.

strlen, strcpy — and why they exist

#include <iostream>
#include <cstring>
using namespace std;

int main() {
    char src[20] = "copy me";
    char dst[20];

    strcpy(dst, src);                       // copy, including the '\0'
    cout << dst << endl;
    cout << "length = " << strlen(dst) << endl;  // 7, terminator not counted

    cout << "sizeof dst = " << sizeof(dst) << endl; // 20: array size, not text length
    return 0;
}

The pair strlen (7) and sizeof (20) is a favorite interview trap: one measures text, the other the box.

Why strcpy is dangerous

char small[5];
char big[] = "this is much longer than five";
strcpy(small, big);   // writes past the end — undefined behavior

strcpy copies until it sees '\0' and does not know your array's size. That is a buffer overflow, and it is how a huge share of security bugs were born. The guarded version is strncpy (or better: don't use C strings).

What std::string changes

#include <string>

std::string s = "hi";
s[0] = 'H';              // still indexable
s += " there";           // grows — no size to manage
std::cout << s.size();   // always knows its own length
std::cout << s.substr(0, 2);   // operations instead of convention

std::string owns its memory, grows automatically, and carries its length. No terminator to forget, no overflow from a fixed buffer, no strlen call to find the end.

Side-by-side

char[] (C string)std::string
Lengthfound by scanning for '\0'stored, .size()
Sizefixed at declarationgrows and shrinks
Copystrcpy (can overflow)= (safe)
Concatenatestrcat (can overflow)+=
Comparestrcmp (not ==)== works
Read a linecin.getline(s, n)getline(cin, s)

The trap that bites beginners

#include <iostream>
using namespace std;

int main() {
    char a[10] = "abc";
    char b[10] = "abc";

    // This compares *addresses*, not text. Always false (or worse)!
    cout << "a == b ? " << (a == b) << endl;

    // Character-by-character comparison is what you actually mean:
    bool same = true;
    for (int i = 0; a[i] != '\0' || b[i] != '\0'; i++) {
        if (a[i] != b[i]) { same = false; break; }
    }
    cout << "same text? " << same << endl;
    return 0;
}

With std::string, a == b does the right thing. With arrays, == compares the array's address to itself — almost always the wrong question.

Reading input with spaces

#include <iostream>
using namespace std;

int main() {
    char line[50];
    cin.getline(line, 50);      // whole line, spaces included
    cout << "[" << line << "]" << endl;
    return 0;
}

Remember cin >> s stops at the first space. getline takes the rest of the line — and beware the leftover newline if you mixed the two (see cin vs getline).

Which should you use?

Practice it

Related: data types (why char is a small number), cin vs getline, vector vs array.