Does &s[0] point to contiguous characters in a std::string?
A std::string's allocation is not guaranteed to be contiguous under the C++98/03 standard, but C++11 forces it to be. In practice, neither I nor Herb Sutter know of an implementation that does not use contiguous storage.
Notice that the &s[0]
thing is always guaranteed to work by the C++11 standard, even in the 0-length string case. It would not be guaranteed if you did str.begin()
or &*str.begin()
, but for &s[0]
the standard defines operator[]
as:
Returns:
*(begin() + pos)
ifpos < size()
, otherwise a reference to an object of typeT
with valuecharT()
; the referenced value shall not be modified
Continuing on, data()
is defined as:
Returns: A pointer
p
such thatp + i == &operator[](i)
for eachi
in[0,size()]
.
(notice the square brackets at both ends of the range)
Notice: pre-standardization C++0x did not guarantee &s[0]
to work with zero-length strings (actually, it was explicitly undefined behavior), and an older revision of this answer explained this; this has been fixed in later standard drafts, so the answer has been updated accordingly.
Does std::string need to store its character in a contiguous piece of memory?
The C++11 standard, basic_string 21.4.1.5,
The char-like objects in a basic_string object shall be stored
contiguously. That is, for any basic_string object s, the identity
&*(s.begin() + n) == &*s.begin() + n shall hold for all values of n
such that 0 <= n < s.size().
How to convert a std::string to const char* or char*
If you just want to pass a std::string
to a function that needs const char*
you can use
std::string str;
const char * c = str.c_str();
If you want to get a writable copy, like char *
, you can do that with this:
std::string str;
char * writable = new char[str.size() + 1];
std::copy(str.begin(), str.end(), writable);
writable[str.size()] = '\0'; // don't forget the terminating 0
// don't forget to free the string after finished using it
delete[] writable;
Edit: Notice that the above is not exception safe. If anything between the new
call and the delete
call throws, you will leak memory, as nothing will call delete
for you automatically. There are two immediate ways to solve this.
boost::scoped_array
boost::scoped_array
will delete the memory for you upon going out of scope:
std::string str;
boost::scoped_array<char> writable(new char[str.size() + 1]);
std::copy(str.begin(), str.end(), writable.get());
writable[str.size()] = '\0'; // don't forget the terminating 0
// get the char* using writable.get()
// memory is automatically freed if the smart pointer goes
// out of scope
std::vector
This is the standard way (does not require any external library). You use std::vector
, which completely manages the memory for you.
std::string str;
std::vector<char> writable(str.begin(), str.end());
writable.push_back('\0');
// get the char* using &writable[0] or &*writable.begin()
std::string to char*
It won't automatically convert (thank god). You'll have to use the method c_str()
to get the C string version.
std::string str = "string";
const char *cstr = str.c_str();
Note that it returns a const char *
; you aren't allowed to change the C-style string returned by c_str()
. If you want to process it you'll have to copy it first:
std::string str = "string";
char *cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
// do stuff
delete [] cstr;
Or in modern C++:
std::vector<char> cstr(str.c_str(), str.c_str() + str.size() + 1);
Get all N consecutive characters in string using stringstream in C++
With C++17 you can do it like this, which is way more readable:
void update(std::string_view s, int size) {
const int iterations = s.size() - size;
for (int i = 0; i <= iterations; i++) {
std::cout << s.substr(i, size) << "\n";
}
}
string_view is made exactly for this purpose, for fast read access to a string. string_view::substr is const complexity while string::substr is linear.
As a side note, besides what Nick mentioned, your code has few other small problems:
- std::endl fflushes the stream, it heavily impacts performance. Here you could just use '\n' to make a newline.
- the return at the end is absolutely redundant, void functions do not require returns
- what is the purpose of templating this? This will easily bloat your code without any measurable performance increase. Just pass the N as a parameter.
- also your main is declared as void and should be int (even more so as you do return a value at the end)
how does one securely clear std::string?
Based on the answer given here, I wrote an allocator to securely zero memory.
#include <string>
#include <windows.h>
namespace secure
{
template <class T> class allocator : public std::allocator<T>
{
public:
template<class U> struct rebind { typedef allocator<U> other; };
allocator() throw() {}
allocator(const allocator &) throw() {}
template <class U> allocator(const allocator<U>&) throw() {}
void deallocate(pointer p, size_type num)
{
SecureZeroMemory((void *)p, num);
std::allocator<T>::deallocate(p, num);
}
};
typedef std::basic_string<char, std::char_traits<char>, allocator<char> > string;
}
int main()
{
{
secure::string bar("bar");
secure::string longbar("bDoes "&S[0]" Point to Contiguous Characters in a Std::StringDoes "&S[0]" Point to Contiguous Characters in a Std::StringDoes "&S[0]" Point to Contiguous Characters in a Std::StringDoes "&S[0]" Point to Contiguous Characters in a Std::Stringaaaaar");
}
}
However, it turns out, depending on how std::string
is implemented, it is possible that the allocator isn't even invoked for small values. In my code, for example, the deallocate
doesn't even get called for the string bar
(on Visual Studio).
The answer, then, is that we cannot use std::string to store sensitive data. Of course, we have the option to write a new class that handles the use case, but I was specifically interested in using std::string
as defined.
Thanks everyone for your help!
How to get the real and total length of char * (char array)?
You can't. Not with 100% accuracy, anyway. The pointer has no length/size but its own. All it does is point to a particular place in memory that holds a char. If that char is part of a string, then you can use strlen
to determine what chars follow the one currently being pointed to, but that doesn't mean the array in your case is that big.
Basically:
A pointer is not an array, so it doesn't need to know what the size of the array is. A pointer can point to a single value, so a pointer can exist without there even being an array. It doesn't even care where the memory it points to is situated (Read only, heap or stack... doesn't matter). A pointer doesn't have a length other than itself. A pointer just is...
Consider this:
char beep = '\a';
void alert_user(const char *msg, char *signal); //for some reason
alert_user("Hear my super-awsome noise!", &beep); //passing pointer to single char!
void alert_user(const char *msg, char *signal)
{
printf("%s%c\n", msg, *signal);
}
A pointer can be a single char, as well as the beginning, end or middle of an array...
Think of chars as structs. You sometimes allocate a single struct on the heap. That, too, creates a pointer without an array.
Using only a pointer, to determine how big an array it is pointing to is impossible. The closest you can get to it is using calloc
and counting the number of consecutive \0 chars you can find through the pointer. Of course, that doesn't work once you've assigned/reassigned stuff to that array's keys and it also fails if the memory just outside of the array happens to hold \0
, too. So using this method is unreliable, dangerous and just generally silly. Don't. Do. It.
Another analogy:
Think of a pointer as a road sign, it points to Town X. The sign doesn't know what that town looks like, and it doesn't know or care (or can care) who lives there. It's job is to tell you where to find Town X. It can only tell you how far that town is, but not how big it is. That information is deemed irrelevant for road-signs. That's something that you can only find out by looking at the town itself, not at the road-signs that are pointing you in its direction
So, using a pointer the only thing you can do is:
char a_str[] = "hello";//{h,e,l,l,o,\0}
char *arr_ptr = &a_str[0];
printf("Get length of string -> %d\n", strlen(arr_ptr));
But this, of course, only works if the array/string is \0-terminated.
As an aside:
int length = sizeof(a)/sizeof(char);//sizeof char is guaranteed 1, so sizeof(a) is enough
is actually assigning size_t
(the return type of sizeof
) to an int
, best write:
size_t length = sizeof(a)/sizeof(*a);//best use ptr's type -> good habit
Since size_t
is an unsigned type, if sizeof
returns bigger values, the value of length
might be something you didn't expect...
Related Topics
Copy a File in a Sane, Safe and Efficient Way
Is #Pragma Once a Safe Include Guard
Why Does Modulus Division (%) Only Work With Integers
Multi-Character Constant Warnings
What Is the Correct Way of Using C++11'S Range-Based For
Difference Between an Int and a Long in C++
Why Cast Unused Return Values to Void
Are There Any Valid Use Cases to Use New and Delete, Raw Pointers or C-Style Arrays With Modern C++
Why How to Use Auto on a Private Type
Is (4 ≫ Y ≫ 1) a Valid Statement in C++? How to Evaluate It If So
What Is the Best Open Xml Parser For C++
What Is the Usefulness of 'Enable_Shared_From_This'
C/C++ With Gcc: Statically Add Resource Files to Executable/Library