Uses for multiple levels of pointer dereferences? - c++

When does using pointers in any language require someone to use more than one, let's say a triple pointer. When does it make sense to use a triple pointer instead of just using a regular pointer?
For example:
char * * *ptr;
instead of
char *ptr;

each star should be read as "which pointed to by a pointer" so
char *foo;
is "char which pointed to by a pointer foo". However
char *** foo;
is "char which pointed to by a pointer which is pointed to a pointer which is pointed to a pointer foo". Thus foo is a pointer. At that address is a second pointer. At the address pointed to by that is a third pointer. Dereferencing the third pointer results in a char. If that's all there is to it, its hard to make much of a case for that.
Its still possible to get some useful work done, though. Imagine we're writing a substitute for bash, or some other process control program. We want to manage our processes' invocations in an object oriented way...
struct invocation {
char* command; // command to invoke the subprocess
char* path; // path to executable
char** env; // environment variables passed to the subprocess
...
}
But we want to do something fancy. We want to have a way to browse all of the different sets of environment variables as seen by each subprocess. to do that, we gather each set of env members from the invocation instances into an array env_list and pass it to the function that deals with that:
void browse_env(size_t envc, char*** env_list);

If you work with "objects" in C, you probably have this:
struct customer {
char *name;
char *address;
int id;
} typedef Customer;
If you want to create an object, you would do something like this:
Customer *customer = malloc(sizeof Customer);
// Initialise state.
We're using a pointer to a struct here because struct arguments are passed by value and we need to work with one object. (Also: Objective-C, an object-oriented wrapper language for C, uses internally but visibly pointers to structs.)
If I need to store multiple objects, I use an array:
Customer **customers = malloc(sizeof(Customer *) * 10);
int customerCount = 0;
Since an array variable in C points to the first item, I use a pointer… again. Now I have double pointers.
But now imagine I have a function which filters the array and returns a new one. But imagine it can't via the return mechanism because it must return an error code—my function accesses a database. I need to do it through a by-reference argument. This is my function's signature:
int filterRegisteredCustomers(Customer **unfilteredCustomers, Customer ***filteredCustomers, int unfilteredCount, int *filteredCount);
The function takes an array of customers and returns a reference to an array of customers (which are pointers to a struct). It also takes the number of customers and returns the number of filtered customers (again, by-reference argument).
I can call it this way:
Customer **result, int n = 0;
int errorCode = filterRegisteredCustomers(customers, &result, customerCount, &n);
I could go on imagining more situations… This one is without the typedef:
int fetchCustomerMatrix(struct customer ****outMatrix, int *rows, int *columns);
Obviously, I would be a horrible and/or sadistic developer to leave it that way. So, using:
typedef Customer *CustomerArray;
typedef CustomerArray *CustomerMatrix;
I can just do this:
int fetchCustomerMatrix(CustomerMatrix *outMatrix, int *rows, int *columns);
If your app is used in a hotel where you use a matrix per level, you'll probably need an array to a matrix:
int fetchHotel(struct customer *****hotel, int *rows, int *columns, int *levels);
Or just this:
typedef CustomerMatrix *Hotel;
int fetchHotel(Hotel *hotel, int *rows, int *columns, int *levels);
Don't get me even started on an array of hotels:
int fetchHotels(struct customer ******hotels, int *rows, int *columns, int *levels, int *hotels);
…arranged in a matrix (some kind of large hotel corporation?):
int fetchHotelMatrix(struct customer *******hotelMatrix, int *rows, int *columns, int *levels, int *hotelRows, int *hotelColumns);
What I'm trying to say is that you can imagine crazy applications for multiple indirections. Just make sure you use typedef if multi-pointers are a good idea and you decide to use them.
(Does this post count as an application for a SevenStarDeveloper?)

