calculate array index from pointers - c++

Me and some peers are working on a game (Rigs ofRods) and are trying to integrate OpenCL for physics calculation. At the same time we are trying to do some much needed cleanup of our data structures. I guess I should say we are trying to cleanup our data structures and be mindful of OpenCL requirements.
One of the problems with using open CL is the inability to use pointers as the memory space is different. From what little I know of OpenCL is copies all the data onto the GPU then performs the calculations, pointer values would be copied but the address would not correspond to the expected address.
The data in question is centralized in an array, when objects need to that data they use pointers to the object it needs, or stores an array index.
One solution to account for OpenCL is to use array index instead of pointers. This leads to hard coupling that could lead to headaches later on. As a solution I had the idea of calculating the array index based on the address of the start and the address of the current. This of course would only work with a continuous array.
I wrote a sample app to test this and it worked just fine, some people verified it on different platforms as well.
#include <iostream>
typedef struct beam_t
{
unsigned int item;
} beam_t;
#define GLOBAL_STATIC_ASSERT(expr, msg) \
extern char STATIC_ASSERTION__##msg[1]; \
extern char STATIC_ASSERTION__##msg[(expr)?1:2]
#ifdef __amd64
typedef unsigned long pointer_int;
#else
typedef unsigned int pointer_int;
#endif
GLOBAL_STATIC_ASSERT(sizeof(pointer_int) == sizeof(pointer_int*), integer_size);
#define MAX_BEAM 5
int main ()
{
beam_t beams[MAX_BEAM];
beam_t* beam_start = &beams[0];
beam_t* beam_ptr = NULL;
std::cout << "beams: " << &beams << "\n";
for( pointer_int i = 0; i < MAX_BEAM; ++i )
{
beam_ptr = &beams[i];
pointer_int diff = ((pointer_int)beam_ptr - (pointer_int)beam_start);
std::cout << "beams[" << i << "]: " << beam_ptr
<< "\t calculated index:" << diff / sizeof(beam_t)
<< "\n";
}
return 0;
}
I'm concerned that this more of a kludge than a bonified solution. I'm aware that this would not work no non-coninuous memory.
basically my questions are this:
What would be the pitfalls for using this approach in known coninuous memory?
How would you be able to tell it was continuous?
What approaches have people used when dealing with this type of issue?
Thanks, and my appologies if the formating is off, this is my first time posting a question.

This should give you the index of pointer relative to base:
pointer - base
Yes, it's that easy. =]
Use ptrdiff_t to store the result portably.

Although simple subtraction of pointers works, it's advisable to use std::distance. This will also work for iterator types that aren't pointers, and can be overloaded for custom types, too. The result, for pointers, will be a ptrdiff_t.

#define ARRAY_INDEX_FROM_ADDR(base, addr, type) \
(((uintptr_t)(addr)-(uintptr_t)(base))/sizeof(type))
If not using C99, use unsigned long long instead of uintptr_t

Related

Access struct variable value by pointer offset

