C++ Struct pointer question - c++

This is probably simple, but im trying to try and understand pointers better.
Lets say I have a struct
struct Person{
char Name[20];
char ID[15];
char Address[50];
char Number[15];
};
and lets say I have a bunch of these stored in memory like one after the other.
so now i declare a new pointer to the struct.
struct Person *ptr;
Will this Pointer start at the FIRST entry? (aka the first "Name") and when I iterate it (aka ptr++) will it go to the next STRUCT or the next "entry" aka like name-->ID--->Address
So lets say Im on the first entry for example and the data is:
Jason Adams
111222333
111 Fake Drive
55555551000
and the second entry is
Matt Johns
111555333
555 Derp lane
1000022434
now I iterate the ptr (ptr++) will the ptr point to second struct (the one with matt johns) or will it point to Jason Adams "ID"
I hope this makes sense?

It will point to the second struct. The pointer will be advanced by sizeof(Person).

As John mentioned, it will be advanced by the size of itself - aka sizeof(Person).
Pointer manipulation is fun however, and you can do things like cast the pointer to a different type. Once you do that, pointer arithmetic will advance by the underlying size of the type. Commonly you'll see pointers casted to (byte *) or (unsigned char *) to allow individual byte access to the underlying data.

First of all, you must allocate memory for your pointer ptr before using it.
auto_ptr<Person> ptr(new Person); //auto_ptr for automatic freeing
After that, you can try below code.
strcpy(ptr->ID, "100"); //For illustraction
int offset = ptr->ID - ptr->Name; //Get offset of ID member
char *pID = ((char *)ptr.get())+ offset;
//Typecast to char pointer and increment by offset to get to ID field
cout<<pID; //Now pId can be used to access ID.
You asked how to access ID attribute by incrementing ptr.
As shown above, you can access ID member of structure.

Related

Why does my pointer to a char only get the first character in it?

I initialized a char and a pointer, and then point it to the char. But I found that only the first character in the char was passed into the pointer. How could this be? Appreciate any advice!
char p[]="This is a long char.";
std::cout<<sizeof(p)<<"\n";
char *ptr=p;
std::cout<<*ptr<<"\n";
Got:
21
T
Program ended with exit code: 0
When checking the value of variables I noticed that:
ptr=(char *) "This is a long char."
*ptr=(char) 'T'
Why is the ptr holding the whole char but the content in it is only the first character? Isn't this the opposite of what we call a pointer? Got really confused...
When you said:
std::cout<<*ptr...
you dereferenced ptr, which gives you the (first) character that ptr is pointing to.
flyingCode's answer shows you how to print the entire string.
In C++, an array is just like multiple variables grouped together, so they each have a memory address, but they are one after another.
So, the pointer is pointing at the address of the first element, and the other elements are in the adresses right after that in order.
When you use the * operator on a pointer, it references the contents of the memory address the pointer is pointing to.
If you wanted to access another element of the array using this, you would use *(ptr + 5) to offset the memory address.
When you use the variable name alone, the language just does the offset for you and gets all the contents of the array. The pointer doesn't know the length of the array, but it can find the end of it, because char arrays always end with a null character (\0).
ran your code in repl and changing it to the code below worked :D
char p[]="This is a long char.";
std::cout<<sizeof(p)<<"\n";
char *ptr=p;
std::cout<<ptr<<"\n"; //notice no *
I recommend you use std::string rather than c-strings unless you have a specific need for them :)

Trying to make a Pointer to a dynamically allocated char array

I'm trying to allocate a char array on the heap and then make a pointer to it:
char * head;
char * coolArray = new char[5];
This should allocate 5 bits on the heap with chars correct?
head = &coolArray;
Not able to do this ^ due to &coolArray being a char **?
I am able to fix it by doing:
head = *&coolArray;
But I'm not sure why this works.
Can anyone explain this concept of pointing to something that is on the heap?
First of all, before anything else, use std::string to handle character strings.
Except for purposes of learning, generally don't use raw arrays, pointers and new expressions.
” This should allocate 5 bits
No, it allocates 5 bytes.
A byte is the smallest addressable unit of memory in C++. Types char, unsigned char and signed char, as well as with C++17 and later std::byte, are all guaranteed byte size. The number of bits per byte is usually 8, and is at least 8, but can be larger, and is given by the CHAR_BIT constant from the <limits.h> header.
head = &coolArray;
Just write
head = coolArray;
This assigns a pointer value (the one in the pointer variable coolArray) to a pointer variable.
head = *&coolArray;
Generally, for any variable v, the expression &v gives you a pointer to that variable.
Dereferencing that pointer, *&v, denotes the same variable. So you could just write v instead.
The "heap" and memory allocations are red herrings.
&coolArray is "where coolArray is".
*p is "the thing that is at the location p".
*&x is "the thing that is where coolArray is", which is coolArray.
This works pretty much like the real world – "the person who lives in the house where Jack lives" is Jack himself, right?
Incidentally, you could also write head = coolArray;.