A pointer is simply a variable that holds a memory address.
So you use a pointer to a pointer, when you want to hold the address of a pointer variable.
If you want to return a pointer, and you are already using the return variable for something, you will pass in the address of a pointer. The function then dereferences this pointer so it can set the pointer value. I.e. the parameter of that function would be a pointer to a pointer.
Multiple levels of indirection are also used for multi dimensional arrays. If you want to return a 2 dimensional array, you would use a triple pointer. When using them for multi dimensional arrays though be careful to cast properly as you go through each level of indirection.
Here is an example of returning a pointer value via a parameter:
//Not a very useful example, but shows what I mean...
bool getOffsetBy3Pointer(const char *pInput, char **pOutput)
{
*pOutput = pInput + 3;
return true;
}
And you call this function like so:
const char *p = "hi you";
char *pYou;
bool bSuccess = getOffsetBy3Pointer(p, &pYou);
assert(!stricmp(pYou, "you"));

ImageMagicks's Wand has a function that is declared as
WandExport char* * * * * * DrawGetVectorGraphics ( const DrawingWand *)
I am not making this up.

N-dimensional dynamically-allocated arrays, where N > 3, require three or more levels of indirection in C.

A standard use of double pointers, eg: myStruct** ptrptr, is as a pointer to a pointer. Eg as a function parameter, this allows you to change the actual structure the caller is pointing to, instead of only being able to change the values within that structure.

Char *** foo can be interpreted as a pointer to a two-dimensional array of strings.

You use an extra level of indirection - or pointing - when necessary, not because it would be fun. You seldom see triple pointers; I don't think I've ever seen a quadruple pointer (and my mind would boggle if I did).
State tables can be represented by a 2D array of an appropriate data type (pointers to a structure, for example). When I wrote some almost generic code to do state tables, I remember having one function that took a triple pointer - which represented a 2D array of pointers to structures. Ouch!

int main( int argc, char** argv );

Functions that encapsulate creation of resources often use double pointers. That is, you pass in the address of a pointer to a resource. The function can then create the resource in question, and set the pointer to point to it. This is only possible if it has the address of the pointer in question, so it must be a double pointer.

If you have to modify a pointer inside a function you must pass a reference to it.

It makes sense to use a pointer to a pointer whenever the pointer actually points towards a pointer (this chain is unlimited, hence "triple pointers" etc are possible).
The reason for creating such code is because you want the compiler/interpreter to be able to properly check the types you are using (prevent mystery bugs).
You dont have to use such types - you can always simply use a simple "void *" and typecast whenever you need to actually dereference the pointer and access the data that the pointer is directing towards. But that is usually bad practice and prone to errors - certainly there are cases where using void * is actually good and making code much more elegant. Think of it more like your last resort.
=> Its mostly for helping the compiler to make sure things are used the way they are supposed to be used.

To be honest, I've rarely seen a triple-pointer.
I glanced on google code search, and there are some examples, but not very illuminating. (see links at end - SO doesn't like 'em)
As others have mentioned, double pointers you'll see from time to time. Plain single pointers are useful because they point to some allocated resource. Double pointers are useful because you can pass them to a function and have the function fill in the "plain" pointer for you.
It sounds like maybe you need some explanation about what pointers are and how they work?
You need to understand that first, if you don't already.
But that's a separate question (:
http://www.google.com/codesearch/p?hl=en#e_ObwTAVPyo/security/nss/lib/ckfw/capi/ckcapi.h&q=***%20lang:c&l=301
http://www.google.com/codesearch/p?hl=en#eVvq2YWVpsY/openssl-0.9.8e/crypto/ec/ec_mult.c&q=***%20lang:c&l=344

Pointers to pointers are rarely used in C++. They primarily have two uses.
The first use is to pass an array. char**, for instance, is a pointer to pointer to char, which is often used to pass an array of strings. Pointers to arrays don't work for good reasons, but that's a different topic (see the comp.lang.c FAQ if you want to know more). In some rare cases, you may see a third * used for an array of arrays, but it's commonly more effective to store everything in one contiguous array and index it manually (e.g. array[x+y*width] rather than array[x][y]). In C++, however, this is far less common because of container classes.
The second use is to pass by reference. An int* parameter allows the function to modify the integer pointed to by the calling function, and is commonly used to provide multiple return values. This pattern of passing parameters by reference to allow multiple returns is still present in C++, but, like other uses of pass-by-reference, is generally superseded by the introduction of actual references. The other reason for pass-by-reference - avoiding copying of complex constructs - is also possible with the C++ reference.
C++ has a third factor which reduces the use of multiple pointers: it has string. A reference to string might take the type char** in C, so that the function can change the address of the string variable it's passed, but in C++, we usually see string& instead.

