I've been told that the following is bad code because z_strings is already a char array. However I don't really know much C++ so I don't really know what the usage is doing or why it would be wrong. Can somebody offer an explanation?
Declaration: char z_strings[3];
Usage: MyFunction(myints, (char**)&z_strings, another_int_arg);
Definition of MyFunction: void MyFunction(int* my_ints, char** z_strings, int another_int_arg)
For context, this is a coworker's "code review" code which is intentionally broken; he was using it to ask interview candidates to fix the bad code. However this coworker has actually left the company and the only notes say that it's a bad cast, and I'm trying to figure out some more details about why because I'm curious.
I removed context I thought was irrelevant, but for the full context MyFunction is actually GetPowers(p_int, (char**)&z_strings, 3); p_int will be an array like [2,3,4] and z_strings will be populated with values like ['Hundreds','Thousands','Ten Thousands'], in other words this function translates numerical powers into English equivalents.
Unlike the widespread and erroneously taught belief, arrays are not pointers. They may decay into pointers in most contexts, but the address-of operator is not one of those contexts.
If the type of z_strings is char[3], then the type of &z_strings is char (*)[3]. It is a pointer to an array of three characters. And a pointer to an array is not compatible with a pointer to a pointer.
That's what's wrong with your cast. As for how to fix it, with the little context you've shown, the obvious solution is to introduce an actual pointer:
char *p_z_strings = z_strings; //decay here
MyFunction(myints, &p_z_strings , another_int_arg); // no cast; exact match
With the added context you provided, the "obvious" solution is now rather glaringly incorrect. There's still a few details missing, but if we are working under the assumption that GetPowers will do the allocation for the new strings, we do not need additional variables:
char* z_strings[3]; // Now we have an array of pointers
GetPowers(p_int, z_strings, 3); // It decays into a pointer to a pointer
// GetPowers populates it
The cast is bad, because it shuts up the compiler, without fixing the code.
The real fix might be using the proper array, which could be (as the function argument type suggests) an array of pointers, e.g.
char *z_strings[3];
Now you can call the function without any cast at all:
MyFunction(myints, z_strings, another_int_arg);
In C and C++ an array 'decays' to a pointer when the identifier is used as an argument to a function that expects a pointer. This means that if you have a function that takes a char* (C and common C++ form of a string argument) then you can just pass it a char array and no casting is required.
In your example, you are casting to a char** which is a pointer to a pointer to a char. This suggests the function expects to change what a char* argument points to and this is not something that makes sense with an array argument. Without knowing more context here it's hard to give a more specific answer to your question though. It's also possible that a char** argument could be intended to be an array of strings (in which case you would expect an additional array size argument) but without seeing what MyFunction() is intended to do it's hard to say.
Related
I am trying to change the properties of a file using C ++
what am I doing wrong ?
The code is completely taken
https://learn.microsoft.com/en-us/windows/win32/stg/writeread-sample
propspec.ulKind = PRSPEC_LPWSTR;
propspec.lpwstr = L"Property Name";// this line problem
propvarWrite.vt = VT_LPWSTR;
propvarWrite.pwszVal = L"Property Value"; // this line problem
As the error message tells already: String literals are of type const char[] or const wchar_t[] (depending on underlying type), and you cannot legally assign an array of const to a pointer to non-const (some compilers accept such code, though, just emitting a warning), solely the other way round is allowed.
Question is now, how to get out of that dilemma?
In general:
If you are 100% sure (really, not the very least doubt!) that the strings won't get modified, you could just cast the const away:
wchar_t* ptr = const_cast<wchar_t*>(L"...");
If you have the least doubt about (modifications of string literals are undefined behaviour!), then copy the literal into an array:
wchar_t value[] = L"...";
ptr = value;
At this point, you need to be sure that the called function won't take ownership of the string, though: Would it try to free the string? Would it store the pointer somewhere for later usage, such that the array pointed to must live longer than the scope of the calling function?
If so, you might need to use a global array or malloc memory to copy the string to...
In specific case:
If you peek into the documentation of read and write functions, you see that the structs in question are passed to const parameters. Well, actually, that will make the pointer constant, not the data pointed to, still it looks pretty much safe to assume that the strings won't get modified (if need be, copied to somewhere – well, written to some file), so you actually should be fine with the const_cast option.
Side note: The example doesn't free the strings read back again; pretty interesting now the question for ownership (who will free them again)? Unfortunately, the documentation is not precise about...
I understand the use of pointer to constant for strlen implementation.
size_t strlen ( const char * str );
Can anyone suggest other reasons or provide some scenarios where 'Pointer to Const value' is useful in practice.
Think of it this way. You want me to look at the value of a variable but you don't want me to alter that variable in any way, so you pass it to me as a constant. When I use your function and see that a parameter is constant then I know there is a contract between you and I that says I should not change the value of that variable nor can I do it directly.
When you write code you don't always know who will use your functions. So it is good practice to protect your code. It also protects you from yourself, you will get compiler errors the moment you tr to change the value of that variable.
A side note: It is true that in C you can still change the value even though the parameter says const, but it would take another pointer which would alter the content of that variable in memory.
Try compiling this code and notice how the compiler protects you from making a mistake.
const char *cookies(const char *s)
{
return ('\0' == *s)? s: s + 1;
}
It won't let you compile, why? Because you are trying to change a const variable.
Another post with the same question here: const usage with pointers in C
Marking a pointer argument as const is a contract whereby you assert to the user you won't change the values pointed to. It's also a contract that you won't try to write to them, so that it is legal for them to give you a pointer to something that is read-only memory, and your function won't crash - as long as you fulfill this contract.
It's not just "useful", in some cases it is required, particularly when you are dealing with what amounts to write protected memory such as string literals or any value stored in the code section of your executable.
It's also valuable when you are using data that might be shared: If two threads want to call a function foo(char* x) each will need its own copy of the string, otherwise bad things would happen. If the function is foo(const char* x) then we know it is safe for both to share a single pointer to the input.
Consider, if you have a pointer to write-protected memory:
mprotect(ptr, sizeOfData, PROT_READ);
It is now not possible to call a function that attempts to write to ptr without a program exception (this is often done with things like caches when nobody owns a write-lock on the cache).
Thus you can only call const functions on ptr at this point.
Pointer to const of char is the type of the strings literals (those inside ""). This is the primary use for pointer to const value.
In Borland C++ when I write this code, compiler gives this error --> "Lvalue required".
struct harf {
char word[10];
} pr[10];
void main() {
pr[0].word="Alireza"; //Lvalue required
getch();
}
What can I do?
Assignment operation is not allowed on arrays. C++ does not allow you to do that.
For copying data to a character array, use string copy function.
Use it like this.
strcpy(pr[0].word,"Alireza");
Another way to do this is to perform char by char copy using a loop yourself. Though better use library functions. :)
This question may also help you.
Iterating through C-style array not using a pointer
Remember that compound operations are not allowed on arrays in C++. You cannot directly perform arithmetic or logical operations on them.
You need to use strcpy(..) or strncpy(..). You can not directly assign it using assignment operator.
strcpy(pr[0].word,"Alireza");
Besides, since you are using C++, why not use std::string. Something like:
std::string myString;
..
myString = "AlireZa";
use :
strncpy( pr[0].word, "Alireza", 10);
slightly safier solution is to :
strncpy( pr[0].word, "Alireza", sizeof(pr[0].word)/sizeof(pr[0].word[0]));
this way if word array changes you wont have to fix size change in other parts of your code. Using strncpy is considered safier than strcpy, because the second one can easily cause buffer overrun.
Still, its better to use std::string
pr[0].word is an array. You cannot assign to arrays.
In your situation, the array expression decays to a pointer to the first element, but that expression is an rvalue (since obviously it makes no sense to attempt to change that pointer!).
pr[0].word is an array at some location in memory.
"Alireza" is another char array in some different location in memory.
Your assignment tries to redirect pr[0].word to the Alireza memory, which is invalid since pr[0].word is an array. You can redirect pointers but not arrays. You can either:
make a pr[0].word a pointer and then set the pointer to different locations as you try to do now.
Copy the contents of the "Alireza" memory to pr[0].word memory, using strcpy function as suggested by others
As you are in C++, you can also declare pr[0].word as a std::string which will do all memory-copy the magic for you under a convenient = operator, making pr[0].word="Alireza" valid again. This approach may also help you avoid some nasty bugs which could otherwise occur when dealing with "naked" char *.
i'm pretty new to box2d and i'm trying to use the userdata (of type void*) field in the b2body object to store an int value (an enum value, so i know the type of the object).
right now i'm doing something this:
int number = 1023;
void* data = (void*)(&number);
int rNumber = *(int*)data;
and i get the value correctly, but as i've been reading around casting to void* it's not portable or recommendable... is my code cross-platform? is it's behavior defined or implementation dependent?
Thanks!
Casting to void * is portable. It is not recommended because you are losing type safety. Anything can be put into a void * and anything can be gotten out. It makes it easier to shoot yourself in the foot. Otherwise void * is fine as long as you are careful and extra cautious.
You are actually not casting int to void*, you cast int* to void*, which is totally different.
A pointer to any type can be stored in a void*, and be cast back again to the same type. That is guaranteed to work.
Casting to any other type is not portable, as the language standard doesn't say that different pointers have to be the same size, or work the same way. Just that void* has to be wide enough to contain them.
One of the problems with void* is that you need to know (keep track of) what type it originally was in order to cast it properly. If it originally was a float and you case it to an int the compiler would just take your word for it.
To avoid this you could create a wrapper for your data which contains the type, that way you will be able to always cast it to the right type.
Edit: you should also make a habit of using C++ casting style instead of C i.e. reinterpret_cast
void * is somehow a relic of the past (ISO C), but very convenient. You can use it safely as far as you are careful casting back and forward the type you want. Consider other alternatives like the c++ class system or overloading a function
anyways you will have better cast operators, some times there is no other way around (void*), some other times they are just too convenient.
It can lead to non portable code, not because of the casting system, but because some people are tempted to do non portable operations with them. The biggest problem lies in the fact that (void*) is a as big as a memory address, which in many platforms happens to be also the length of the platform integers.
However in some rare exceptions size(void*) != size(int)
If you try to do some type of operations/magic with them without casting back to the type you want, you might have problems. You might be surprised of how many times I have seen people wanting to store an integer into a void* pointer
To answer your question, yes, it's safe to do.
To answer the question you didn't ask, that void pointer isn't meant for keeping an int in. Box2D has that pointer for you to point back to an Entity object in your game engine, so you can associate an Entity in your game to a b2Body in the physics simulation. It allows you to more easily program your entities interact with one another when one b2Body interacts with another.
So you shouldn't just be putting an enum in that void*. You should be pointing it directly to the game object represented by that b2body, which could have an enum in it.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How do pointer to pointers work in C?
Hello,
Altough I think I passed the newbie phase in programming I still have some questions that somehow I can't find them explained. Yes, there are plenty of "how to"s overthere but almost always nobody explains why and/or when one technique is useful.
In my case I have discovered that in some cases a pointer to a pointer is used in C++. Is not a pointer to an object enough? Which are the benefits? Where or when should be used a pointer to a pointer? I feel little bit desorientated in this matter.
I hope time experienced expert could respond to this concerns that hopefully is shared by other no so experienced programers. ;-)
Thank you everyone.
Julen.
Well, it is somehow hard to answer to such a general question.
First answer of a C++ programmer will certainly be : Do not use pointers in C++ ! As you have a lot of safer ways to handle problems than pointers, one of your goal will be to avoid them in the first place :)
So pointers to pointers are seldom used in C++. They are mainly used in C. First, because in C, strings are "char*" so when you need a "pointer to a C string" you end with a "char**". Second, as you do not have references in C, when you need to have a function that modify a pointer or that give a pointer as an output value, you need to give a pointer to a pointer parameter. You typically find that in functions that allocate memory, as they give you a pointer to the allocated memory.
If you go the C++ way, try to avoid pointers, you usually have better ways.
my2c
In C, an argument is passed to a function that changes it, through a pointer. You will see the same with C++ for old or legacy code (int main(int argc, char** argv)) , for code that will be accessed from C (COM / XPCOM) or with code that was written by someone used to C (or the C style).
From a "purely C++" standpoint, using pointer to pointer is in most situations a sign of poor coding style, as most situations that require a ** construct can (and should) be refactored to use safer alternatives (like std:: containers, or *& parameters).
I can think of two use cases.
One is arrays as inherited from C. Arrays automatically decay to pointers to their first elements in many cases. If you happen to have an array of pointers, you get a pointer to a pointer for that.
(Something similar can happen when you have a std::vector of pointers, BTW: A pointer is a perfect random access iterator and I have indeed seen std lib implementations using pointers for std::vector<>::iterator. For a std::vector of pointers, v.begin() would return a pointer to a pointer.)
The other is for function arguments. For function arguments, taking something per pointer indicates that callers might call the function even if they don't have an object to pass in; they can pass in NULL then. (Otherwise why take a pointer instead of a reference? See here for more details on this).
Taking a non-const reference to a pointer would indicate that the called function might assign a new address to that pointer.
So taking a pointer to a pointer would indicate that the function might assign a new address to a pointer, if the caller passes in a pointer to it, but is callable with NULL as well.
For example:
void f(int** ppi);
void g(int i);
void h()
{
f(NULL); // call `f()` only for its side-effects
int* pi = NULL;
f(&pi); // call `f()` and get some object in *pi
if(pi)
g(*pi); // use result
}
Where or when should be used a pointer to a pointer?
In a function that optionally may return pointer to caller, if the caller requests that. Frequently used by system APIs, some COM objects, etc.
int f(void** p = 0){
//.......
}
If caller provides p, then function passes pointer through p. If caller doesn't provide p, then no pointer is returned. May be useful for debugging purposes in certain situations.
Which are the benefits?
The question is too broad. Look, it is a VERY simple technique without some kind of mysterious benefits. You use it when you have to. That's all. There is no hidden meaning and no secret advantages of this concept - it is equivalent to asking "what are benefits of using letter \"e\" in english language".
Pointers to pointers have most relevance in C. Seldomly, you need them in C++. There you can work with containers from the std lib or with references.
There are two popular use cases in C though:
An array of pointers, most prominently used as argv to main(): the pointer gives the address to the array of argument strings (type char*). In C, the [] operators work on pointers to anything as pointers to anything are seen as an equivalent to arrays.
A function argument denoting a place where to store the address of something. Use case: In C, the return value is often used for error handling or state information. Arguments are used for carrying the payload. One example: A function "returns" an address to newly allocated memory, but using an argument. You give the function a pointer to the pointer that should afterwards point to the data. The function overwrites that space and for that, it needs a pointer to a pointer.
You only use them when employing manual memory management, something that's rare as hell in C++, therefore they're pretty useless. Even regular pointers are of questionable value in the majority of scenarios.
There're actually two use cases.
First, is when you call a function that has to return more than one value, some of which, are pointers. Then, you would provide her with an address of a pointer, so it could fill in the pointed pointer:
int *p1 = 0, *p2 = 0, *p3 = 0;
multi_malloc(&p1, &p2, &p3); // Allocates three pointers
Second is when you want to do sparse 2d arrays:
int main(int argc, char **argv)
This is a pointer to pointer. argv[i] is a pointer to char. This way, argv[i][j] is a char j in row i.
You will be happy to hear that there're nearly zero uses for pointer to pointer to pointer. int ***p; is almost never useful.