Array of char pointers

I am looking at some code I did not write and wanted help to understand an element of it. The code stores character arrays, creates pointers to these arrays (assigning the pointers the arrays addresses). It looks like it then creates an array to store these characters pointers addresses and I just wanted some clarification on what I am looking at exactly. I also am confused about the use of the double (**) when creating the array.
I have included a stripped down and simplified example of what I am looking at below.
char eLangAr[20] = "English";
char fLangAr[20] = "French";
char gLangAr[20] = "German";
char* eLangPtr = eLangAr;
char* fLangPtr = fLangAr;
char* gLangPtr = gLangAr;
char **langStrings [3]=
{
&eLangPtr,
&fLangPtr,
&gLangPtr
};
When using the array they pass it as an argument to a function.
menu (*langStrings[0]);
So the idea is that the character array value "English" is passed to the function but I'm having trouble seeing how. They pass the menu function a copy of the value stored in the langStrings function at location 0, which would be the address of eLandPtr? If someone could explain the process in English so I could get my head around it that would be great. It might be just because it has been a long day but its just not straight in my head at all.
You are correct that langStrings contains pointers to pointers of array of characters. So each langString[i] points to a pointer. That pointer points to an array. That array contains the name of a language.
As others point out, it looks a bit clumsy. I'll elaborate:
char eLangAr[20] = "English"; is an array of 20 chars and the name "English" is copied to it. I don't expect that variable eLangAr will ever contain something else than this language name, so there is no need to use an array; a constant would be sufficient.
char **langStrings [3]= ... Here, it would be sufficient to have just one indirection (one *) as there seems no need to ever have the pointer point to anything else (randomly shuffle languages?).
in conclusion, just having the following should be sufficient:
const char *langStrings [3]=
{
"English",
"French",
"German"
};
(Note the const as the strings are now read-only constants/literals.)
What the given code could be useful for is when these language names must be spelled differently in different languages. So
"English",
"French",
"German" become "Engels", "Frans", "Duits". However, then there still is one level of indirection too many and the following would be sufficient:
char *langStrings [3]=
{
aLangArr,
fLangAr,
gLangAr
};
Ok, here goes.
The **ptrToptr notation means a pointer to a pointer. The easiest way to think on that is as a 2D matrix - dereferencing one pointer resolves the whole matrix to just one line in the matrix. Dereferencing the second pointer after that will give one value in the matrix.
This declaration:
char eLangAr[20] = "English";
Declares an array of length 20, type char and it contains the characters 'E', 'n', 'g', 'l', 'i', 's', 'h' '\0'
so it is (probably) null terminated but not full (there are some empty characters at the end). You can set a pointer to the start of it using:
char* englishPtr = &eLangAr[0]
And if you dereference englishPtr, it'll give the value 'E'.
This pointer:
char* eLangPtr = eLangAr;
points to the array itself (not necessarily the first value).
If you look at
*langStrings[0]
You'll see it means the contents (the dereferencing *) of the pointer in langStrings[0]. langStrings[0] is the address of eLangPtr, so dereferencing it gives eLangPtr. And eLangPtr is the pointer to the array eLangAr (which contains "English").
I guess the function wants to be able to write to eLangAr, so make it point to a different word without overwriting "English" itself. It could just over-write the characters itself in memory, but I guess it wants to keep those words safe.
** represents pointer to pointer. It's used when you have to store pointer for another pointer.
Value of eLangPtr will be pointer to eLangAr which will has the value "English"
Here:
char eLangAr[20] = "English";
an array is created. It has capacity of 20 chars and contains 8 characters - word "English" and terminating NULL character. Since it's an array, it can be used in a context where pointer is expected - thanks to array-to-pointer decay, which will construct a pointer to the first element of an array. This is done here:
char* eLangPtr = eLangAr;
Which is the same as:
char* eLangPtr = &eLangAr[0]; // explicitly get the address of the first element
Now, while char* represents pointer to a character (which means it points to a single char), the char** represents a pointer to the char* pointer.
The difference:
char text[] = "Text";
char* chPointer = &ch[0];
char** chPointerPointer = &chPointer; // get the address of the pointer
std::cout << chPointer; // prints the address of 'text' array
std::cout << *chPointer; // prints the first character in 'text' array ('T')
std::cout << chPointerPointer; // prints the address of 'chPointer'
std::cout << *chPointerPointer; // prints the value of 'chPointer' which is the address of 'text' array
std::cout << *(*chPointerPointer); // prints the first character in 'text' array ('T')
As you can see, it is simply an additional level of indirection.
Pointers to pointers are used for the same reason "first-level" pointers are used - they allow you to take the address of a pointer and pass it to a function which may write something to it, modifying the content of the original pointer.
In this case it is not needed, this would be sufficient:
const char *langStrings [3]=
{
eLangPtr,
fLangPtr,
gLangPtr
};
And then:
menu (langStrings[0]);

