Pointer and char in struct - c++

How to read the second letter in char with a pointer? I can read the whole message "carp" and first letter 'c' but I have no idea how to read second letter... Here is my example code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
struct list {
char name[20];
int length;
};
list first ={
"carp",
6,
};
list *p = &first;
cout << p->name << endl; // "carp"
cout << *p->name << endl; // "c"
p = p + 1;
cout << *p->name << endl; // Not working...How to read a?
return 0;
}

Incrementing p with p++ or p = p+1 moves you to the next instance of struct list, which is not what you want (and it's not even there).
Instead, you want to move to the second letter of name, which can be done in several ways:
Use index on the name - cout << p->name[1] << endl;
Make a pointer to p->name and increment it, i.e. char *np = p->name; np++; cout << *np
Use pointer arithmetic instead of indexing, i.e. cout << *(p->name+1) << endl;

You can use index on name to access any character:
p->name[1] // gives 'a'
p->name[2] // gives 'r'
Note that arrays begin with an index of 0. So p->name[0] would give 'c'.
p + 1 actually increments p, which is a pointer to list. This essentially moves to the next instance of list, which is not even initialized in your code.

Use the array subscript operator with an index of 1:
p->name[1];

If you want to output the second character using pointers without the subscript operator then you can just write
cout << *( p->name + 1 ) << endl;
It is the same as
cout << p->name[1] << endl;
Or you can introduce an intermediate pointer. For example
for ( const char *q = p->name; *q != '\0'; ++q )
{
cout << *q;
}
cout << endl;

Related

std::cout behaves differently when printing variable vs function expression

I'm new to c++ and I'm facing an odd behavior from std::cout that I don't understand. In particular, when I want to print the value of the second node, using cout << nd.next[2]->next[17]->val, I get some convoluted bytes. However, if I set it to a variable first, e.g string let2 = nd.next[2]->next[17]->val, then use cout << let2, it prints the correct character. My code is below, I was implementing a trie. (Also since I am very new to c++ any other comments about what I am doing wrong in the code is appreciated)
#include <iostream>
#include <set>
#include <iterator>
#include <map>
#include <string>
#include <unordered_map>
using std::set;
using std::cout;
using std::endl;
using std::string;
struct Node {
Node* next[26];
string val;
void insert(string str) {
cout << "insert " << str << endl;
insert(str, 0);
}
void insert(string str, int idx) {
if (idx >= str.length()) {
return;
}
char cur = str[idx];
int curIdx = cur - 'a';
cout << "cur: " << cur << endl;
cout << "cur idx: " << curIdx << endl;
if (!next[curIdx]) {
Node newNode = Node();
newNode.val = cur;
next[curIdx] = &newNode;
}
next[curIdx]->insert(str, idx+1);
}
};
int plus(int a, int b) {
return a+b;
}
int main() {
Node nd = Node();
nd.insert("cryptography");
string let1 = nd.next[2]->val;
string let2 = nd.next[2]->next[17]->val;
cout << "first letter " << let1 << endl; // c
cout << "second letter " << nd.next[2]->next[17]->val << endl; // wrong
cout << "second letter " << let2 << endl; // work as expected
cout << "sum " << plus(1,2) << endl; // work as expected
// cout << nd.next[2]->next[17]->val << endl;
return 0;
}
Regarding the second part of your question ("what I am doing wrong"), in the insert() method you create Node() object on stack and assign next[curIdx] with a pointer to this object. But that stack object is destroyed automatically once the execution steps out of the scope where that object is defined, so next[curIdx] ends up pointing to garbage (memory where the object used to be before destroying).
Not sure how the next line is even working, next[curIdx] points to garbage at this point: next[curIdx]->insert(str, idx+1);
Instead you should allocate Node objects on heap with the new operator, ex:
if (!next[curIdx]) {
next[curIdx] = new Node(); // allocated on heap
next[curIdx]->val = cur;
}
but then you should make sure to deallocate (delete) them at some point to avoid memory leaks. Destructor of Node may be a good place for that – you can recursively delete all non-null Nodes from next array.
Also you could use smart pointers instead of raw pointers, they automatically delete objects when they can't be no longer accessed (garbage collector does that automatically in other languages like Java and C#).
More on stack vs heap: https://www.geeksforgeeks.org/stack-vs-heap-memory-allocation/

C++ Reallocating pointer to array in dynamic memory in a different function

I have just done a module on pointers and dynamic memory in C++ and am attempting to complete a personal assignment so that I can practice the concepts. The program manages an array of strings that are names. The goal that I set for myself is that the list is stored in the heap (to practice using "new"), and the list is dynamically sized as new names are entered.
Disclaimer: I realize that this is easily accomplished using vectors, and after struggling with this for hours I re-wrote my original code to use a vector for the list with no problems. However I want to learn where my understanding of how pointers work is broken.
The problem that I have with the program is this: I initialize the name array to have zero elements and have a function to add names that handles the dynamic sizing. When first called it seems to re-size the array correctly and add a new name to the the new array. Within the function to add a name, I can print the contents of the new array. I can also re-assign the old array pointer to the address of the new array on the heap. However when I call the print function from main after adding a name to the list, the list does not contain a name. By my understanding, since I'm using pointers I should be updating values directly, so after the add name function terminates, the values should persist. Also, if I attempt to add a second name the program crashes. What am I doing wrong with the handling of memory?
I've searched quite a bit and the closest that I can find for a resolution was this post:
How to make an array with a dynamic size? General usage of dynamic arrays (maybe pointers too)?
I modified my code based on what I understand from that but it still doesn't work properly.
#include <stdio.h>
#include <vector>
#include <iostream>
using namespace std;
void add_name_to_list(string * my_list, size_t * list_size);
string get_name();
void print_names(const string *const my_list, const size_t *const list_size);
int main()
{
string *name_list_ptr {nullptr};
name_list_ptr = new string [0];
size_t name_list_size{0};
size_t *name_list_size_ptr {&name_list_size};
print_names(name_list_ptr, name_list_size_ptr);
add_name_to_list(name_list_ptr, name_list_size_ptr);
print_names(name_list_ptr, name_list_size_ptr);
return 0;
}
void add_name_to_list (string * my_list, size_t *list_size)
{
string new_name{get_name()};
string *new_string_ptr{nullptr};
new_string_ptr = new string [*list_size+1];
// copy existing list into new list
cout << "List size is " << *list_size << " so *list size == 0 is " << (*list_size == 0) << endl;
if(*list_size == 0)
{
new_string_ptr[0] = new_name;
*list_size = *list_size +1;
cout << new_string_ptr[0] << " has been added to position " << *list_size << endl;
}
else
{
print_names(my_list, list_size);
for(size_t i{0}; i < *list_size; i++)
{
cout << "At position " << i << " original list is " << my_list[i] << endl;
new_string_ptr[i] = my_list[i];
cout << "The name " << new_string_ptr[i] << " has been added to position " << i << " of the new list" << endl;
}
new_string_ptr[*list_size - 1] = new_name;
*list_size = *list_size + 1;
}
print_names(new_string_ptr, list_size);
string *temp_ptr{nullptr};
temp_ptr = new string [*list_size-1];
cout << "temp ptr is " << temp_ptr << " and my list is " << my_list << endl;
temp_ptr = my_list;
cout << "temp ptr is " << temp_ptr << " and my list is " << my_list << endl;
my_list = new_string_ptr;
delete [] temp_ptr;
new_string_ptr = nullptr;
print_names(my_list, list_size);
}
string get_name()
{
cin.sync();
cin.clear();
string new_name{};
cout << "\nEnter the full name: ";
getline(cin, new_name);
cin.sync();
cin.clear();
if(new_name.size() <= 1)
return "0";
else
return new_name;
}
void print_names(const string *const my_list, const size_t *const list_size)
{
if(*list_size == 0)
cout << "The list is empty" << endl;
else
for(size_t j{0}; j < *list_size; j++)
cout << j << ". " << my_list[j] << endl;
}
One variation that I've tried based on what I learned from searching is:
cout << "temp ptr is " << temp_ptr << " and my list is " << my_list << endl;
//my_list = new_string_ptr;
//delete [] temp_ptr;
//new_string_ptr = nullptr;
delete [] my_list;
my_list = new string[*list_size];
my_list = new_string_ptr;
print_names(my_list, list_size);
Unfortunately the results are the same.
Without checking the logic of the implementation, your list doesn't update because you are assigning my_list = new_string_ptr; but your function received void add_name_to_list (string * my_list, size_t *list_size).
As you are newcomer to C++ world, let me explain clearly:
list_size is a pointer to a size_t, so if you modify the pointed memory, the change will persist, but if you modify the pointer itself, it will not.
list_size = new size_t; // This change doesn't persist
list_size++; // This change doesn't persist
*list_size++; // This change persists and the value of pointed memory was increased.
With my_list is happening exactly the same, you are trying to modify the pointer itself, not the pointed memory.
So, you should use:
void add_name_to_list (string * &my_list, size_t *list_size)
Or maybe you are more confortable with
void add_name_to_list (string ** my_list, size_t *list_size)
[...]
*my_list = new_string_ptr;
Hope this helps

Comparison Of Pointers

I want to compare the memory address and pointer value of p, p + 1, q , and q + 1.
I want to understand, what the following values actually mean. I can't quite wrap my head around whats going on.
When I run the code:
I get an answer of 00EFF680 for everytime I compare the adresss p with another pointer.
I get an answer of 00EFF670 for everytime I compare the address of q with another pointer.
I get an answer of 15726208 when I look at the pointer value of p.
And I get an answer of 15726212 When I look at the pointer value of p + 1.
I get an answer of 15726192 when I look at the pointer value of q
And I get an answer of 15726200 Wehn I look at the pointer value of q + 1.
Code
#include <iostream>
#include <string>
using namespace std;
int main()
{
int val = 20;
double valD = 20;
int *p = &val;
double *q;
q = &valD;
cout << "Memory Address" << endl;
cout << p == p + 1;
cout << endl;
cout << q == q + 1;
cout << endl;
cout << p == q;
cout << endl;
cout << q == p;
cout << endl;
cout << p == q + 1;
cout << endl;
cout << q == p + 1;
cout << endl;
cout << "Now Compare Pointer Value" << endl;
cout << (unsigned long)(p) << endl;
cout << (unsigned long) (p + 1) << endl;
cout << (unsigned long)(q) << endl;
cout << (unsigned long) (q + 1) << endl;
cout <<"--------" << endl;
return 0;
}
There are a few warnings and/or errors.
The first is that overloaded operator << has higher precedence than the comparison operator (on clang++ -Woverloaded-shift-op-parentheses is the flag).
The second is that there is a comparison of distinct pointer types ('int *' and 'double *').
For the former, parentheses must be placed around the comparison to allow for the comparison to take precedence. For the latter, the pointers should be cast to a type that allows for safe comparison (e.g., size_t).
For instance on line 20, the following would work nicely.
cout << ((size_t) p == (size_t) (q + 1));
As for lines 25-28, this is standard pointer arithmetic. See the explanation here.
As to your question:
I want to compare p, p +1 , q , and q + 1. And Understand what the results mean.
If p is at address 0x80000000 then p+1 is at address 0x80000000 + sizeof(*p). If *p is int then this is 0x80000000 + 0x8 = 0x80000008. And the same reasoning applies for q.
So if you do p == p + 1 then compiler will first do the additon: p+1 then comparison, so you will have 0x80000000 == 0x80000008 which results in false.
Now to your code:
cout << p == p + 1;
is actually equivalent to:
(cout << p) == p + 1;
and that is because << has higher precedence than ==. Actually you should get a compilation error for this.
Another thing is comparision of pointers of non related types like double* with int*, without cast it should not compile.
In C and C++ pointer arithmetic is very closely tied with array manipulation. The goal is that
int array[3] = { 1, 10, 100 };
int *ptr = { 1, 10, 100 };
std::cout << array[2] << '\n';
std::cout << *(ptr + 2) << '\n';
outputs two 100s. This allows the language to treat arrays and pointers as equivalent - that's not the same thing as "the same" or "equal", see the C FAQ for clarification.
This means that the language allows:
int array[3] = { 1, 10, 100 };
int *ptr = { 1, 10, 100 };
And then
std::cout << (void*)array << ", " << (void*)&array[0] << '\n';
outputs the address of the first element twice, the first array behaves like a pointer.
std::cout << (void*)(array + 1) << ", " << (void*)&array[1] << '\n';
prints the address of the second element of array, again array behaving like a pointer in the first case.
std::cout << ptr[2] << ", " << *(ptr + 2) << '\n';
prints element #3 of ptr (100) twice, here ptr is behaving like an array in the first use,
std::cout << (void*)ptr << ", " << (void*)&ptr[0] << '\n';
prints the value of ptr twice, again ptr behaving like an array in the second use,
But this can catch people unaware.
const char* h = "hello"; // h points to the character 'h'.
std::cout << (void*)h << ", " << (void*)(h+1);
This prints the value of h and then a value one higher. But this is purely because the type of h is a pointer to a one-byte-sized data type.
h + 1;
is
h + (sizeof(*h)*1);
If we write:
const char* hp = "hello";
short int* sip = { 1 };
int* ip = { 1 };
std::cout << (void*)hp << ", " << (void*)(hp + 1) << "\n";
std::cout << (void*)sip << ", " << (void*)(sip + 1) << "\n";
std::cout << (void*)ip << ", " << (void*)(ip + 1) << "\n";
The first line of output will show two values 1 byte (sizeof char) apart, the second two values will be 2 bytes (sizeof short int) apart and the last will be four bytes (sizeof int) apart.
The << operator invokes
template<typename T>
std::ostream& operator << (std::ostream& stream, const T& instance);
The operator itself has very high precedence, higher than == so what you are actually writing is:
(std::cout << p) == p + 1
what you need to write is
std::cout << (p == p + 1)
this is going to print 0 (the result of int(false)) if the values are different and 1 (the result of int(true)) if the values are the same.
Perhaps a picture will help (For a 64bit machine)
p is a 64bit pointer to a 32bit (4byte) int. The green pointer p takes up 8 bytes. The data pointed to by p, the yellow int val takes up 4 bytes. Adding 1 to p goes to the address just after the 4th byte of val.
Similar for pointer q, which points to a 64bit (8byte) double. Adding 1 to q goes to the address just after the 8th byte of valD.
If you want to print the value of a pointer, you can cast it to void *, for example:
cout << static_cast<void*>(p) << endl;
A void* is a pointer of indefinite type. C code uses it often to point to arbitrary data whose type isn’t known at compile time; C++ normally uses a class hierarchy for that. Here, though, it means: treat this pointer as nothing but a memory location.
Adding an integer to a pointer gets you another pointer, so you want to use the same technique there:
cout << static_cast<void*>(p+1) << endl;
However, the difference between two pointers is a signed whole number (the precise type, if you ever need it, is defined as ptrdiff_t in <cstddef>, but fortunately you don’t need to worry about that with cout), so you just want to use that directly:
cout << (p+1) - p << endl;
cout << reinterpret_cast<char*>(p+1) - reinterpret_cast<char*>(p) << endl;
cout << (q - p) << endl;
That second line casts to char* because the size of a char is always 1. That’s a big hint what’s going on.
As for what’s going on under the hood: compare the numbers you get to sizeof(*p) and sizeof(*q), which are the sizes of the objects p and q point to.
The pointer values that are printed are likely to change on every execution (see why the addresses of local variables can be different every time and Address Space Layout Randomization)
I get an answer of 00EFF680 for everytime I compare the adresss p with another pointer.
int val = 20;
double valD = 20;
int *p = &val;
cout << p == p + 1;
It is translated into (cout << p) == p + 1; due to the higher precedence of operator << on operator ==.
It print the hexadecimal value of &val, first address on the stack frame of the main function.
Note that in the stack, address are decreasing (see why does the stack address grow towards decreasing memory addresses).
I get an answer of 00EFF670 for everytime I compare the address of q with another pointer.
double *q = &valD;
cout << q == q + 1;
It is translated into (cout << q) == q + 1; due to the precedence of operator << on operator ==.
It prints the hexadecimal value of &valD, second address on the stack frame of the main function.
Note that &valD <= &val - sizeof(decltype(valD) = double) == &val - 8 since val is just after valD on the stack. It is a compiler choice that respects some alignment constraints.
I get an answer of 15726208 when I look at the pointer value of p.
cout << (unsigned long)(p) << endl;
It just prints the decimal value of &val
And I get an answer of 15726212 When I look at the pointer value of p + 1.
int *p = &val;
cout << (unsigned long) (p + 1) << endl;
It prints the decimal value of &val + sizeof(*decltype(p)) = &val + sizeof(int) = &val + 4 since on your machine int = 32 bits
Note that if p is a pointer to type t, p+1 is p + sizeof(t) to avoid memory overlapping in array indexing.
Note that if p is a pointer to void, p+1 should be undefined (see void pointer arithmetic)
I get an answer of 15726192 when I look at the pointer value of q
cout << (unsigned long)(q) << endl;
It prints the decimal value of &valD
And I get an answer of 15726200 Wehn I look at the pointer value of q + 1.
cout << (unsigned long) (q + 1) << endl;
It prints the decimal value of &val + sizeof(*decltype(p)) = &valD + sizeof(double) = &valD + 8

What's a practical use-case for "address of array"?

(Disclaimer: Pointers in C++ is a VERY popular topic and so I'm compelled to believe that someone before me has already raised this point. However, I wasn't able to find another reference. Please correct me and feel free to close this thread if I'm wrong.)
I've come across lots of examples that distinguish between pointer to first element of array and pointer to the array itself. Here's one program and its output:
//pointers to arrays
#include <iostream>
using namespace std;
int main() {
int arr[10] = {};
int *p_start = arr;
int (*p_whole)[10] = &arr;
cout << "p_start is " << p_start <<endl;
cout << "P_whole is " << p_whole <<endl;
cout << "Adding 1 to both . . . " <<endl;
p_start += 1;
p_whole += 1;
cout << "p_start is " << p_start <<endl;
cout << "P_whole is " << p_whole <<endl;
return 0;
}
Output:
p_start is 0x7ffc5b5c5470
P_whole is 0x7ffc5b5c5470
Adding 1 to both . . .
p_start is 0x7ffc5b5c5474
P_whole is 0x7ffc5b5c5498
So, as expected, adding 1 to both gives different results. But I'm at a loss to see a practical use for something like p_whole. Once I have the address of the entire array-block, which can be obtained using arr as well, what can I do with such a pointer?
For single arrays, I don't think there's much point to it. Where it becomes useful is with multi-dimensional arrays, which are arrays of arrays. A pointer to one of the sub-arrays is a pointer to the row, and incrementing it gets you a pointer to the next row. In contrast, a pointer to the first element of the inner array is a pointer to a single element, and incrementing it gets you the next element.
int (*)[10] is a "stronger" type than int* as it keeps size of the array,
so you may pass it to function without passing additional size parameter:
void display(const int(*a)[10]) // const int (&a)[10] seems better here
{
for (int e : *a) {
std::cout << " " << e;
}
}
versus
void display(const int* a, std::size_t size) // or const int* end/last
{
for (std::size_t i = 0; i != size; ++i) {
std::cout << " " << a[i];
}
}

variable value and its address using pointers in C++

I'm having some trouble understanding pointers. In the following code, I'm trying print the address of a variable in 2 ways-once using the address operator and then using pointers:
#include<iostream>
using namespace std;
int main (void)
{
int x = 10;
int *int_pointer;
int_pointer = &x;
cout << "x address=" << &x << endl;
cout << "x address w pointer=" << int_pointer << endl;
return 0;
}
x address = 0028FCC4
x address w pointer = 0028FCC4
This works as expected. But when I do the same thing but now using character type variable, I get some trash output:
#include<iostream>
using namespace std;
int main(void)
{
char c = 'Q';
char *char_pointer;
char_pointer = &c;
cout << "address using address operator=" << &c << endl;
cout << "address pointed by pointer=" << char_pointer << endl;
return 0;
}
address using address operator=Q╠╠╠╠£åbªp é
address pointed by pointer=Q╠╠╠╠£åbªp é
I have no idea why this is happening. Thanks in Advance.
The C++ library overloads the << operator for certain types. (char*) is one of them. Cout is trying to print a string, an array of characters terminated by a null character.
Just cast the pointer:
cout << "address pointed by pointer" << ( void* )char_pointer << endl;
or
cout << "address pointed by pointer" << static_cast<void*>(char_pointer) << endl;
The reason it prints out junky stuff is because your char does not have a null terminator which means the program will keep searching for one until, and in the process will print out whatever it finds. The text you see is ASCII but referenced by the address which the ostream is misinterpreting. To get the address held in memory, you could use implicit conversion or a static_cast. I prefer the latter:
cout << "address pointed by pointer=" << static_Cast<void*>(char_pointer) << endl;
Like 2501 said, in different wording, &c, since c is a char, equals a char *, so it's going to try to print until the new line character '\0' that is either implicitly or explicitly put in character arrays going to std::cout so the stream knows where the end of the character array is.
So, yeah use the (void *) like 2501 said.