I have a struct which looks like:
#pragma pack(1)
typedef struct WHEATHER_STRUCT {
uint8_t packetID; // Value 9
uint16_t packetSize; // Value 7
float cloudLayerAltitude; // Value 25000
} Wheather_Struct
This struct was initialized correctly. Due to design of an algorithm I need to read these three attributes values by a pointer offset. I thank about declare an array which have the size in bytes of these attributes. Just like:
int sizeOfStructAttributes = {1, 2, 4};
And finally to access these values do something like:
pointer = (*this->wheather_struct->packetID)
for (i=0; i<sizeof(sizeOfStructAttributes); i++)
cout << &pointer << ' ';
pointer = pointer + sizeOfStructAttributes[i];
Expected result:
9
7
25000
Could you help me please?
You have many problems with the code I will try to go through them all:
1- Your structure has padding values that depends on the architecture you are targeting maybe 3 or 7 bytes after the first member (packetID) it depends on the architecture and compiler.
2- You are initializing the pointer in a wrong way, it should be:
pointer = &(this->wheather_struct->packetID);
3- cout should be:
cout << *((datatype*)pointer) << ' ';
//datatype should be different in each loop iteration of course.
4- In case you are creating array of this strcutrue, I am not sure if you will face a problem of padding or not. It happens in very rare cases when you use different packing and padding due to mixing your code with other libraries that are compiled with different compiler directives or even uses #pragma to modify the behavior of the compiler during the compile time.
Finally I am sure there is no need at all to enumerate struct members with a pointer.
I encourage you to read about struct padding and packing, good place to start is this question on SO:
Structure padding and packing
One thing for sure, you won't be able to write these offsets manually. This is absolutely not a stable way of doing things, because your compiler might do optimizations such as aligning your struct members.
What you can do is this:
Wheather_Struct w;
long offsetsOfStructAttributes[3] = {0,
(char*)&w.packetSize - (char*)&w.packetID,
(char*)&w.cloudLayerAltitude - (char*)&w.packetID};
Notice that this is the byte difference in size.
Having told you how to do that, I have to say like people said in the comments, please find another way of doing this. This is not safe, unless you absolutely know what you're doing.
Your mistake is that you've assumed that the class has no padding between the members. But there must be padding in order to meet the alignment requirements of the members. Thus the offsets are not what you assume.
To get the offset of a class member, you can use the offsetof macro provided by the standard library. That said, without knowing what you need it for, I remain skeptical about it being appropriate. Note that offsetof works only if your class is a standard layout class. Otherwise the behaviour will be undefined. Your example WHEATHER_STRUCT is standard layout.
cout << &pointer << ' ';
Something like this can not possibly have the output that you expect. You take the address of the pointer, it cannot possibly give you the value of the pointed object that you wanted.
The way to get the pointed value is the indirection operator. But, indirection operator can only work correctly if the pointer is of correct type (float* for float members, uint16_t* for uint16_t members ...) but it cannot be of correct type since it has to be a pointer to a byte for the pointer arithmetic to work with the offsets.
Besides the offset, you also need to know the type of the variable in order to interpret the value. You could store the type in some structure. But you cannot cast the pointer to a type determined at runtime, so what you need is some runtime flow-structure such as a switch or a jump table for the conversion.
You'd better do not use pointer hack: one day underlying memory layout will be changed and your program may corrupt it.
Try to simulate metadata instead.
enum WheatherStructFields
{
wsfPacketID,
wsfPacketSize,
wsfCloudLayerAltitude,
wsfNone
};
typedef struct WHEATHER_STRUCT
{
uint8_t packetID;
uint16_t packetSize;
float cloudLayerAltitude;
void OutFieldValue(std::ostream& os, WheatherStructFields whatField)
{
switch (whatField)
{
case wsfPacketID:
os << (int)packetID;
break;
case wsfPacketSize:
os << packetSize;
break;
case wsfCloudLayerAltitude:
os << cloudLayerAltitude;
break;
default:
os << "Unsupported field: " << whatField;
}
}
} Wheather_Struct;
int main()
{
Wheather_Struct weather = { 9, 7, 25000 };
for (WheatherStructFields whatField = wsfPacketID; whatField < wsfNone;
whatField = (WheatherStructFields)((int)whatField + 1))
{
weather.OutFieldValue(std::cout, whatField);
std::cout << " ";
}
}
There are two problems with your approach:
Firstly, it requires you to get the sizes right. Use sizeof to do that. So your array would look like:
size_t sizeOfStructAttributes = {sizeof(wheather_struct::packet_id),
sizeof(wheather_struct::packet_size),
sizeof(wheather_struct::cloudLayerAltitude) };
The second (more serious) problem is that you don't allow for padding in your structure. Almost all compilers will (unless specially instructed), insert a padding byte between packet_id and packet_size so that everything is nicely aligned. Fortunately, there is a solution for that too - use the offsetof macro (defined in stddef.h):
size_t offsetOfStructAttributes = {offsetof(wheather_struct, packet_id),
offsetof(wheather_struct, packet_size),
offsetof(wheather_struct, cloudLayerAltitude) };
The code then becomes:
for (size_t offset: offsetsOfStructAttributes) {
pointer = &(this->wheather_struct->packetID) + offset
cout << pointer << ' ';
}
Actually: the above code fixes a third problem with your code: sizeof() returns the size in bytes, which is unlikely to be the element count.
Finally, your variables have a typo: meteorology is concerned with whether the weather will be fine or not. You have confused the two words and I am pretty sure you mean "weather".

