简体   繁体   中英

How does a function detect string pointer vs string literal argument?

I have encountered a function, such that it can differentiate between being called as

foo("bar");

vs

const char *bob = "bar";
foo(bob);

Possibilities I have thought of are:

  • Address of string: both arguments sat in .rdata section of the image. If I do both calls in the same program, both calls receive the same string address.
  • RTTI: no idea how RTTI can be used to detect such differences.

The only working example I could conjure up is:

void foo(char *msg)
{
    printf("string literal");
}

void foo(const char *&msg)
{
    printf("string pointer");
}

foo("bar");                 // "string literal"

const char *soap = "bar";
foo(soap);                  // "string pointer"

I do not have access to the function's code, and the declarations in the header file only revealed one function declaration.

Here's another way to distinguish between a string literal and a pointer, based on the fact that string literals have array type, not pointer type:

#include <iostream>

void foo(char *msg)
{
    std::cout << "non-const char*\n";
}

void foo(const char *&msg) // & needed, else this is preferred to the
                           // template function for a string literal
{
    std::cout << "const char*\n";
}

template <int N>
void foo(const char (&msg)[N])
{
    std::cout << "const char array reference ["<< N << "]\n";
}

int main() {
    foo("bar"); // const char array reference [4]
}

But note that all of them (including your original function) can be "fooled" by passing something that isn't a string literal:

const char *soap = 0;
foo(soap);

char *b = 0;
foo(b);

const char a[4] = {};
foo(a);

There is no type in C++ which is unique to string literals. So, you can use the type to tell the difference between an array and a pointer, but not to tell the difference between a string literal and another array. RTTI is no use, because RTTI exists only for classes with at least one virtual member function. Anything else is implementation-dependent: there is no guarantee in the standard that string literals will occupy any particular region of memory, or that the same string literal used twice in a program (or even in a compilation unit) will have the same address. In terms of storage location, anything that an implementation can do with string literals, it is permitted also to do with my array a .

The function foo() in theory could use a macro to determine if the argument was a literal or not.

#define foo(X) (*#X == '"'
                ? foo_string_literal(X)
                : foo_not_string_literal(X))

And what happens if you call it as:

const char bob[] = "bar";
foo(bob);

It's probably using some sort of distinction like that to make the determination.

EDIT: If there's only one function declaration in the header I can't conceive of any portable way the library could make that distinction.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM