Convert std::string to char* debate [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
In C++ 98, is this a legitimate method to cast from a string to a char *?
char * n = (char *) someString.c_str();
(In my original wording, the function above was recommended by a senior programmer)
Namely, is it a better method than:
s2 = (char *)alloca(s0.size() + 1);
memcpy(s2, s0.c_str(), s0.size() + 1);
(courtesy of convert string to char*)
If so, why?
Use Case:
I need to use a char*, but I don't need to alter the data after it is in the char*. I'm passing it to a display library.
I'm just looking for a short and sweet answer. Thanks!
Edit: I changed the wording to this question because it got down voted. I hope my rewording makes it a better question. I think the answers were interesting and insightful.
For the record: Anyone interested in this question, should look at all the responses. I could only pick one, but I found them all interesting.

string::c_str() returns a const pointer to a null-terminated C-style string that contains the same contents as the original string. In most common implementations, c_str() simply returns a pointer to the string's internal data if it is not empty, but that is not required by the C++ standard.
If you just need to read the content of the string and not modify it, there is no need to allocate a separate buffer, just use c_str() by itself. The returned char* will remain valid as long as the string is not altered, either by the =/+=/[] operator, or the insert() or erase() method, or an iterator, etc.
If you need to modify the string via the char* pointer, then you have to allocate a separate buffer, copy the string content into it, modify it as needed, and then copy the new content back to the string using its own methods.

Your senior programmer is wrong. Casting away const-ness like that at the very least is wrong (no guarantees that it points to the actual memory of the string for example), and yields undefined behavior if the underlying objects happen to be const.

The answer here depends on whether you need a mutable string or just to be able to read it.
If all you want to do with your char* is to look at the contents then, as the comments have pointed out, you need to assign it to a const char* (and drop the cast).
Your method works, but if all you need to do is read the string, there is no point in copying it to a new location.
If you need to modify the string, then your copy would be appropriate. However, you need to be aware that changes will not be reflected in the original string.

First off, memcpy does not allocate memory. It only copies things from one place to another.
In C++ the idiom, using memcpy is:
std::string my_string = "California Needs Rain!\n";
char * p_text_string = new char [my_string.length() + 1U];
memcpy(p_text_string,
my_string.c_str(),
my_string.length());
// Add the nul terminator
p_text_string[my_string.length()] = '\0';
Remember that the memory allocated needs to be 1 more than the length of the string because of the nul, '\0', terminator character that needs to be appended.
The std::string is not required to be nul terminated.

Related

Modifying string literals for recursive function [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I've got a recursive function that is supposed to check if a given word is a palindrome, which works by comparing the first and last value, then strips them off and passes them recursively into checkPalindrome, but whenever I try to assign word[size-1] to '\0', I get a Bus Error.
Here is my code:
bool checkPalindrome(char word[]){
int size = std::strlen(word);
//Parts removed...
word[size-1]='\0'; //This is the line causing the issue
return checkPalindrome(word+1);
}
}
Here is an example of a call to this function:
checkPalindrome("racecar");
Thank you!
There are two ways I can think of to solve this problem:
The obvious one would be to use a std::string instead of a string literal and just .pop_back() (C++11) to remove the last character.
The second would be to pass the length of the string to the function as a parameter, instead of computing it. Then, just decrease the length by 1 so now you have a new "fake end point" to the string. Since you're using this number to check the last character, you don't really need to actually modify the string, just change where the "last" character is.
But since you're using C++, I don't see why not use std::string and avoid overcomplicating the problem.
So as stated in the comments you can't modify a string literal.
So before passing it to the function, make a copy of it.
std::size_t len = std::strlen(word);
char* copy = new char[len + 1];
std::strncpy ( copy, word, len + 1 );
isPalindromeR(copy);
delete[] copy;
other solution would be to not use recursion, thus not needing to modify the string.
anyway outside of assignments use a std::string

better approach to copy portion of char array than strncpy

I used std::strncpy in c++98 to copy portion of a char array to another char array. It seems that it requires to manually add the ending character '\0', in order to properly terminate the string.
As below, if not explicitly appending '\0' to num1, the char array may have other characters in the later portion.
char buffer[] = "tag1=123456789!!!tag2=111222333!!!10=240";
char num1[10];
std::strncpy(num1, buffer+5, 9);
num1[9] = '\0';
Is there better approach than this? I'd like to have a one-step operation to reach this goal.
Yes, working with "strings" in C was rather verbose, wasn't it!
Fortunately, C++ is not so limited:
const char* in = "tag1=123456789!!!tag2=111222333!!!10=240";
std::string num1{in+5, in+15};
If you can't use a std::string, or don't want to, then simply wrap the logic you have described into a function, and call that function.
As below, if not explicitly appending '\0' to num1, the char array may have other characters in the later portion.
Not quite correct. There is no "later portion". The "later portion" you thought you observed was other parts of memory that you had no right to view. By failing to null-terminate your would-be C-string, your program has undefined behaviour and the computer could have done anything, like travelling back in time and murdering my great-great-grandmother. Thanks a lot, pal!
It's worth noting, then, that because it's C library functions doing that out-of-bounds memory access, if you hadn't used those library functions in that way then you didn't need to null-terminate num1. Only if you want to treat it as a C-style string later is that required. If you just consider it to be an array of 10 bytes, then everything is still fine.

Am I right that &str[0] points to the buffer which is len + 1 size, including null terminating character [duplicate]

This question already has answers here:
Legal to overwrite std::string's null terminator?
(4 answers)
Closed 5 years ago.
Is it ok to do the following?
auto len = GetWindowTextLengthA(min_area_edit_hwnd);
std::string buffer(len, '\0');
GetWindowTextA(min_area_edit_hwnd, &buffer[0], len + 1);
I mean, is it ok to tell the GetWindowTextA function that &buffer[0] points to the buffer with len + 1 size? Is it correct or should I create string in the following way
std::string buffer(len + 1, '\0');
?
This is generally legal starting from C++11, but you do indeed have to reserve an extra character for the null terminator.
Before C++11 such uses of std::string were illegal. However, note that buffer.length() will not automatically update just because GetWindowTextA placed a \0 somewhere in the middle of its controlled sequence. If you want C-length of the string to be consistent with buffer.length(), it is your responsibility to resize() your buffer accordingly.
I'd tend to err on the side of caution myself:
char cbuffer[MAX_LEN_OF_SOME_DESCRIPTION];
GetWindowTextA(..., cbuffer, ...);
cbuffer[len] = '\0';
std::string buffer(cbuffer); // assuming you actually NEED a C++ string.
This method will work without having to parse the rather voluminous C++ standards documents to find out whether writing directly into a string object is legal :-)
The GetWindowTextA function will write into the provided buffer. In C++11 and C++14, it is undefined behaviour to write out of bounds of the string content of a std::string, even if you're writing a null terminator over the null terminator.
You will need to size the string to len + 1 before making the call, and then resize the string again afterwards, based on the return value.
From the standpoint of the standard, the following is guaranteed:
std::basic_string is a contiguous container
operator[](std::size_t) will not invalidate iterators
It is legal to read any element in the range [0, size()] and you may modify any such element except the one returned by operator[](size())
I would therefore conclude, that it is perfectly fine to do as long as the function does not eagerly write a null terminator (i.e. checks if it already ends with '\0' which it always will and then does nothing). Also, I have only heard of one instance of a string being implemented such that this would actively lead to real trouble, that is the implementation at Facebook.
Personally, I would go with the safer route and set the size to be a byte longer if you can not strictly control the access, so I would not pass a size of len + 1 .
Edit: from a comment under another answer, not correctly handling the (possibly not allocated) null terminator can result in real failures, see CppCon 2016: Nicholas Ormrod “The strange details of std::string at Facebook"
According to the Standard, this is not safe. The Standard goes to some considerable effort to explicitly state that writing to the NUL terminator is undefined behavior:
and
Slightly more difficult to analyze is whether &buffer[0] points to size() + 1 consecutive characters to begin with. The Standard does not make this guarantee explicitly, and in fact the wording of operator[] quoted above seems to leave the door open to having a buffer of only size() consecutive characters, with the terminator stored separately. However when all the semantic rules are considered, the string must actually have room for size() + 1 characters at all times. (Otherwise a call to c_str(), which is a const member function, could not return a pointer to a run of size()+1 characters without invalidating references, which it is not allowed to do. A second proof, also valid, is that c_str() cannot copy the content to a new location and still meet the complexity requirement).
However, it is not assured that the character at location size() + &buffer[0] is actually a NUL until c_str() or data() is called (at which point &buffer[size()] begins returning a reference to it instead of an alternate location).
&(buffer[0]) has a type char*, and probably points to the text of length len, but even this is not guaranteed. You should use char buffer[len+1]; instead.

