-4

I'm using some C Leagacy Code within a C++ project.

On used C function looks like this

void Add_To_log(const * const char pString_1, const * const char pString_2, int number);

Now when I call this Functions from C++ Code like this

foo()
{
     Add_To_log("my first string", "my second string", 2);
}

I get a compiler warning ISO C++ Forbids converting string to char. So to get rid of this i thought of creating a c++ wrapper with string_view to avoid unnecessary coping of my strings

void CPP_Wrapper(const string_view& string1, const string_view& string2, int number)
{
    Add_To_log(string1, string2, 2);
}

Now if i understood the reference correctly string_view does not necessarily contain a terminating null character with is essential for all c functions because it does not own the string object. It simply displays it.

However can i assume in my particular case that string1 and string2 are null terminated?

JuliusCaesar
  • 341
  • 3
  • 14
  • did you try std::string::data() or std::string::c_str() first? – Kenny Ostrom May 07 '19 at 21:00
  • 4
    This line (by itself) does not compile: `void Add_To_log(const * const char pString_1, const * const char pString_2, int number);` please read how to post a [mcve] – Richard Critten May 07 '19 at 21:01
  • I think it is dangerous to create an interface that looks like one thing but has hidden requirements. – Galik May 07 '19 at 21:07
  • You are making something up. Assuming the corrected declaration of `Add_To_log`, the code you provided for `foo()` will not trigger any warnings. Definitely nothing like "ISO C++ Forbids converting string to char". Why are you even talking about `string_view`? Aside from missing return type, your `foo()` is perfectly fine and will compile without any diagnostic messages. What is your question about? – AnT stands with Russia May 07 '19 at 21:11
  • Presumably they are passing std::string to a function that takes const char*, and are unaware that std::string has functions to make that easy. (and the C function prototype is clearly wrong, as well) – Kenny Ostrom May 07 '19 at 21:23
  • Presumably, if they are getting "ISO C++ forbids ..." warning, the real C function actually takes non-const `char*` pointers, which string literals can't be assigned to without casting since C++11. – Remy Lebeau May 08 '19 at 03:36

2 Answers2

3

std::string already has functions to provide a pointer to older C library functions

http://www.cplusplus.com/reference/string/string/data/

These provide a non-owning, read only pointer suitable to most C library functions that need read only access during the function call. I'm assuming the std::string has a greater lifetime than the function call, and that the pointer is used only during the function call. Or as the documentation I linked above states, "The pointer returned may be invalidated by further calls to other member functions that modify the object." (including the destructor obviously)

Also, take care to use c_str() in c++98 builds, as data() doesn't guarantee the terminating null until c++11, as noted in the documentaion link and by eerorika.

#include <stdio.h>
#include <string>

extern "C" {
    void legacy_logger(const char * const pstr) {
        printf("%s\n", pstr);
    }
}

int main()
{
    std::string message{ "This is the string." };
    legacy_logger(message.data());
}
Kenny Ostrom
  • 5,639
  • 2
  • 21
  • 30
  • Unless `legacy_logger` stores the pointer for later use. (that is unlikely given the name, but in general case...) – eerorika May 07 '19 at 21:09
  • Good point, I should be explicit about the assumptions, rather than just linking the docs. – Kenny Ostrom May 07 '19 at 21:12
  • 1
    Also, prior to C++11, `string::data` is not guaranteed to be null terminated. `string::c_str` should be used if backwards compatibility needs to be considered. – eerorika May 07 '19 at 21:17
  • That said, if the asker is considering using `std::string_view`, brand new in c++ 17, an unterminated `data` should not be a problem. – user4581301 May 07 '19 at 21:35
3

However can i assume in my particular case that string1 and string2 are null terminated?

No. You should not assume that a string view is null terminated. The wrapper function that you suggest is counter productive, if the C function expects a null-terminated string.


On used C function looks like this

void Add_To_log(const * const char pString_1, const * const char pString_2, int number);

That declaration is ill-formed. If you fix it to be something like:

void Add_To_log(const char * const  pString_1, const char * const pString_2, int number)

then this call is well-formed:

Add_To_log("my first string", "my second string", 2); // No problem
Community
  • 1
  • 1
eerorika
  • 232,697
  • 12
  • 197
  • 326