When you use nested dynamically allocated (or pointer linked) data structures. These things are all linked by pointers.

Particularly in single-threaded dialects of C which don't aggressively use type-based aliasing analysis, it can sometimes be useful to write memory managers which can accommodate relocatable objects. Instead of giving applications direct pointers to chunks of memory, the application receives pointers into a table of handle descriptors, each of which contains a pointer to an actual chunk of memory along with a word indicating its size. If one needs to allocate space for a struct woozle, one could say:
struct woozle **my_woozle = newHandle(sizeof struct woozle);
and then access (somewhat awkwardly in C syntax--the syntax is cleaner in
Pascal): (*my_woozle)->someField=23; it's important that applications not
keep direct pointers to any handle's target across calls to functions which
allocate memory, but if there only exists a single pointer to every block
identified by a handle the memory manager will be able to move things around
in case fragmentation would become a problem.
The approach doesn't work nearly as well in dialects of C which aggressively
pursue type-based aliasing, since the pointer returned by NewHandle doesn't
identify a pointer of type struct woozle* but instead identifies a pointer
of type void*, and even on platforms where those pointer types would have
the same representation the Standard doesn't require that implementations
interpret a pointer cast as an indication that it should expect that aliasing
might occur.

Double indirection simplifies many tree-balancing algorithms, where usually one wants to be able to efficiently "unlink" a subtree from its parent. For instance, an AVL tree implementation might use:
void rotateLeft(struct tree **tree) {
struct tree *t = *tree,
*r = t->right,
*rl = r->left;
*tree = r;
r->left = t;
t->right = rl;
}
Without the "double pointer", we would have to do something more complicated, like explicitly keeping track of a node's parent and whether it's a left or right branch.

Related

Unspecified number of variables within a struct

I'm writing a simple program using structures. The structure I have a problem with is supposed be flexible when it comes to the number of variables within the definition of a said structure. The program is to download the number from a file with .txt extension:
ints: 5
strings: 6
then create a defined number of ints and strings in the structure. At first I was thinking about using pointers within the struct:
struct Data
{
int* intArr;
string* stringArr;
};
But after a quick search it turned out to be an ineffective way to go about the problem. The biggest challenge is... that I cannot use STL.
Could you please point me in the right direction?
Hardly am I an experienced programmer so I apologise if the question is inaccurate or just plainly wrong.
void* is convertible to any data type, you can do void *var = new char and is valid, but void has not size, so it is useless to allocate different types together, because you'll have to know the type in order to dereference the pointer (and/or the length to iterate over it), but you don't know it, unless you track all the types, but as you can suppose, this is really ineffective.
If you want to allocate memory for different datatypes, do it in the right way, that is, a pointer for each type:
int * foo;
foo = new int[N];
char * bar;
bar = new bar[N];
Regarding the ineffectiveness, bear in mind that you have two ways, calculate the worst case scenario and reserve the memory at compilation time (i.e. char charArray[50]; int intArray[200]), or use new/delete to allocate memory based on the runtime requirements (which is what stl is going to do under the hood, unless you use std::array)
I did not understood your problem correctly but what you have mentioned it seems you want to bind variable number of information to a structure.
Use double pointer as variable in the structure to allocate address of array or pointers. This should solve your problem of variable number of members.
struct X
{
int **ptr;
};
X a;
a.ptr = malloc(sizeof(int*)*10);
This should create 10 pointers and allocate address of created pointer to structure member variable. This value 10 can vary at run time.

Why, or in what situations, would you pass an argument to a function as a reference (or pointer) in C++?