Reading a cubin structure from a pointer

I am trying to read the contents a c++ structure(in windows) which has the following format
typedef struct __cudaFatCudaBinaryRec {
unsigned long magic;
unsigned long version;
unsigned long gpuInfoVersion;
char* key;
char* ident;
char* usageMode;
__cudaFatPtxEntry *ptx;
__cudaFatCubinEntry *cubin;
__cudaFatDebugEntry *debug;
void* debugInfo;
unsigned int flags;
__cudaFatSymbol *exported;
__cudaFatSymbol *imported;
struct __cudaFatCudaBinaryRec *dependends;
unsigned int characteristic;
__cudaFatElfEntry *elf;
} __cudaFatCudaBinary;
I have a pointer to this structure (void *ptr)
Now I am looking to read the contents of this structure.
__cudaFatCudaBinary *ptr2=(cudaFatCudaBinary*)ptr;
cout<<ptr->magic;//This works fine
cout<<ptr->key;//This crashes my program..bad pointer results..why?
The above is consistent with all non pointer and pointer members. What am I doing wrong?
ADDED:
ok let me elaborate on the problem. Yes, the address pointed to by "key" is NULL and so it is for all the pointer members. But I know for sure the structure has valid data. It is used by a driver function to generate a handle and it executes fine. All I need is to copy the entire image of the structure and store it in a text file. How would I do it? Why are some of the member fields null? I am thinking of a brute force way to find the address limits of the structure. But the values themselves seem to be invalid when read and I don't know how to go about it!
ADDED 2
Memory Dump of the structure
Thanks !
cout << ptr->key will print as a 0-terminated string whatever key points to, not the pointer itself. If key is NULL or otherwise invalid then this will be undefined behaviour. (In this case a "crash")
If you just want to print the pointer itself make sure you print it as a void* pointer:
cout << static_cast<void*>(ptr->key);
As of CUDA 4.0, the format of this struct drastically changed. The value of magic is now different and gpuInfoVersion is now a pointer to a struct that contains the actual data. For more information, you might want to read this thread.

Difference between using character pointers and character arrays

