Note sure about the "best" solution, but here's how I'd do it in C++:

    #include <string>
    #include <iostream>
    
    using namespace std;
    
    bool is_palindrome(const string &inputString)
    {
        for(int i = 0, j = inputString.size() - 1; i < j; i++, j--)
            if (inputString[i] != inputString[j]) return false;
        return true;
    }
    
    int main(int argc, char *argv[])
    {
        if (argc != 2) cout << "Usage: " << argv[0] << " <string>" << endl;
        else cout << "The string '" << argv[1] << "' is "
                    << (is_palindrome(argv[1]) ? "" : "not ")
                    << "a palindrome." << endl;
        return 0;
    }

But since you mentioned close-to-the-metal, I endeavored to do it in C instead:

    #include <stdio.h>
    #include <string.h>
    
    int is_palindrome(const char *inputString)
    {
        int i, j;
    
        if (inputString)
            for(i = 0, j = strlen(inputString) - 1; i < j; i++, j--)
                if (inputString[i] != inputString[j]) return 0;
        return 1;
    }
    
    int main(int argc, char *argv[])
    {
        if (argc != 2) printf("Usage: %s <string>\n", argv[0]);
        else printf("The string '%s' is %sa palindrome.\n",
                    argv[1], (is_palindrome(argv[1]) ? "" : "not "));
        return 0;
    }

Note that in both cases, the loop conditional in `is_palindrome` also ensures that the empty string qualifies as a palindrome, without improperly attempting to access a character at index `-1`.