I am used to passing arguments regularly in my own code but frequently stumble upon function arguments being passed by reference or pointer while reading over others' C++ code. I do not understand what is the purpose of doing so. Can somebody please explain this?
There are essentially three reasons why this is done.
Reduced memory usage
Every time you call a function the arguments are copied and passed. This isn't a big deal when you are passing around numbers. However when you are dealing with big chunks of memory, like objects, structs, arrays etc. this becomes very expensive.
So all complex types are typically passed as pointers. If you are throwing around objects you are always working with a pointer.
The const qualifier should be used in this instance to indicate that the variable won't be changed.
Modify the argument
Sometimes it is useful to modify the passed argument, though this should be avoided as bad style. The best example I think is modifying an array, for example a push() function. Another is modifying an objects public members, or when you want to return multiple values from a function.
Note that this can be a source of bugs. If you are modifying a passed variable it should be obvious from the name of the function that this is what you are doing.
Low level memory access
Anything which directly works with memory will want direct access to said memory. Standard practice in C but less common in C++. Look at functions like memcpy() and anything else from <string.h>.
If I pass a bunch of characters to a function, I can change them inside it and they will remain unchanged outside the function. This means if you wish to capitalise some text, you'd have to make a copy of it, then change some of the letters.
If on the other hand, you told the function the address of that string in memory, it could then change the existing string without making a copy. Sometimes, the arguments required will consume a trivial size. Other-times, the data required make take several hundred mega/giga/tera bytes. The last thing you want to do is read all that in, then make a copy of it that you can send off to a function.
The difference between references and pointers is mostly convenient syntax for the programmer, but there are important exceptions to this rule.
If you pass argument to a function, you can change it inside the function. Once the execution of that function has finished, the passed in variable will rename unchanged.
int square_this_number(int x)
{
int y = 0;
y = x * x;
x = 1000;
return y;
}
int a = 10;
int b = 0;
b = square_this_number(a);
/* a is still 10, not 1000. */
/* b is 100. */
Pass by reference or pass by pointer means that you want to keep the change once the execution of function has finished.
int try_square_and_change_input(int& x)
{
int y = 0;
y = x * x;
x = 23;
return y;
}
int a = 5;
int b = 0;
b = try_square_and_change_input(a);
/* a is now 23 instead of just 5. */
/* b is 25 of course. */
You may refer to this page: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.3.0/com.ibm.zos.v2r3.cbclx01/cplr233.htm
Reasons to do this include:
I need to modify a variable that is not local to the called function.
I want to pass a single word to the function, rather than make a copy of a large structure or array (and possibly another if I need to modify it).
It's a pointer to shared memory and I want changes to be visible in different processes or threads.
It's a pointer to a polymorphic struct or union (or class in C++) and I want the function to be able to determine the correct type at runtime.
The size and type of the data might vary, as with memcpy().
The type should be opaque to client code.
That's just how the interface is specified.
Pass by value: when we don't want to change variables value from called function.
Pass by reference: (only. In c++, not in c): when we want to do changes in variabe by called function.
Pass by pointer: from periferi it works same as reference, but there exist differences..

Why can you convert all types to other pointer types?