Basic question.
char new_str[]="";
char * newstr;
If I have to concatenate some data into it or use string functions like strcat/substr/strcpy, what's the difference between the two?
I understand I have to allocate memory to the char * approach (Line #2). I'm not really sure how though.
And const char * and string literals are the same?
I need to know more on this. Can someone point to some nice exhaustive content/material?
The excellent source to clear up the confusion is Peter Van der Linden, Expert C Programming, Deep C secrets - that arrays and pointers are not the same is how they are addressed in memory.
With an array, char new_str[]; the compiler has given the new_str a memory address that is known at both compilation and runtime, e.g. 0x1234, hence the indexing of the new_str is simple by using []. For example new_str[4], at runtime, the code picks the address of where new_str resides in, e.g. 0x1234 (that is the address in physical memory). by adding the index specifier [4] to it, 0x1234 + 0x4, the value can then be retrieved.
Whereas, with a pointer, the compiler gives the symbol char *newstr an address e.g. 0x9876, but at runtime, that address used, is an indirect addressing scheme. Supposing that newstr was malloc'd newstr = malloc(10);, what is happening is that, everytime a reference in the code is made to use newstr, since the address of newstr is known by the compiler i.e. 0x9876, but what is newstr pointing to is variable. At runtime, the code fetches data from physical memory 0x9876 (i.e. newstr), but at that address is, another memory address (since we malloc'd it), e.g 0x8765 it is here, the code fetches the data from that memory address that malloc assigned to newstr, i.e. 0x8765.
The char new_str[] and char *newstr are used interchangeably, since an zeroth element index of the array decays into a pointer and that explains why you could newstr[5] or *(newstr + 5) Notice how the pointer expression is used even though we have declared char *newstr, hence *(new_str + 1) = *newstr; OR *(new_str + 1) = newstr[1];
In summary, the real difference between the two is how they are accessed in memory.
Get the book and read it and live it and breathe it. Its a brilliant book! :)
Please go through this article below:
Also see in case of array of char like in your case, char new_str[] then the new_str will always point to the base of the array. The pointer in itself can't be incremented. Yes you can use subscripts to access the next char in array eg: new_str[3];
But in case of pointer to char, the pointer can be incremented new_str++ to fetch you the next character in the array.
Also I would suggest this article for more clarity.
This is a character array:
char buf [1000];
So, for example, this makes no sense:
buf = &some_other_buf;
This is because buf, though it has characteristics of type pointer, it is already pointing to the only place that makes sense for it.
char *ptr;
On the other hand, ptr is only a pointer, and may point somewhere. Most often, it's something like this:
ptr = buf; // #1: point to the beginning of buf, same as &buf[0]
or maybe this:
ptr = malloc (1000); // #2: allocate heap and point to it
or:
ptr = "abcdefghijklmn"; // #3: string constant
For all of these, *ptr can be written to—except the third case where some compiling environment define string constants to be unwritable.
*ptr++ = 'h'; // writes into #1: buf[0], #2: first byte of heap, or
// #3 overwrites "a"
strcpy (ptr, "ello"); // finishes writing hello and adds a NUL
The difference is that one is a pointer, the other is an array. You can, for instance, sizeof() array. You may be interested in peeking here
If you're using C++ as your tags indicate, you really should be using the C++ strings, not the C char arrays.
The string type makes manipulating strings a lot easier.
If you're stuck with char arrays for some reason, the line:
char new_str[] = "";
allocates 1 byte of space and puts a null terminator character into it. It's subtly different from:
char *new_str = "";
since that may give you a reference to non-writable memory. The statement:
char *new_str;
on its own gives you a pointer but nothing that it points to. It can also have a random value if it's local to a function.
What people tend to do (in C rather than C++) is to do something like:
char *new_str = malloc (100); // (remember that this has to be freed) or
char new_str[100];
to get enough space.
If you use the str... functions, you're basically responsible for ensuring that you have enough space in the char array, lest you get all sorts of weird and wonderful practice at debugging code. If you use real C++ strings, a lot of the grunt work is done for you.
The type of the first is char[1], the second is char *. Different types.
Allocate memory for the latter with malloc in C, or new in C++.
char foo[] = "Bar"; // Allocates 4 bytes and fills them with
// 'B', 'a', 'r', '\0'.
The size here is implied from the initializer string.
The contents of foo are mutable. You can change foo[i] for example where i = 0..3.
OTOH if you do:
char *foo = "Bar";
The compiler now allocates a static string "Bar" in readonly memory and cannot be modified.
foo[i] = 'X'; // is now undefined.
char new_str[]="abcd";
This specifies an array of characters (a string) of size 5 bytes (one byte for each character plus one for the null terminator). So it stores the string 'abcd' in memory and we can access this string using the variable new_str.
char *new_str="abcd";
This specifies a string 'abcd' is stored somewhere in the memory and the pointer new_str points to the first character of that string.
To differentiate them in the memory allocation side:
// With char array, "hello" is allocated on stack
char s[] = "hello";
// With char pointer, "hello" is stored in the read-only data segment in C++'s memory layout.
char *s = "hello";
// To allocate a string on heap, malloc 6 bytes, due to a NUL byte in the end
char *s = malloc(6);
s = "hello";
If you're in c++ why not use std::string for all your string needs? Especially anything dealing with concatenation. This will save you from a lot of problems.