Can you use a fixed size type and pointers together in the same union?

I'm investigating the possibility of defining a structure for a packet. I would like to set header variables in the packet and then set a pointer to the data part of the packet. My end goal is to be able to send this packet to a low level library that takes only a uint8_t*. I created this quick program to test the feasibility and it does not seem to work.
#include <iostream>
#include <cstdint>
#include <stdlib.h>
typedef union {
struct {
uint8_t header;
uint8_t* data;
};
uint8_t* packet;
} sometype;
int main() {
sometype s;
s.header = 3;
s.data = (uint8_t *) malloc(sizeof(uint8_t) * 2);
s.data[0] = 1;
s.data[1] = 2;
for (unsigned int i = 0; i < 3; i++) {
std::cout << s.packet[i] << std::endl;
}
std::cout << std::endl;
std::cout << s.header << std::endl;
std::cout << s.data[0] << std::endl;
std::cout << s.data[1] << std::endl;
}
My output is
�
�
�
Which makes me realize I have some type of error in my code (I've never worked with union before). However, when I debug the program I can see the data in the union. Looking at the packet, I can see that this method does not appear to be working. The data in the packet is not 3, 1, 2. It is 300, 221, 020 instead.
(gdb) print s
$1 = {{header = 3 '\003', data = 0x613c20 "\001\002"}, packet = 0x400903 <main()+125> "\300\211ƿ`\020`"}
Is this method that I am attempting valid? From google searches I saw someone say you can use whatever datatypes you want. Do I have to pack the structure using a pragma to get this to work or is this method not feasible?
The unusual output is because you attempt to use << to print a uint8_t.
Usually (although the C++ standard doesn't specify this), uint8_t triggers the character overload of <<, so you print out the glyph corresponding to that character code, instead of the integer. To avoid this hiccup you could do std::cout << static_cast<int>(s.header); etc.
Note that in Standard C++ it is not permitted to write one member of a union and then read a different member, i.e. you may only read the same member that was last written. The technique you are trying to use is called union aliasing and is not allowed in Standard C++, although compilers may seem to support it as an extension.
However, even if you're on a compiler that does offer union aliasing, you still won't be able to do s.packet[i] with your current struct definition. This is because packet overlaps with header and data. The byte value of header should not be a part of the address packet is pointing to, but your code treats it like it is.
I guess you mentally had a model of a single pointer and you can interpret the memory being pointed to by the pointer as either a char array, or as a char followed by a char array. But your code doesn't reflect that (and in fact you can't do that at all, unless the lengths of the arrays are known at compile-time).
Since header and data[0] are not in contiguous memory, there's no way you are going to be able to have a single pointer that points to some fictitious memory block in which those two bytes are adjacent. I would recommend giving up on this entire line of enquiry; just have a single memory block, and you can make functions that access particular parts of it.
Yes, you have to use #pragma pack(1) to get the behavior most engineers expect. And yes, this is how most communication low level software works.
Otherwise, compilers tend to align each element to its data size for performance and compatibility reasons.
There is enormous cross-compatibility with #pragma pack() across compilers. See this for gcc.

How many indirection level I can have in c++? [duplicate]

How many pointers (*) are allowed in a single variable?
Let's consider the following example.
int a = 10;
int *p = &a;
Similarly we can have
int **q = &p;
int ***r = &q;
and so on.
For example,
int ****************zz;
The C standard specifies the lower limit:
5.2.4.1 Translation limits
276 The implementation shall be able to translate and execute at least one program that contains at least one instance of every one of the following limits: [...]
279 — 12 pointer, array, and function declarators (in any combinations) modifying an
arithmetic, structure, union, or void type in a declaration
The upper limit is implementation specific.
Actually, C programs commonly make use of infinite pointer indirection. One or two static levels are common. Triple indirection is rare. But infinite is very common.
Infinite pointer indirection is achieved with the help of a struct, of course, not with a direct declarator, which would be impossible. And a struct is needed so that you can include other data in this structure at the different levels where this can terminate.
struct list { struct list *next; ... };
now you can have list->next->next->next->...->next. This is really just multiple pointer indirections: *(*(..(*(*(*list).next).next).next...).next).next. And the .next is basically a noop when it's the first member of the structure, so we can imagine this as ***..***ptr.
There is really no limit on this because the links can be traversed with a loop rather than a giant expression like this, and moreover, the structure can easily be made circular.
Thus, in other words, linked lists may be the ultimate example of adding another level of indirection to solve a problem, since you're doing it dynamically with every push operation. :)
Theoretically:
You can have as many levels of indirections as you want.
Practically:
Of course, nothing that consumes memory can be indefinite, there will be limitations due to resources available on the host environment. So practically there is a maximum limit to what an implementation can support and the implementation shall document it appropriately. So in all such artifacts, the standard does not specify the maximum limit, but it does specify the lower limits.
Here's the reference:
C99 Standard 5.2.4.1 Translation limits:
— 12 pointer, array, and function declarators (in any combinations) modifying an
arithmetic, structure, union, or void type in a declaration.
This specifies the lower limit that every implementation must support. Note that in a footenote the standard further says:
18) Implementations should avoid imposing fixed translation limits whenever possible.
As people have said, no limit "in theory". However, out of interest I ran this with g++ 4.1.2, and it worked with size up to 20,000. Compile was pretty slow though, so I didn't try higher. So I'd guess g++ doesn't impose any limit either. (Try setting size = 10 and looking in ptr.cpp if it's not immediately obvious.)
g++ create.cpp -o create ; ./create > ptr.cpp ; g++ ptr.cpp -o ptr ; ./ptr
create.cpp
#include <iostream>
int main()
{
const int size = 200;
std::cout << "#include <iostream>\n\n";
std::cout << "int main()\n{\n";
std::cout << " int i0 = " << size << ";";
for (int i = 1; i < size; ++i)
{
std::cout << " int ";
for (int j = 0; j < i; ++j) std::cout << "*";
std::cout << " i" << i << " = &i" << i-1 << ";\n";
}
std::cout << " std::cout << ";
for (int i = 1; i < size; ++i) std::cout << "*";
std::cout << "i" << size-1 << " << \"\\n\";\n";
std::cout << " return 0;\n}\n";
return 0;
}
Sounds fun to check.
Visual Studio 2010 (on Windows 7), you can have 1011 levels before getting this error:
fatal error C1026: parser stack overflow, program too complex
gcc (Ubuntu), 100k+ * without a crash ! I guess the hardware is the limit here.
(tested with just a variable declaration)
There is no limit, check example at Pointers :: C Interview Questions and Answers.
The answer depends on what you mean by "levels of pointers." If you mean "How many levels of indirection can you have in a single declaration?" the answer is "At least 12."
int i = 0;
int *ip01 = & i;
int **ip02 = & ip01;
int ***ip03 = & ip02;
int ****ip04 = & ip03;
int *****ip05 = & ip04;
int ******ip06 = & ip05;
int *******ip07 = & ip06;
int ********ip08 = & ip07;
int *********ip09 = & ip08;
int **********ip10 = & ip09;
int ***********ip11 = & ip10;
int ************ip12 = & ip11;
************ip12 = 1; /* i = 1 */
If you mean "How many levels of pointer can you use before the program gets hard to read," that's a matter of taste, but there is a limit. Having two levels of indirection (a pointer to a pointer to something) is common. Any more than that gets a bit harder to think about easily; don't do it unless the alternative would be worse.
If you mean "How many levels of pointer indirection can you have at runtime," there's no limit. This point is particularly important for circular lists, in which each node points to the next. Your program can follow the pointers forever.
It's actually even funnier with pointer to functions.
#include <cstdio>
typedef void (*FuncType)();
static void Print() { std::printf("%s", "Hello, World!\n"); }
int main() {
FuncType const ft = &Print;
ft();
(*ft)();
(**ft)();
/* ... */
}
As illustrated here this gives:
Hello, World!
Hello, World!
Hello, World!
And it does not involve any runtime overhead, so you can probably stack them as much as you want... until your compiler chokes on the file.
There is no limit. A pointer is a chunk of memory whose contents are an address.
As you said
int a = 10;
int *p = &a;
A pointer to a pointer is also a variable which contains an address of another pointer.
int **q = &p;
Here q is pointer to pointer holding the address of p which is already holding the address of a.
There is nothing particularly special about a pointer to a pointer. So there is no limit on chain of poniters which are holding the address of another pointer.
ie.
int **************************************************************************z;
is allowed.
Every C++ developer should have heard of the (in)famous Three star programmer.
And there really seems to be some magic "pointer barrier" that has to be camouflaged.
Quote from C2:
Three Star Programmer
A rating system for C-programmers. The more indirect your pointers are (i.e. the more "*" before your variables), the higher your reputation will be. No-star C-programmers are virtually non-existent, as virtually all non-trivial programs require use of pointers. Most are one-star programmers. In the old times (well, I'm young, so these look like old times to me at least), one would occasionally find a piece of code done by a three-star programmer and shiver with awe.
Some people even claimed they'd seen three-star code with function pointers involved, on more than one level of indirection. Sounded as real as UFOs to me.
Note that there are two possible questions here: how many levels of pointer indirection we can achieve in a C type, and how many levels of pointer indirection we can stuff into a single declarator.
The C standard allows a maximum to be imposed on the former (and gives a minimum value for that). But that can be circumvented via multiple typedef declarations:
typedef int *type0;
typedef type0 *type1;
typedef type1 *type2; /* etc */
So ultimately, this is an implementation issue connected to the idea of how big/complex can a C program be made before it is rejected, which is very compiler specific.
I'd like to point out that producing a type with an arbitrary number of *'s is something that can happen with template metaprogramming. I forget what I was doing exactly, but it was suggested that I could produce new distinct types that have some kind of meta maneuvering between them by using recursive T* types.
Template Metaprogramming is a slow descent into madness, so it is not necessary to make excuses when generating a type with several thousand level of indirection. It's just a handy way to map peano integers, for example, onto template expansion as a functional language.
Rule 17.5 of the 2004 MISRA C standard prohibits more than 2 levels of pointer indirection.
There isn't such a thing like real limit but limit exists. All pointers are variables that are usually storing in stack not heap. Stack is usually small (it is possible to change its size during some linking). So lets say you have 4MB stack, what is quite normal size. And lets say we have pointer which is 4 bytes size (pointer sizes are not the same depending on architecture, target and compiler settings).
In this case 4 MB / 4 b = 1024 so possible maximum number would be 1048576, but we shouldn't ignore the fact that some other stuff is in stack.
However some compilers may have maximum number of pointer chain, but the limit is stack size. So if you increase stack size during linking with infinity and have machine with infinity memory which runs OS which handles that memory so you will have unlimited pointer chain.
If you use int *ptr = new int; and put your pointer into heap, that is not so usual way limit would be heap size, not stack.
EDIT Just realize that infinity / 2 = infinity. If machine has more memory so the pointer size increases. So if memory is infinity and size of pointer is infinity, so it is bad news... :)
It depends on the place where you store pointers. If they are in stack you have quite low limit. If you store it in heap, you limit is much much much higher.
Look at this program:
#include <iostream>
const int CBlockSize = 1048576;
int main()
{
int number = 0;
int** ptr = new int*[CBlockSize];
ptr[0] = &number;
for (int i = 1; i < CBlockSize; ++i)
ptr[i] = reinterpret_cast<int *> (&ptr[i - 1]);
for (int i = CBlockSize-1; i >= 0; --i)
std::cout << i << " " << (int)ptr[i] << "->" << *ptr[i] << std::endl;
return 0;
}
It creates 1M pointers and at the shows what point to what it is easy to notice what the chain goes to the first variable number.
BTW. It uses 92K of RAM so just imagine how deep you can go.