Code:
class Dummy {
double i,j;
};
class Addition {
int x,y;
public:
Addition (int a, int b) { x=a; y=b; }
int result() { return x+y;}
};
int main () {
Dummy d;
Addition * padd;
padd = (Addition*) &d;
//cout << padd->result();
return 0;
}
Questions:
Why can you do this padd = (Addition*) &d; but not this padd = (Addition) &d;?
When declaring an object of Addition like Addition padd instead of Addition* padd, why does it ask for a constructor, which it doesn't when declaring a pointer?
Taking the address of a variable returns a pointer, which is a very different thing than the original variable. A pointer is just a memory address (usually the size of an int), while the object pointed can be anything from char to a huge table or a stream. So you can definitively not cast a pointer in non-pointer type (and vice-versa), and (Addition) &d can not work.
When you type Addition padd;, you build an object of type Addition which the default constructor. When you type Addition* padd;, you just declare a pointer, so a memory address, and no object is created.
Finally, be careful with the C cast (the type in parenthesis in front of the variable). This cast will try several C++ cast until it succeeds (from static_cast to reinterpret_cast), and you can easily find yourself on an undefined behavior. See this for instance.
A simple simile that indirectly answers your questions:
Pointers are like real-life signs.
A sign pointing to a lake is similar to a sign pointing to a building (but you can also use a different definition of "similar" which will say these things aren't similar).
A sign pointing to a lake is not similar to an actual lake or building.
Now when you assume a sign is pointing to a lake when it's in fact pointing to a building, and you try to treat that building like a lake (by e.g. swimming in it), you're going to have problems.
That is to say: C++ would run code that casts between incompatible pointers, but trying to access the object the pointer you incorrectly cast is pointing to probably won't work so well for you.
Making a new sign doesn't require that you also make the thing you want it to point to.
You can have a sign to a lake that doesn't actually point to a lake (yet?), or you can point it to an existing lake.
&lake gives you a sign to lake.
Disclaimer: I might've borrowed the core idea from someone else.
Basically you asking what is the difference between an object and a pointer to an object?
Object is a region of storage. A pointer is just a an integer pointing an offset in this storage. A pointer physically (after making a binary out of code) does not differ from an object of one type to an object of another type - always an integer. On the other hand, object is a region that has an offset and a size. That two basic matters that C++ distinguishes.
Why can you do this padd = (Addition*) &d; but not this padd = (Addition) &d;?
Like it is said above all pointers are physically the same (i.e. integers). That is why it is always possible to do the former. Mind that at the end dereferencing this pointer is undefined behavior. However it does not seem feasible for the compiler to convert to different matters (pointer to storage).
When declaring an object of Addition like Addition padd instead of Addition* padd, why does it ask for a constructor, which it doesn't when declaring a pointer?
Again pointer is just an integer, you do not need anything else to create it. However, Addition is a storage shat is type that has no default constructor that is why you have to provide other objects to initialize it.
By the way, pointers are also object, that is why you can have a pointer to a pointer and etc.
In addition:
Pointers to void, objects, functions are very different from pointers to members;
Pointers to void, objects, functions must not be assumed to have a fixed size, size might be varying on some platforms, compilers, but not larger than void*.

Using char* or char [] in struct C++

I am creating a struct called student. In order to store the name, is there anything wrong with just declaring a char pointer in the struct instead of a char array with a predefined size? I can then assign a string literal to the char pointer in the main code.
struct student
{
int ID;
char* name;
};
It really depends on your use case. As suggested above you should use std::string in C++. But if you are using C-style strings, then it depends on your usage.
Using char[] of defined size you can avoid errors due to null pointers and other pointer related errors like memory leaks, dangling pointers etc., but you might not be making an optimal use of memory. You may for example define
#define MAX_SIZE 100
struct student
{
int ID;
char name[MAX_SIZE];
};
And then
#define STUDENT_COUNT 50
struct student many_students[STUDENT_COUNT];
But the length of names of student will be different and in many cases much less than MAX_SIZE. As such much memory will be wasted here.
Or in some cases it might be greater than MAX_SIZE. You may have to truncate the names here to avoid memory corruption.
In other case where we define use char*, memory is not wasted as we allocate only the required amount, but we must take care of memory allocation and freeing.
struct student
{
int ID;
char *name;
};
Then while storing name we need to do something like this:
struct student many_student[STUDENT_COUNT];
int i;
for( i=0; i<STUDENT_COUNT; i++) {
// some code to get student name
many_student[i].name = (char*)malloc(name_length+1 * sizeof(char));
// Now we can store name
}
// Later when name is no longer required free it
free(many_student[some_valid_index_to_free].name);
// also set it to NULL, to avoid dangling pointers
many_student[some_valid_index_to_free].name = NULL;
Also if you are again allocating memory to name, you should free previously allocated memory to avoid memory leaks. Also another thing to consider is NULL checks for pointers before use, i.e., you should always check as
if(many_students[valid_index].name!=NULL) {
// do stuff
}
Although you can create macros to do this, but these are basic overheads with pointers.
Another advantage of using pointers is that if there are many similar names then you can point multiple pointers to same name and save memory, but in array you will be having separate memory for all, e.g,
// IF we have a predefined global name array
char *GLOBAL_NAMES[] = {"NAME_1", "NAME_2", "NAME_3", "NAME_4", ... , "NAME_N"};
// using pointers, just need to assign name to correct pointer in array
many_student[valid_index_1].name = GLOBAL_NAMES[INDEX_NAME_1];
many_student[valid_index_2].name = GLOBAL_NAMES[INDEX_NAME_1];
// In case of array we would have had to copy.
Although this might not be your case, but just saying that pointers may help avoid extra usage.
Hope it will help you :)
Don't use either, use std::string. I (and many others) guarantee that compared to either char* or char[]:
it will be easier to use and
it will be less prone to bugs.
Difference is same as difference between static and dynamic memory allocation. With former ( static ) you have to specify size enough to store the name whereas with latter you have to pay attention to delete it when in no need.
Although it's all time better to use std::string.
Unless there is a strong reason to not do so, I'd suggest you to use a convenient string class like std::string, instead of a raw char* pointer.
Using std::string will simplify your code a lot, e.g. the structure will be automatically copyable, the strings will be automatically released, etc.
A reason why you could not use std::string is because you are designing an interface boundary, think of e.g. Win32 APIs which are mainly C-interface-based (implementation can be in C++), so you can't use C++ at the boundary and instead must use pure C.
But if that's not the case, do yourself a favor and use std::string.
Note also that in case you must use a raw char* pointer, you have several design questions to clarify, e.g.:
Is this an owning pointer, or an observing pointer?
If it's an owning pointer, in what way is it allocated, and in what way is it released? (e.g. malloc()/free(), new[]/delete[], some other allocator like COM CoTaskMemAlloc(), SysAllocString(), etc.)
If it's an observing pointer, you must make sure that the observed string's lifetime exceeds that of the observing pointer, to avoid dangling references.
All these questions are just non-existent if you use a convenient string class (like e.g. std::string).
Note also that, as some Win32 data structures do, you can have a maximum-sized string buffer inside your structure, e.g.
struct Student
{
int ID;
char Name[60];
};
In this case you could use C functions like strcpy(), or safer variants, to deep-copy a source string into the Name buffer. In that case you have good locality since the name string is inside the structure, and a simplified memory management with respect to the raw char* pointer case, but at the cost of having a pre-allocated memory buffer.
This may or may not be a better option for you, depending on your particular programming context. Anyway, keep in mind that this is a more C-like approach; a better C++ approach would be to just use a string class like std::string.
TL;DR - use std::string, as we're talking in c++.
EDIT: Previously, as per the C tag (currently removed)
As per your requirement, assigning a string literal needs a pointer, you cannot do that with an array, anyway.#
If you're using that pointer to store the base address of a string literal, then it is ok. Otherwise, you need to
allocate memory before using that pointer
deallocate memory once you're done with it.
#) Base address of compile time allocted array cannot be changed, thus assignment won't work.
Use the std::string library. It is more easier to work with. And has way more functionality compared to the built in counterparts.