How do I find the memory address of a string?

I am having a mental block and I know I should know this but I need a little help.
If I declare a string variable like this:
string word = "Hello";
How do I find the memory address of "Hello"?
Edit: This is what I am trying to do...
Write a function that takes one argument, the address of a string, and prints that string once. (Note: you will need to use a pointer to complete this part.)
However, if a second argument, type int, is provided and is nonzero, the function should print the string a number of times equal to the number of times that function has been called at that point. (Note that the number of times the string is printed is not equal to the value of the second argument; it is equal to the number of times the function has been called so far.)
Use either:
std::string::data() if your data isn't null-terminated c-string like.
or
std::string::c_str() if you want the data and be guaranteed to get the null-termination.
Note that the pointer returned by either of these calls doesn't have to be the underlying data the std::string object is manipulating.
Take the address of the first character is the usual way to do it. &word[0]. However, needing to do this if you're not operating with legacy code is usually a sign that you're doing something wrong.
I guess you want a pointer to a plain old C-string? Then use word.c_str(). Note that this is not guaranteed to point to the internal storage of the string, it's just a (constant) C-string version you can work with.
You can use the c_str() function to get a pointer to the C string (const char *); however note that the pointer is invalidated whenever you modify the string; you have to invoke c_str() again as the old string may have been deallocated.
OK, so, I know this question is old but I feel like the obvious answer here is actually:
std::string your_string{"Hello"};
//Take the address of the beginning
auto start_address = &(*your_string.begin())
//Take the address at the end
auto end_address = &(*your_string.end())
In essence this will accomplish the same thing as using:
auto start_address = your_string.c_str();
auto end_address = your_string.c_str() + strlen(your_string.c_str());
However I would prefer the first approach (taking the address of the dereferenced iterator) because:
a) Guaranteed to work with begin/end compatible containers which might not have the c_str method. So for example, if you decided you wanted a QString (the string QT uses) or AWS::String or std::vector to hold your characters, the c_str() approach wouldn't work but the one above would.
b) Possibly not as costly as c_str()... which generally speaking should be implemented similarly to the call I made in the second line of code to get the address but isn't guaranteed to be implemented that way (E.g. if the string you are using is not null terminated it might require the reallocation and mutation of your whole string in order to add the null terminator... which will suddenly make it thread unsafe and very costly, this is not the case for std::string but might be for other types of strings)
c) It communicates intent better, in the end what you want is an address and the first bunch of code expresses exactly that.
So I'd say this approach is better for:
Clarity, compatibility and efficiency.
Edit:
Note that with either approach, if you change your initial string after taking the address the address will be invalidated (since the string might be rellocated). The compiler will not warn you against this and it could cause some very nasty bugs :/
Declare a pointer to the variable and then view it how you would.