How many levels of pointers can we have?

How many pointers (*) are allowed in a single variable?
Let's consider the following example.
int a = 10;
int *p = &a;
Similarly we can have
int **q = &p;
int ***r = &q;
and so on.
For example,
int ****************zz;
The C standard specifies the lower limit:
5.2.4.1 Translation limits
276 The implementation shall be able to translate and execute at least one program that contains at least one instance of every one of the following limits: [...]
279 — 12 pointer, array, and function declarators (in any combinations) modifying an
arithmetic, structure, union, or void type in a declaration
The upper limit is implementation specific.
Actually, C programs commonly make use of infinite pointer indirection. One or two static levels are common. Triple indirection is rare. But infinite is very common.
Infinite pointer indirection is achieved with the help of a struct, of course, not with a direct declarator, which would be impossible. And a struct is needed so that you can include other data in this structure at the different levels where this can terminate.
struct list { struct list *next; ... };
now you can have list->next->next->next->...->next. This is really just multiple pointer indirections: *(*(..(*(*(*list).next).next).next...).next).next. And the .next is basically a noop when it's the first member of the structure, so we can imagine this as ***..***ptr.
There is really no limit on this because the links can be traversed with a loop rather than a giant expression like this, and moreover, the structure can easily be made circular.
Thus, in other words, linked lists may be the ultimate example of adding another level of indirection to solve a problem, since you're doing it dynamically with every push operation. :)
Theoretically:
You can have as many levels of indirections as you want.
Practically:
Of course, nothing that consumes memory can be indefinite, there will be limitations due to resources available on the host environment. So practically there is a maximum limit to what an implementation can support and the implementation shall document it appropriately. So in all such artifacts, the standard does not specify the maximum limit, but it does specify the lower limits.
Here's the reference:
C99 Standard 5.2.4.1 Translation limits:
— 12 pointer, array, and function declarators (in any combinations) modifying an
arithmetic, structure, union, or void type in a declaration.
This specifies the lower limit that every implementation must support. Note that in a footenote the standard further says:
18) Implementations should avoid imposing fixed translation limits whenever possible.
As people have said, no limit "in theory". However, out of interest I ran this with g++ 4.1.2, and it worked with size up to 20,000. Compile was pretty slow though, so I didn't try higher. So I'd guess g++ doesn't impose any limit either. (Try setting size = 10 and looking in ptr.cpp if it's not immediately obvious.)
g++ create.cpp -o create ; ./create > ptr.cpp ; g++ ptr.cpp -o ptr ; ./ptr
create.cpp
#include <iostream>
int main()
{
const int size = 200;
std::cout << "#include <iostream>\n\n";
std::cout << "int main()\n{\n";
std::cout << " int i0 = " << size << ";";
for (int i = 1; i < size; ++i)
{
std::cout << " int ";
for (int j = 0; j < i; ++j) std::cout << "*";
std::cout << " i" << i << " = &i" << i-1 << ";\n";
}
std::cout << " std::cout << ";
for (int i = 1; i < size; ++i) std::cout << "*";
std::cout << "i" << size-1 << " << \"\\n\";\n";
std::cout << " return 0;\n}\n";
return 0;
}
Sounds fun to check.
Visual Studio 2010 (on Windows 7), you can have 1011 levels before getting this error:
fatal error C1026: parser stack overflow, program too complex
gcc (Ubuntu), 100k+ * without a crash ! I guess the hardware is the limit here.
(tested with just a variable declaration)
There is no limit, check example at Pointers :: C Interview Questions and Answers.
The answer depends on what you mean by "levels of pointers." If you mean "How many levels of indirection can you have in a single declaration?" the answer is "At least 12."
int i = 0;
int *ip01 = & i;
int **ip02 = & ip01;
int ***ip03 = & ip02;
int ****ip04 = & ip03;
int *****ip05 = & ip04;
int ******ip06 = & ip05;
int *******ip07 = & ip06;
int ********ip08 = & ip07;
int *********ip09 = & ip08;
int **********ip10 = & ip09;
int ***********ip11 = & ip10;
int ************ip12 = & ip11;
************ip12 = 1; /* i = 1 */
If you mean "How many levels of pointer can you use before the program gets hard to read," that's a matter of taste, but there is a limit. Having two levels of indirection (a pointer to a pointer to something) is common. Any more than that gets a bit harder to think about easily; don't do it unless the alternative would be worse.
If you mean "How many levels of pointer indirection can you have at runtime," there's no limit. This point is particularly important for circular lists, in which each node points to the next. Your program can follow the pointers forever.
It's actually even funnier with pointer to functions.
#include <cstdio>
typedef void (*FuncType)();
static void Print() { std::printf("%s", "Hello, World!\n"); }
int main() {
FuncType const ft = &Print;
ft();
(*ft)();
(**ft)();
/* ... */
}
As illustrated here this gives:
Hello, World!
Hello, World!
Hello, World!
And it does not involve any runtime overhead, so you can probably stack them as much as you want... until your compiler chokes on the file.
There is no limit. A pointer is a chunk of memory whose contents are an address.
As you said
int a = 10;
int *p = &a;
A pointer to a pointer is also a variable which contains an address of another pointer.
int **q = &p;
Here q is pointer to pointer holding the address of p which is already holding the address of a.
There is nothing particularly special about a pointer to a pointer. So there is no limit on chain of poniters which are holding the address of another pointer.
ie.
int **************************************************************************z;
is allowed.
Every C++ developer should have heard of the (in)famous Three star programmer.
And there really seems to be some magic "pointer barrier" that has to be camouflaged.
Quote from C2:
Three Star Programmer
A rating system for C-programmers. The more indirect your pointers are (i.e. the more "*" before your variables), the higher your reputation will be. No-star C-programmers are virtually non-existent, as virtually all non-trivial programs require use of pointers. Most are one-star programmers. In the old times (well, I'm young, so these look like old times to me at least), one would occasionally find a piece of code done by a three-star programmer and shiver with awe.
Some people even claimed they'd seen three-star code with function pointers involved, on more than one level of indirection. Sounded as real as UFOs to me.
Note that there are two possible questions here: how many levels of pointer indirection we can achieve in a C type, and how many levels of pointer indirection we can stuff into a single declarator.
The C standard allows a maximum to be imposed on the former (and gives a minimum value for that). But that can be circumvented via multiple typedef declarations:
typedef int *type0;
typedef type0 *type1;
typedef type1 *type2; /* etc */
So ultimately, this is an implementation issue connected to the idea of how big/complex can a C program be made before it is rejected, which is very compiler specific.
I'd like to point out that producing a type with an arbitrary number of *'s is something that can happen with template metaprogramming. I forget what I was doing exactly, but it was suggested that I could produce new distinct types that have some kind of meta maneuvering between them by using recursive T* types.
Template Metaprogramming is a slow descent into madness, so it is not necessary to make excuses when generating a type with several thousand level of indirection. It's just a handy way to map peano integers, for example, onto template expansion as a functional language.
Rule 17.5 of the 2004 MISRA C standard prohibits more than 2 levels of pointer indirection.
There isn't such a thing like real limit but limit exists. All pointers are variables that are usually storing in stack not heap. Stack is usually small (it is possible to change its size during some linking). So lets say you have 4MB stack, what is quite normal size. And lets say we have pointer which is 4 bytes size (pointer sizes are not the same depending on architecture, target and compiler settings).
In this case 4 MB / 4 b = 1024 so possible maximum number would be 1048576, but we shouldn't ignore the fact that some other stuff is in stack.
However some compilers may have maximum number of pointer chain, but the limit is stack size. So if you increase stack size during linking with infinity and have machine with infinity memory which runs OS which handles that memory so you will have unlimited pointer chain.
If you use int *ptr = new int; and put your pointer into heap, that is not so usual way limit would be heap size, not stack.
EDIT Just realize that infinity / 2 = infinity. If machine has more memory so the pointer size increases. So if memory is infinity and size of pointer is infinity, so it is bad news... :)
It depends on the place where you store pointers. If they are in stack you have quite low limit. If you store it in heap, you limit is much much much higher.
Look at this program:
#include <iostream>
const int CBlockSize = 1048576;
int main()
{
int number = 0;
int** ptr = new int*[CBlockSize];
ptr[0] = &number;
for (int i = 1; i < CBlockSize; ++i)
ptr[i] = reinterpret_cast<int *> (&ptr[i - 1]);
for (int i = CBlockSize-1; i >= 0; --i)
std::cout << i << " " << (int)ptr[i] << "->" << *ptr[i] << std::endl;
return 0;
}
It creates 1M pointers and at the shows what point to what it is easy to notice what the chain goes to the first variable number.
BTW. It uses 92K of RAM so just imagine how deep you can go.