Is it a good idea to typedef pointers?

I looked through some code and noticed that the convention was to turn pointer types like
SomeStruct*
into
typedef SomeStruct* pSomeStruct;
Is there any merit to this?
This can be appropriate when the pointer itself can be regarded as a "black box", that is, a piece of data whose internal representation should be irrelevant to the code.
Essentially, if your code will never dereference the pointer, and you just pass it around API functions (sometimes by reference), then not only does the typedef reduce the number of *s in your code, but also suggests to the programmer that the pointer shouldn't really be meddled with.
This also makes it easier to change the API in the future if the need arises. For instance, if you change to using an ID rather than a pointer (or vice versa) existing code won't break because the pointer was never supposed to be dereferenced in the first place.
Not in my experience. Hiding the '*' makes the code hard to read.
The only time I use a pointer inside the typedef is when dealing with pointers to functions:
typedef void (*SigCatcher(int, void (*)(int)))(int);
typedef void (*SigCatcher)(int);
SigCatcher old = signal(SIGINT, SIG_IGN);
Otherwise, I find them more confusing than helpful.
The struck-out declaration is the correct type for a pointer to the signal() function, not of the signal catcher. It could be made clearer (using the corrected SigCatcher type above) by writing:
typedef SigCatcher (*SignalFunction)(int, SigCatcher);
Or, to declare the signal() function:
extern SigCatcher signal(int, SigCatcher);
That is, a SignalFunction is a pointer to a function which takes two arguments (an int and a SigCatcher) and returns a SigCatcher. And signal() itself is a function which takes two arguments (an int and a SigCatcher) and returns a SigCatcher.
This can help you avoid some errors. For example in following code:
int* pointer1, pointer2;
pointer2 is not an int *, it is simple int.
But with typedefs this is not gonna happen:
typedef int* pInt;
pInt pointer1, pointer2;
They are both int * now.
My answer is a clear "No".
Why?
Well, first of all, you simply exchange a single character * for another single character p. That is zero gain. This alone should keep you from doing this as it is always bad to do extra stuff that's pointless.
Second, and that is the important reason, the * carries meaning that is not good to hide. If I pass something to a function like this
void foo(SomeType bar);
void baz() {
SomeType myBar = getSomeType();
foo(myBar);
}
I do not expect the meaning of myBar to be changed by passing it to foo(). After all, I'm passing by value, so foo() only ever sees a copy of myBar right? Not when SomeType is aliased to mean some kind of pointer! Especially when that pointer acts as a reference to some kind of object whose value is basically the meaning of the pointer: I won't care that the pointer itself does not change (due to pass-by-value), I'm interested in whether the object changes or not (the object behind the pointer).
This applies both to C pointers and C++ smart pointers: If you hide the fact that they are pointers to your users, you will create confusion that is totally unnecessary. So, please, don't alias your pointers.
(I believe the habit of typedefing pointer types is just a misguided attempt to hide how many stars one has as a programmer http://wiki.c2.com/?ThreeStarProgrammer .)
This is a matter of style. You see this kind of code very frequently in the Windows header files. Though they tend to prefer the all upper case version instead of prefixing with a lower case p.
Personally I avoid this use of typedef. It's much clearer to have the user explicitly say they want a Foo* than PFoo. Typedef's are best suited these days for making STL readable :)
typedef stl::map<stl::wstring,CAdapt<CComPtr<IFoo>> NameToFooMap;
It (like so many answers) depends.
In C this is very common as you are trying to disguise that an object is a pointer. You are trying to imply that this is the object that all your functions manipulate (we know it is a pointer underneath but it represents the object you are manipulating).
MYDB db = MYDBcreateDB("Plop://djdjdjjdjd");
MYDBDoSomthingWithDB(db,5,6,7);
CallLocalFuc(db); // if db is not a pointer things could be complicated.
MYDBdestroyDB(db);
Underneath MYDB is probably a pointer at some object.
In C++ this is no longer required.
Mainly because we can pass things around by reference and the methods are incorporated into the class declaration.
MyDB db("Plop://djdjdjjdjd");
db.DoSomthingWithDB(5,6,7);
CallLocalFuc(db); // This time we can call be reference.
db.destroyDB(); // Or let the destructor handle it.
Discussion pitched assuming the language of interest is C. Ramifications for C++ have not been considered.
Using a a pointer typedef for an untagged structure
The question Size of a struct that is defined as a pointer raises an interesting side-light on using typedef for (structure) pointers.
Consider the tagless concrete (not opaque) structure type definition:
typedef struct { int field1; double field2; } *Information;
The details of the members are completely tangential to this discussion; all that matters is that this not an opaque type like typedef struct tag *tag; (and you can't define such opaque types via a typedef without a tag).
The question raised is 'how can you find the size of that structure'?
The short answer is 'only via a variable of the type'. There is no tag to use with sizeof(struct tag). You can't usefully write sizeof(*Information), for example, and sizeof(Information *) is the size of a pointer to the pointer type, not the size of the structure type.
In fact, if you want to allocate such a structure, you can't create one except via dynamic allocation (or surrogate techniques that mimic dynamic allocation). There is no way to create a local variable of the structure type whose pointers are called Information, nor is there a way to create a file scope (global or static) variable of the structure type, nor is there a way to embed such a structure (as opposed to a pointer to such a structure) into another structure or union type.
You can — must — write:
Information info = malloc(sizeof(*info));
Apart from the fact that the pointer is hidden in the typedef, this is good practice — if the type of info changes, the size allocation will remain accurate. But in this case, it is also the only way to get the size of the structure and to allocate the structure. And there's no other way to create an instance of the structure.
Is this harmful?
It depends on your goals.
This isn't an opaque type — the details of the structure must be defined when the pointer type is typedef'd.
It is a type that can only be used with dynamic memory allocation.
It is a type that is nameless. The pointer to the structure type has a name, but the structure type itself does not.
If you want to enforce dynamic allocation, this seems to be a way to do it.
On the whole, though, it is more likely to cause confusion and angst than enlightenment.
Summary
It is, in general, a bad idea to use typedef to define a pointer to a tagless stucture type.
No.
It will make your life miserable the moment you mix it with const
typedef foo *fooptr;
const fooptr bar1;
const foo *bar2
Are bar1 and bar2 the same type?
And yeah, I am just quoting Herb Sutter's Guru. Much truth did she speak. ;)
-- Edit --
Adding link to cited article.
http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835
Typedef is used to make code more readable, but making pointer as typedef will increase confusion. Better to avoid typedef pointers.
If you do this, you will be unable to create STL containers of const pSomeStruct since the compiler reads:
list<const pSomeStruct> structs;
as
list<SomeStruct * const> structs;
which is not a legal STL container since the elements are not assignable.
See this question .
Win32 API does this with just about every structure (if not all)
POINT => *LPPOINT
WNDCLASSEX => *LPWNDCLASSEX
RECT => *LPRECT
PRINT_INFO_2 => *LPPRINT_INFO_2
It's nice how it is consistent, but in my opinion it doesn't add any elegance.
The purpose with typedef is to hide the implementation details, but typedef-ing the pointer property hides too much and makes the code harder to read/understand.
So please do not do that.
If you want to hide implementation details (which often is a good thing to do), do not hide the pointer part. Take for instance at the prototype for the standard FILE interface:
FILE *fopen(const char *filename, const char *mode);
char *fgets(char *s, int size, FILE *stream);
here fopen returns a pointer to some structure FILE (which you do not know the implementation details for). Maybe FILE is not such a good example because in this case it could have worked with some pFILE type that hid the fact that it is a pointer.
pFILE fopen(const char *filename, const char *mode);
char *fgets(char *s, int size, pFILE stream);
However, that would only work because you never mess around with the content that is pointed to directly. The moment you typedef some pointer that you some places modify the code becomes very hard to read in my experience.
In general, no. In specific cases, yes.
There are a couple constructs that some other answers alluded to, and that is pointer-only types. There are a couple pointer-only type constructs that come to mind. If anyone thinks of more I'll add them to the list.
Opaque Types
These are types where the type's implementation is totally hidden to the user. You will typically see a structure typedef in the header, but no implementation of that struct. Because of that you cannot dereference values of these types. All functions that operate on this type take pointers to these types. It is appropriate to add the pointer to the typedef in these situations. You often see these called "handle" types.
typedef struct handle_ * handle;
handle get_handle(string s);
void mutate_handle(handle h, value v);
void release_handle(handle h);
Flexible Array Member Types
Another pointer-only type are types that are defined with flexible array members (FAMs). The last member in a FAM type is an unconstrained array. You are intended to dynamically allocate storage for these types and the flexible array is treated as inline with the structure. You can access fields in a FAM type, but cannot dereference the whole object. It is also appropriate to add the pointer to the typedef here.
typedef struct string {
size_t capacity;
size_t length;
char buffer[];
} * string;
string string_new(void);
size_t string_length(string s);
void string_append(string * s, char c);
void string_delete(string * s);
Some time ago, i'd have answered "no" to this question. Now, with the rise of smart pointers, pointers are not always defined with a star '*' anymore. So there is nothing obvious about a type being a pointer or not.
So now i'd say : it is fine to typedef pointers, as long as it is made very clear that it is a "pointer type". That means you have to use a prefix/suffix specifically for it. No, "p" is not a sufficient prefix, for instance. I'd probably go with "ptr".