Simple General Questions about C++ [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Ive moved from autoit and am now learning C++ and some problems keep coming up.
The first one is storing character input. The problem is that I have no idea how many characters are in that line of the file (if you are reading a file) or how many letters a user is going to type (in a console application).
What is the best way to approach this problem?? I have heard about the string class, but I want to avoid it becuase I dont know how it works and that leads to vunerabilities etc.
Secondly...
In C you can load shellcode into memory, create a function pointer, and execute that code.
Is there any mechanism for this in C++???
Thirdly...
How does the interpreter iterate through char arrays for string output??? (char array[3];) Does the compiler keep track of the size of the array, or does it just keep reading from memory until it hits that \0 thing???
Lastly...
If Char * are just pointers to data in memory, then why does:
char * title = "Program Title";
this work??? where is the string literal stored in memory?? how is it referenced???
Thankyou very much. I greatly appreciate your help.
-Hyperzap
Investing your time in learning std::string is well worth the effort, as it takes care of a lot of hassle for you. If you don't want to take advantage of the features in C++, then why use C++ and not just C?
You can use the same code for this as you would in C.
Yes, iostream-output of C-style strings outputs until terminating zero. Once again, if you use std::string you do not have to care about such details.
Correct me if I'm wrong, but I think title would be a const char[] stored on the stack.
Example:
const char* hello = "Hello\0World";
cout << hello; // Prints only "Hello", i.e. up to terminating zero (\0)
The reason this works:
const char* hello = "Hello world";
cout << hello;
is because hello is really "Hello world\0"; - in other words, the compiler inserts a terminating zero.
Note that std::string doesn't do any magic. It too reads until the terminating zero:
string hello = "Hello\0World\n";
cout << hello; // Still only gives "Hello"
char* title = "String Literal" works because the compiler preallocates a memory location to store your string literal, thus you then get back a pointer to this memory location.
In c++, an array for which you know the size at compile time (as in your example: char array[3] is a type in itself, so the compiler does keep track of the size. However, if you do not know the size (ie. char array[]), it is just a pointer to char. However, you should be using std::vector in c++ (better safety and performance).
I'm not too sure about your other two questions (didn't quite understand them)