I was wondering out of curiosity if it is possible to cast a std::vector<> to a double pointer.
I've never had an issue passing a std::vector as a pointer in this fashion:
std::vector<char> myCharVector;
myCharVector.push_back('a');
myCharVector.push_back('b');
myCharVector.push_back('c');
char *myCharPointer = &myCharVector[0];
So I was curious if it was possible to assign the address of the pointer in a similar way to this:
char *myPointer = "abc";
char **myDoublePointer = &myPointer;
I've tried:
char **myDoublePointer = (char**)&myCharVector;
But it doesn't work. Is there any way of achieving this?
You already know that &myCharVector[0] is a pointer to char. So if you store it in a variable:
char *cstr = &myCharVector[0];
then you can take the address of that variable:
char **ptrToCstr = &cstr;
But simply dereferencing twice like this:
char **ptrToCstr = &(&myCharVector[0])
is invalid because the value (&myCharVector[0]) isn't stored in memory anywhere yet.
In C++11, you can do:
char *myCharPointer = myCharVector.data();
But you cannot take the address of the return value of data() because it does not return a reference to the underlying storage, just the pointer value.
If the purpose is to be able to change what the pointer is pointing to, then you may really want a pointer to a vector, rather than a pointer to a pointer to a char. But, the STL doesn't let you change the underlying pointer within the vector itself without going through the regular vector APIs (like resize or swap).
You most definitely can't do this. std::vector and a char ** are completely different types of objects and you can't just "cast" one to another.
The reason you were able to do char *myCharPointer = &myCharVector[0] is that myCharVector[0] gives you a char, and thus &myCharVector[0] gives you the address of that char, which you can assign to a char *.
The only way you could convert a full std::vector into a char * (not char **) is to loop over your std::vector and construct a char * from the data manually.
For instance something like:
char *ptr = malloc(myCharVector.size()+1);
for (unsigned int i=0; i < myCharVector.size(); i++) {
ptr[i] = myCharVector[i];
}
ptr[myCharVector.size()] = 0;
Then ptr will be a C string of chars.
Related
So I am trying to avoid using strings for this. I am basically trying to make a string array.
char **hourtimes = (char**)malloc(100 * sizeof(char*));
for (int i = 0; i < 100; i++) {
(*hourtimes) = (char*)malloc((100 * sizeof(char)));
}
So I made a string array basically here
Now, I want to make hourtimes[0] = "twelve";
I tried doing *hourtimes = "twelve";
but I get the same error, I think this works in c, but I'm using c++
hourtimes[0][0] = 't';
hourtimes[0][1] = 'w';
etc works just fine but that would be too cumbersome
*hourtimes = "twelve" is setting *hourtimes to point to an immutable string literal. You are then trying to modify that immutable string. What you want to do is copy "twelve" into *hourtimes.
strcpy(hourtimes[0],"twelve");
Note: This answer was written at a time when the question was tagged for C. C++ will have different preferred ways of doing this kind of thing.
The error message tells you exactly what's wrong: You can't assign a const char * to a char *. What does that mean, though?
Both const char * and char * are types. They are, in fact, very nearly the same type; one is a pointer to a character, and the other is a pointer to a constant character. That means that the latter can't be changed1; that's, after all, what "constant" means. So when you try to tell the compiler to treat a pointer to a constant type as a pointer to a non-const type, it'll give you an error -- because otherwise it'd have no way to guarantee that the string isn't modified.
"whatever" is always a const char *, not a char *, because that's stored in memory that's generally not meant to be modified, and the compiler can make some really neat optimizations if it can safely assume that it's unchanged (which, because it's const, it can).
I won't tell you how to "properly" write the code you're going for, because if you're using C++, you should be using std::vector and std::string instead of anything with pointers whenever possible, and that probably includes here. If, for whatever reason, you need to use pointers, the comments have covered that well enough.
1: Okay, yes, it can -- but that's outside the scope of this answer, and I don't want to confuse any beginners.
In your allocation loop, (*hourtimes) is the same as hourtimes[0], so you are assigning your allocated sub-arrays to the same slot in the main array on each loop iteration, causing memory leaks and uninitialized slots. You need to use hourtimes[i] instead:
char **hourtimes = (char**)malloc(100 * sizeof(char*));
for (int i = 0; i < 100; i++) {
hourtimes[i] = (char*)malloc(100 * sizeof(char));
}
And don't forget to deallocate the arrays when you are done with them:
for (int i = 0; i < 100; i++) {
free(hourtimes[i]);
}
free(hourtimes);
Now, a string literal has type const char[N], where N is the number of characters in the literal, + 1 for the null terminator. So "twelve" would be a const char[7].
Your arrays only allow char* pointers to be stored, but a const char[N] decays into a const char* pointer to the first char. You can't assign a const char* to a char*, thus the compiler error.
Even if it were possible to do (which it is, but only with a type-cast), you shouldn't do it, because doing so would cause a memory leak as you would lose your original pointer to the allocated array, and worse free() can't deallocate a string literal anyway.
What you really want to do is copy the content of the string literal into the allocated array storage. You can use strncpy() for that:
strncpy(hourtimes[0], "twelve", 100);
Now, with all of that said, this is the C way of handling arrays of strings. The C++ way is to use std::vector and std::string instead:
#include <string>
#include <vector>
std::vector<std::string> hourtimes(100);
...
hourtimes[0] = "twelve";
This is a string literal, which can be used as a pointer to a constant char, but not as a pointer to a non-const char.
"twelve"
You do however attempt to assign it to a pointer to non-const char.
hourtimes[0] = "twelve";
That is what the compiler does not like.
I have a number that I need to convert to a const char * (an API I'm using them requires const char * as input to many of its functions). The following works:
int num = 5;
std::string s = std::to_string(5);
const char * p = s.c_str();
as suggested by answers like those in how to convert from int to char*?, but it involves creating the seemingly unnecessary variable s, so I tried the following, but it doesn't work (p points to an empty string afterwards):
int num = 5;
const char * p = std::to_string(num).c_str();
Is there a clean way I can accomplish this? Why doesn't the second example work? The behavior is very similar to what happens if I made this obvious mistake:
const char * p;
{
std::string tempStr( "hi" );
p = tempStr.c_str( );
// p points to "hi" string.
}
// now p points to "" string.
Which makes me suspect that the issue std::to_string(num) immediately goes out of scope or something similar because it's not used to directly initialize anything.
std::string encapsulates managing dynamic memory (created with new[] and delete[]). Let's break it down.
const char * p = std::to_string(num).c_str();
Create a std::string (with a human-readable representation of num).
Get the new[]ly allocated const char* to the string.
Assign that value to p.
Destroy the std::string → delete[] the allocated const char*.
p points to... deallocated data
If you are using a pointer, the data that the pointer points to must exist throughout the lifetime of that pointer.
So, no, there is no way around this other than new[]ing a copy of the string, which you will have to explicitly delete[] later. And at that point, you've thrown the baby out with the bath and have no need to use std::string.
Create a string that lives at least as long as you want to refer to its internal data.
Just use std::string it does everything you want and everything that you would have to do manually if you don't use it.
When you need to pass a const char* to a const char* function simply use std::string::c_str() like this:
some_api_function(mystring.c_str()); // passes a const char*
What you need is a function which returns a char* which holds your value and can be used to manage its lifetime. The problematic version is broken because the char* points to memory which it does not manage.
For example:
std::unique_ptr<char[]> str(int32_t x)
{
std::unique_ptr<char[]> res(new char[12]);
snprintf(res.get(), 12, "%d", x);
return res;
}
Usestd::string everywhere and don't use const char* when not nessecary. They are basically the same thing. I use const char* only when I'm using a file-path.
Use std::string everywhere and your program should work.
I was working with the strcmp function in C, then i saw the function as arguments gets:
strcmp(_const char *s1, const char *s2)_;
And actually i passed normal char array and it worked. Any ideas why this happening?
If you have for example the following code
char c = 'A';
char *p = &c;
const char *cp = &c;
then it means that you can change variable c using pointer p but you may not change it using pointer cp
For example
*p = 'B'; // valid assignment
*cp = 'B'; // compilation error
Thus function declaration
int strcmp(const char *s1, const char *s2);
means that inside the function the strings pointed to by s1 and s2 will not be changed.
There are two ways to use const key word to a pointer:
int my_int = 3;
const int* pt = &my_int; //prevent to modify the value that pointer pt points to
int* const ps = &my_int; //prevent to modify the value of pointer ps:
//it means the pointer is a const pointer, you can't modify the value of the pointer
//The value of the pointer ps is a memory address, so you can't change the memory address
//It means you can't reallocate the pointer(point the pointer to another variable)
int new_int = 5;
*pt = &new_int; //valid
*pt = 10; //invalid
*ps = &new_int; //invalid
*ps = 10; //valid
In strcmp function, the two arguments are pointer points to a const value, it means when you pass two char arrays or char pointers to the strcmp function, the function can use the value of those two pointers point to, but the function can't modify the value that you pass to it. That's why it works.
The const reference works in a similar way.
This worked, because passing non-const in place of const is allowed. It is the other way around that is prohibited:
char *hello = new char[20];
char *world= new char[20];
strcpy(hello, "hello");
strcpy(world, "world");
if (!strcmp(hello, world)) {
...
}
The const in the declaration is meant to tell the users of the API that the function will not modify the content of the string. In C++ this is important, because string literals are const. Without the const in the API, this call would have been prohibited:
if (!strcmp(someString, "expected")) { // <<== This would not compile without const
...
}
I think you intend to ask the mechanism of how the variable can compare the array.
if that's the case,
The pointer that has been declared in your example stores the initial address of the array's first element and
the ending point of the string can be determined by the detection null character that which in turn is the ending address of the array.
With that said the strcmp when called the pointer points to the strings or the character passed that is, the command would be assumed as follows strcmp("string1","string2");
and thus the comparison takes place as usual.
hmm i guess by this and with other examples posted around you can get a better picture for your answer.
how can i use the windows api without working with char and char * arrays. I want to work only with strings.
second question
char * nextdir(char * cstr) {
string mystring(cstr);
mystring.erase(mystring.find("*.*\\"),4);
mystring.append("\\*.*");
char nextdiir[MAX_PATH]="0";
strncpy( nextdiir, mystring.c_str(), sizeof( mystring ) );
cout<<"NEXTDIIR function="<<nextdiir<<endl;
return nextdiir; //}
the next dir is an array! how can i return it from function?
what happen if i cast it to char * array?
My problem is that other function that uses the nextdir returned value is working strange!
void recursive(char * searchdir){
cout<<"searchdir="<<searchdir<<endl;}
when im doing
recursive(nextdiir(foo)); //now the data printed is not the same but garbage! not like the data printed in call to nextdiir function!!
so i get for example
NEXTDIIR function=c:\windows\*.*
searchdir=garbage
//garbage is unknown characters!
how to fix it?
another questions!!
1)is it because i casted char array name to char * ?
2)how to use windows api without this char and char * mess . only work with strings?
3)what is the difference between char array and char *? the char array name is also constant pointer to the first element then what is the difference???
4)how to return char array from function in c ? in c++?
5)what is the differnce between char * and const char * ? they both the same cuz the value being pointed is unchangeable!
Please help
You are returning a pointer to local variable nextdiir. When the function returns, that variable ceases to exist, leaving you with a dangling pointer. De-referencing it is undefined behaviour.
Why not return an std::string? Then use the std::string::c_str() method to get a const char* pointer to its underlying data.
std::string nextdir(const char * cstr) {
string mystring(cstr);
// do your stuff
return mystring;
}
lots of questions...
how can i use the windows api without working with char and char * arrays. I want to work only with strings.
that will be hard, Win Api requires for some functions a pointer to char* array, you might use here std::vector<char> vec(REQUIRED_SIZE); pass &vec[0] to your api function, and assign &vec[0] to your std::string to get results into std::string.
Second question
char nextdiir[MAX_PATH]="0";
is local to your function, so you are not allowd to return its pointer (it will be UB). You can as above first create std::vector<char> and modify it as you want, and return result as a std::string(&vec[0]).
another questions!!
1)is it because i casted char array name to char * ?
not sure where is that cast, but you had a UB as stated above.
2)how to use windows api without this char and char * mess .
MFC CString allows you to access internal buffer using GetBuffer(0) or GetBufferSetLength(100). std::string does not allow you to safely modify internal buffer, thats why its best to use std::vector. Actually std::vector<TCHAR> would be better, in case you use UNICODE builds where TCHAR will be wchar_t.
3)what is the difference between char array and char *?
both points to array of char type, so no much difference.
the char array name is also constant pointer to the first element then what is the difference???
if it is const char* nm = "alabama"; then it says you cannot modify nm array content
4)how to return char array from function in c ? in c++?
to safely return a char array, you should make sure its lifetime is longer that your function lifetime. This means either you have to allocate memory inside function,- or pass already allocated memory to your function.
5)what is the differnce between char * and const char * ? they both the same cuz the value being pointed is unchangeable!
char* is an array of type char that you can modify in your code, const char* is an array of char type you can only read.
What is the proper way to initialize unsigned char*? I am currently doing this:
unsigned char* tempBuffer;
tempBuffer = "";
Or should I be using memset(tempBuffer, 0, sizeof(tempBuffer)); ?
To "properly" initialize a pointer (unsigned char * as in your example), you need to do just a simple
unsigned char *tempBuffer = NULL;
If you want to initialize an array of unsigned chars, you can do either of following things:
unsigned char *tempBuffer = new unsigned char[1024]();
// and do not forget to delete it later
delete[] tempBuffer;
or
unsigned char tempBuffer[1024] = {};
I would also recommend to take a look at std::vector<unsigned char>, which you can initialize like this:
std::vector<unsigned char> tempBuffer(1024, 0);
The second method will leave you with a null pointer. Note that you aren't declaring any space for a buffer here, you're declaring a pointer to a buffer that must be created elsewhere. If you initialize it to "", that will make the pointer point to a static buffer with exactly one byte—the null terminator. If you want a buffer you can write characters into later, use Fred's array suggestion or something like malloc.
As it's a pointer, you either want to initialize it to NULL first like this:
unsigned char* tempBuffer = NULL;
unsigned char* tempBuffer = 0;
or assign an address of a variable, like so:
unsigned char c = 'c';
unsigned char* tempBuffer = &c;
EDIT:
If you wish to assign a string, this can be done as follows:
unsigned char myString [] = "This is my string";
unsigned char* tmpBuffer = &myString[0];
If you know the size of the buffer at compile time:
unsigned char buffer[SIZE] = {0};
For dynamically allocated buffers (buffers allocated during run-time or on the heap):
1.Prefer the new operator:
unsigned char * buffer = 0; // Pointer to a buffer, buffer not allocated.
buffer = new unsigned char [runtime_size];
2.Many solutions to "initialize" or fill with a simple value:
std::fill(buffer, buffer + runtime_size, 0); // Prefer to use STL
memset(buffer, 0, runtime_size);
for (i = 0; i < runtime_size; ++i) *buffer++ = 0; // Using a loop
3.The C language side provides allocation and initialization with one call.
However, the function does not call the object's constructors:
buffer = calloc(runtime_size, sizeof(unsigned char))
Note that this also sets all bits in the buffer to zero; you don't get a choice in the initial value.
It depends on what you want to achieve (e.g. do you ever want to modify the string). See e.g. http://c-faq.com/charstring/index.html for more details.
Note that if you declare a pointer to a string literal, it should be const, i.e.:
const unsigned char *tempBuffer = "";
If the plan is for it to be a buffer and you want to move it later to point to something, then initialise it to NULL until it really points somewhere to which you want to write, not an empty string.
unsigned char * tempBuffer = NULL;
std::vector< unsigned char > realBuffer( 1024 );
tempBuffer = &realBuffer[0]; // now it really points to writable memory
memcpy( tempBuffer, someStuff, someSizeThatFits );
The answer depends on what you inted to use the unsigned char for. A char is nothing else but a small integer, which is of size 8 bits on 99% of all implementations.
C happens to have some string support that fits well with char, but that doesn't limit the usage of char to strings.
The proper way to initialize a pointer depends on 1) its scope and 2) its intended use.
If the pointer is declared static, and/or declared at file scope, then ISO C/C++ guarantees that it is initialized to NULL. Programming style purists would still set it to NULL to keep their style consistent with local scope variables, but theoretically it is pointless to do so.
As for what to initialize it to... set it to NULL. Don't set it to point at "", because that will allocate a static dummy byte containing a null termination, which will become a tiny little static memory leak as soon as the pointer is assigned to something else.
One may question why you need to initialize it to anything at all in the first place. Just set it to something valid before using it. If you worry about using a pointer before giving it a valid value, you should get a proper static analyzer to find such simple bugs. Even most compilers will catch that bug and give you a warning.