Skip to content
C++ Better Explained
Go back
C++ Command Line Arguments: How to Use argc and argv
Edit page

C++ Command Line Arguments: How to Use argc and argv

Most beginner C++ programs are self-contained: you run them, they ask for input with cin, and that’s it. But real command line tools work differently — you pass them information when you launch them, like grep "error" log.txt or g++ main.cpp -o app. Those extra words after the program name are command line arguments, and C++ hands them to you through two parameters: argc and argv.

This guide explains exactly how they work, how to read them safely, and how to turn them into numbers and flags you can actually use.

The Two Forms of main()

You’ve probably always written main like this:

int main()
{
    // ...
}

To receive command line arguments, you use the other legal form of main:

int main(int argc, char* argv[])
{
    // ...
}

Both are valid. The second simply asks the runtime to pass in the arguments. The names argc and argv are just convention — the types are what matter — but everyone uses them, so you should too.

What argc and argv Actually Hold

The crucial detail that trips up beginners: argv[0] is the program name, not the first real argument. The arguments the user typed start at argv[1].

So if you run:

./greet Alice 42

You get:

IndexValueWhat it is
argv[0]./greetthe program name/path
argv[1]Alicefirst user argument
argv[2]42second user argument

And argc is 3 — three slots total. That’s why argc is always at least 1.

Printing Every Argument

The simplest useful program just echoes back what it was given. You loop from 0 to argc - 1:

#include <iostream>

int main(int argc, char* argv[])
{
    std::cout << "You passed " << argc - 1 << " argument(s).\n";

    for (int i = 0; i < argc; ++i)
    {
        std::cout << "argv[" << i << "] = " << argv[i] << "\n";
    }

    return 0;
}

Run it as ./program hello world and you’ll see argv[0] (the program name) followed by each argument. Notice we print argc - 1 as the user-supplied count, since the program name doesn’t count as a “real” argument.

If the for loop syntax feels rusty, the C++ loops tutorial is a quick refresher.

Always Validate Before You Read

Here’s the single most important habit with command line arguments: check argc before you touch argv. If you read argv[1] when the user passed nothing, you’re reading memory that doesn’t belong to you — undefined behavior, and a likely crash.

#include <iostream>

int main(int argc, char* argv[])
{
    if (argc < 2)
    {
        std::cerr << "Usage: " << argv[0] << " <name>\n";
        return 1;   // non-zero signals an error
    }

    std::cout << "Hello, " << argv[1] << "!\n";
    return 0;
}

Two good practices are bundled in here: printing a usage message that uses argv[0] (so it shows the real program name), and returning a non-zero exit code to signal failure. Writing errors to std::cerr rather than std::cout is also the conventional choice for diagnostics.

If you're looking to go deeper with C++, the C++ Better Explained Ebook is perfect for you — whether you're a complete beginner or looking to solidify your understanding. Just $19.

Converting Arguments to Numbers

Every argument arrives as text, even if it looks like a number. argv[1] being "42" is the three-character string, not the integer 42. To do math, you must convert.

The modern, safe tool is std::stoi (string to int). It throws an exception if the text isn’t a valid number, so you can catch bad input instead of getting silent garbage:

#include <iostream>
#include <string>

int main(int argc, char* argv[])
{
    if (argc < 3)
    {
        std::cerr << "Usage: " << argv[0] << " <a> <b>\n";
        return 1;
    }

    try
    {
        int a = std::stoi(argv[1]);
        int b = std::stoi(argv[2]);
        std::cout << a << " + " << b << " = " << a + b << "\n";
    }
    catch (const std::exception& e)
    {
        std::cerr << "Both arguments must be whole numbers.\n";
        return 1;
    }

    return 0;
}

For decimals, use std::stod (string to double) the same way. There’s a full breakdown of the conversion options — including stoi, atoi, and stringstream, and why stoi is usually best — in the C++ string to int conversion guide.

Handling Flags and Options

Real tools accept flags like -v or --help. Since each argument is just a string, you compare it against the options you support. The cleanest way is to wrap each argv[i] in a std::string so you can use ==:

#include <iostream>
#include <string>

int main(int argc, char* argv[])
{
    bool verbose = false;
    std::string filename;

    for (int i = 1; i < argc; ++i)
    {
        std::string arg = argv[i];

        if (arg == "-v" || arg == "--verbose")
        {
            verbose = true;
        }
        else if (arg == "-h" || arg == "--help")
        {
            std::cout << "Usage: " << argv[0] << " [-v] <file>\n";
            return 0;
        }
        else
        {
            filename = arg;   // anything else is treated as the file
        }
    }

    if (verbose) std::cout << "Verbose mode on.\n";
    std::cout << "File: " << filename << "\n";
    return 0;
}

Why convert to std::string? Because comparing raw char* with == compares pointers, not text. Wrapping in std::string gives you real content comparison — a classic beginner trap. If strings in general feel shaky, see the C++ string handling guide.

A Common Pattern: Collect Arguments into a Vector

For anything beyond a couple of flags, it’s tidy to copy the arguments into a std::vector<std::string> once, then work with that:

#include <iostream>
#include <string>
#include <vector>

int main(int argc, char* argv[])
{
    std::vector<std::string> args(argv + 1, argv + argc);  // skip argv[0]

    for (const std::string& arg : args)
    {
        std::cout << "Got: " << arg << "\n";
    }

    return 0;
}

The line std::vector<std::string> args(argv + 1, argv + argc) builds the vector from the range starting just after the program name to the end — a neat one-liner that skips argv[0] automatically. From there you have all of std::vector’s conveniences. New to vectors? The C++ vector tutorial covers them from scratch.

How to Pass Arguments When Running Your Program

How you supply arguments depends on how you run the program:

If you haven’t set up a compiler or IDE yet, start with the C++ setup guide.

Common Mistakes to Avoid

Summary

Command line arguments let your C++ programs take input at launch through main(int argc, char* argv[]). Remember the essentials: argc counts the arguments (program name included), argv holds them as text, argv[0] is the program name, and real input starts at argv[1]. Always check argc before reading, convert text to numbers with std::stoi/std::stod, and compare flags using std::string. With those habits, you can build proper command line tools instead of programs that only talk through cin.

Want every C++ concept explained this clearly, in order, from the ground up?

👉 Get the C++ Better Explained Ebook — $19

📋

Free Download: The 10 Mistakes Every C++ Beginner Makes

A free 1-page checklist that shows the exact traps that slow down every C++ beginner — so you can avoid them from day one.

🔒 No spam. Unsubscribe anytime.


Edit page
Share this post on:

Previous Post
Orthogonality in Programming: Why Independent Code Wins
Next Post
How Long Does It Take to Learn C++? An Honest Timeline