Macro to both get (void*) address of item and length, for arrays and structs

I'm trying to design a macro to produce several related data structures related to things that need initialization. The code has to compile under both C and C++. The goal is to have something like:
MUNGE_THING(struct1);
MUNGE_THING(array1);
turn into something equivalent to
munge_thing((void*)&struct1, sizeof(struct1));
munge_thing((void*)array1, sizeof(array1));
Is there any syntactic stuff I can surround the macro argument with so that it will handle both arrays and structure correctly both when taking the address and when getting the size? The most likely context will be in the constant declaration of an initialization list.
If that isn't possible, and it's necessary to use separate macros for structures and arrays, what would be the best syntax to ensure that passing something incorrectly will yield a compile error rather than bogus code?
In "old" C, prepending an array address with "&" would yield a warning, but not prevent compilation. In C++, it seems to yield the address of a location which stores the address of the array.
The MUNGE_THING macros are going to be within another macro that will be invoked multiple times with different definitions of MUNGE_THING, so having separate macros for arrays and structs would be irksome. The best approach I can figure would be to give MUNGE_THING an extra argument for the "optional" ampersand, but that somehow seems ugly.
If the array is in fact an array (which seems to be required for the sizeof to work), why don't you just use the simple macro:
#define MUNGE_THING( x ) munge_thing((void*)&(x), sizeof(x))
That should work both for arrays and structs:
int array[10];
assert( (void*)array == (void*)&array );
You have tagged the question as both C and C++, in C++ you can use templates and avoid the macros all together.
I'm not sure what problem you are having with &array1. This C++ worked exactly as expected (all values the same)
int main(int argc, char* argv[])
{
int array1[10];
printf("%x %x\n", array1, &array1);
cout << array1 << " " << &array1 << endl;
void* ptr1 = array1;
void* ptr2 = &array1;
printf("%x %x\n", ptr1, ptr2);
cout << ptr1 << " " << ptr2 << endl;
return 0;
}
Okay, I see my confusion. In C++, the type of &array is not compatible with the type of the array, and as the linked discussion notes, (&array)+1 is not the same as (array+1), but casting the unsubscripted pointers does in fact yield the proper results. The distinctions between arrays and pointers in C are very confusing. Thanks for the assistance.