views:

123

answers:

2

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.

A: 

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.

Mark B
+1  A: 

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.

Steve Jessop