c++ char array returns some strange value - c++

After inserting values in dynamic char array, trying to get first value from the top. Method gives me back ² value.
Can you help me with understanding, what I am doing wrong? Here is main method:
char* arr = new char[5]();
arr[0] = 'h';
arr[1] = 'e';
arr[2] = 'l';
arr[3] = 'l';
char result = topValue(arr, 5);
cout << result;
Here is topValue() method:
char topValue(char* stackArr, int stackSize)
{
for (int i = stackSize; i >= 0; i--)
{
std::cout << "In top: " << stackArr[i] << std::endl;
if (stackArr[i] != '\0')
{
return stackArr[i];
}
}
}

In the first iteration of the loop, you access the array outside of its bounds, and the behaviour of the program is undefined.
Note that your function doesn't handle the potential case where all elements are the null terminator character. In such case the function would end without returning a value and the behaviour of the program would be undefined. Either handle that case, or carefully document the pre-condition of the function.
Furthermore, the program leaks memory. I recommend avoiding the use of bare owning pointers.
After inserting values in dynamic char array ...
You aren't inserting values into an array. It isn't possible to insert values into an array. The number of elements in an array is constant.

Related

How to check if certain position in array is modified using pointers

I don't understand how I can check if a certain position in an array is been modified or not. Below is an example:
int array[5];
array[2] = 23;
array[4] = 23;
for (int i = 0; i < 5; ++i) {
if (array[i] == ????){
cout << "in array";
} else {
cout << "not in array";
}
}
So I wanted to know how would I get it so the if statement is checking if the item has been modified. So once I becomes 2 it will says it's in array and if not the it should print 'not in array'.
This has to be done using pointers.
This is undefined behavior because array[0] isn't initialized. So when you compare it in your if, what will happen?
You could initialize them all to a value that you consider as "not modified", and check for this value. For instance:
int array[5] = {}; // initializes all elements to the default value for int, which is 0
And then, in your if:
if (array[i] != 0 ) {
If you can't do that because you need the full range of int values, then you can use std::optional instead:
#include <iostream>
#include <optional>
int main() {
std::optional<int> array[5];
array[2] = 23;
array[4] = 0;
for (int i = 0; i < 5; ++i) {
if (array[i]) {
std::cout << "in array" << std::endl;
}
else { std::cout << "not in array" << std::endl; }
}
}
You can't. In C++, it's impossible to determine if an object is uninitialized. Any attempt to read the value of an uninitialized object is Undefined Behavior. They're effectively write-only.
(You might also have a problem with the terminology, or a lack of understanding. array[0] is in the array from the very start, it's just not yet initialized. )
You might use std::map<int, int> values instead. It can truly be empty (values.empty()==true) When you write values[2]=0, a new value is added, and values.size() will be 1 to reflect the new number of elements.
I don't understand how I can check if a certain position in an array is been modified or not.
On x86 you can set a hardware breakpoint on read/write/execute access to a value at a specific address of length of up to 8 bytes. On Linux one API for that is perf_event_open with PERF_TYPE_BREAKPOINT event type. The value of the event counter is how many of interesting accesses to the value at the address have been made.
One option would be using two arrays. A bool array to store the initialization state, and another array to keep desired objects.
(However std::array or std::vector would be better choices than using normal arrays, but that's a different concern)
E.g.
constexpr unsigned int ArrayLen = 5;
bool isInitialized[ArrayLen] = {false};
MyType myArray[ArrayLen]; // In your case `MyType = int`
...
// When setting/resetting update both arrays
void Set(int i, MyType obj)
{
assert(i < ArrayLen);
isInitialized[i] = true;
myArray[i] = std::move(obj);
}
...
// check isInitialized array first before accessing an element
unsigned int targetIndex = 2;
if (isInitialized[targetIndex])
{
auto& obj = myArray[targetIndex];
// use `obj` ...
} else {
// object in `targetIndex` is not initialized
}
In C++17 you can use std::optional so that the initialization state doesn't need to be separately maintained but instead both the state and the object will be bound to a single std::optional object.

Understanding C++ syntax for array pointers double brackets

I writing a script which receives a structure (Evt) which holds an array of pointers uint16_t *DataChannel[Evt->ChSize[ch]]. I can then loop over the data and print out of the value as so:
for(uint16_t ch=0; ch<sizeof(Evt->DataChannel)/sizeof(Evt->DataChannel[0]); ++ch){
for(int adc_it=0; adc_it<(Evt->ChSize[ch]); ++adc_it){ for(int adc_it=0; adc_it<(Evt->ChSize[ch]); ++adc_it){
std::cout << (Evt->DataChannel)[ch][adc_it] << " ";
}
}
I don't understand where the second bracket comes from ([adc_it]), what it is doing and how it works. I think (Evt->DataChannel) should be a uint16_t which is not an array so why the second bracket?
I tried to replicate this in a quick piece of code:
#include <iostream>
int main()
{
int* test[10];
*(test[0]) = 5;
std::cout << test[0][0] << std::endl; //Gives 5
std::cout << test[0][1] << std::endl; //Seg faults
return 0;
}
Again can some explain what test[0][0] is doing because I have no idea and why it runs but test[0][1] fails?
Cheers
Dom
C++ permits the use of array notation [ ] when dereferencing a pointer.
In the simplest case, you can say something like:
char *ptr = new char[10];
That creates a pointer to char, which points to the first character in an array of ten characters allocated with new[].
After doing this:
char ch = *ptr;
and
char ch = ptr[0];
do the exact same thing. However since there are 10 characters in the array, you can also say:
char ch5 = ptr[5];
to access an element further up the array.
This leads to an eqivalence in C++ (and C, where it originated) that:
ptr[x];
is identical to:
*(ptr + x);
for any pointer / array referenced by ptr and any index x.
Already the first part
int* test[10];
*(test[0]) = 5;
is undefined behaviour, because you dereference an uninitialized pointer value.
Explanation:
int* test[10] is an array of 10 pointers to ints, each pointer
being not initialized and definitely not pointing to a memory that
you reserved to store ints.
test[0] gives an uninitialized pointer; already this statement is
UB
*(test[0]) = 5 dereferences an arbitrary pointer value, definitely
UB
Try:
int* test[10];
int firstLine[5] = { 1,2,3,4,5 };
test[0] = firstLine;
cout << test[0][0]; // gives 1, firstLine[0]
cout << test[0][1]; // gives 2, is the same as firstLine[1]
// cout << test[1][0]; // undefined behaviour, the second pointer in array test is not initialized

How to I Properly Dereference a pointer to a pointer array?

I'm working on an assignment involving string pointers. There are two functions. The first takes in an array of strings, places the address of each element into a separate array, and then returns the pointer to that array. The second function takes the pointer that was returned and prints out the elements of the original array with just the pointer. But when I test it, the dereferenced string** ptrToPtr is different in each pointer. I want to know why
Here is Function 1:
string** arrayOfPtrs(string arr[], int size)
{
string* ptrArray; //The array of string pointers
string** ptrToPtr; //A pointer to the array of string pointers
ptrArray = new string[size];
//ptrArray = arr;
int i = 0;
while (i < size)
{
ptrArray = &arr[i];
i++;
ptrArray++;
}
ptrToPtr = &ptrArray;
return ptrToPtr;
}
Here is Function 2:
void outputArray(string** arr, int size)
{
int count = size; //An int variable that stores the size of array
string* ptr = *arr; //A pointer that stores the address to the last element
//in the string pointer array
while (count > 0)
{
cout << *(ptr - count) << " ";
count--;
}
cout << endl;
}
And here is part of main():
string strArr[] = { "echo", "charlie", "delta", "bravo", "delta" };
string** strPtrs;
strPtrs = arrayOfPtrs(strArr, 5);
cout << "Actual results: ";
outputArray(arrayOfPtrs(strArr, 5), 5);
cout << endl << endl;
I'm I going wrong anywhere? Or is there a better way to deference a pointer to a string pointer?
Here is a similar program ran completely in main:
int main()
{
string words[30];
string* s;
s = new string[30];
string** t;
createArray(30, words);
int num = 0;
t = &s;
while (num < 30)
{
s = &words[num];
num++;
s++;
}
string* u = *t;
int j = 30;
for (int i = 0; i < 30; i++)
{
cout << "*(s - " << j << ") - " << *(s - j) << endl;
cout << "words[ " << i << " ] - " << words[i] << endl;
cout << "*(u - " << j << " ) - " << *(u - j) << endl << endl;
j--;
}
}
And this program works perfectly. Any ideas?
This is incorrect:
while (i < size)
{
ptrArray = &arr[i];
i++;
ptrArray++;
}
Replace ptrArray = &arr[i]; with *ptrArray = arr[i];. As it stands now, you're just overwriting the same pointer each time through the loop and never doing anything useful with it.
This is also incorrect:
string* ptrArray; //The array of string pointers
// ...
ptrToPtr = &ptrArray;
return ptrToPtr;
As soon as you return that, it becomes dangling. You're not allowed to use pointers to local (stack) variables once they're out of scope.
Firstly, I see a few problems in your setup
You don't need this for practical reasons. If you want to have the address of each element in the array, you can calculate it by incrementing the pointer to the first element (which is the array in fact). If you only do that for educational reasons forget about this
string* ptrArray = new ... Now you have an array of strings (array is semantically equaivalent to pointer to first element). But you want an array of string pointers. So you need string** ptrArray = new ... and this cascades to the rest of the function being incorrect.
You never delete the array allocated with new. This results in the memory not being free'd. You need to delete[] *strPtrs;in your last code snippet to free the memory you allocated in your method. In general it is a good idea to let the one who allocates the memory be responsibly for freeing it. I show you another idea below to handle this.
After your copy operations the pointer points past your array. Then you return a pointer to it. You applied the correct arithmetics when outputting the values in you second snippet, but I would never want to have such a pointer going around. Conventionally it should point to the first element. At least when deleting the array-pointer it has to point to the first element, otherwise you get undefined behavior e.g. deleting another array.
Lastly:
string* ptrArray; //The array of string pointers
string** ptrToPtr; //A pointer to the array of string pointers
ptrToPtr points to ptrArray, which is a local variable. It becomes invalid when leaving the function and thus it will be undefined behavior to dereference the returned pointer.
There is a common approach used by some standard libraries (e.g. snprintf from cstdio), so the caller is responsible for allocation and deallocation:
void arrayOfPtrs(string arr[], int size,/*new param*/ string** outArray)
{
string** iter = outArray; // Iterator pointer
int i = 0;
while (i < size)
{
*iter = &arr[i];
i++;
iter++;
}
}
What happens here, is that the caller gives the function a pointer to the pointers (it points to the first pointer). Note that a pointer can be used as an array with index operators etc. So it is in fact an array of pointers. You then fill it by incrementing the copied pointer so it jumps from pointer element to pointer element. Where the array actually is stored is not the problem of this function.
Use it like this:
// Variant 1: Use local variable if size is constant
string* arr[5];
arrayOfPtrs(strArr, 5, arr);
std::cout << *arr[0]; // Dereferences a pointer in arr to get the string which is actually in strArr
// Variant 2: Allocate heap memory (if you need dynamic size)
int size ...; // From somewhere
string** arr = new string[size];
arrayOfPtrs(strArr, size, arr);
std::cout << *arr[0]; // Same again
... // Do further work
delete[] arr; // Free memory
So you have to allocate memory (or use a local variable) before you call the function and then pass it to the function. In the double pointer, the first * is meant for the data type which is "pointer to string" and the second designates it as a "pointer-array".

Output a list of integer values at the same time by using a pointer dynamic array?

In C++, following the code below:
char *p = new char();
*p = 'a';
*(p+1)= 'b';
*(p+2) ='\0';
cout<<p<<endl;
we can get the output result: ab
When I want to write the code like this:
int *p = new int();
*p = 1;
*(p+1)= 2;
cout<<p<<endl;
It gives the result, but not 12 or something start with 12
Question is why the result goes wrong when changing it from char to integer? How to realize the goal that output a list of value by using a pointer dynamic array?
This is because char * is a bit of a special case.
In the C days, char * was the only type we really had to deal with strings. C++ makes it easier to interoperate with legacy code by providing streaming operators that treat char * values specially, by streaming out each character until a null character ('\0') is encountered.
When you stream out p when it's an int * there is no special case -- you just get the raw pointer value displayed.
If you want a one-liner to display the elements in a standard container, you can combine std::copy() with std::ostream_iterator:
std::copy(std::begin(some_array),
std::end(some_array),
std::ostream_iterator<int>(std::cout));
Since your array is allocated on the heap and stored in a pointer, std::begin() and std::end() won't work for you; you'll have to provide the end iterator manually:
std::copy(p, p + 2, std::ostream_iterator<int>(std::cout));
(See a demo.)
But note that both code samples in your question are undefined behavior, because you allocate a single object of type char or int and then try to assign beyond it. You write into memory you haven't allocated. Don't do this.
To fix your cases, you need to allocate enough room for the objects you intend to store:
// Case one
char *p = new char[3];
// Case two
int *p = new int[2];
And, of course, don't forget to delete[] p in both cases -- or you could just use std::string in the first case and std::vector<int> in the second.
Ok, first of all, this is unsafe:
*(p+1)= 'b';
You only allocated one byte and now you're stomping on memory you don't own - which is undefined behavior. If you want to allocate 3 bytes, do it:
char* p = new char[3];
Secondly, this:
int* pi = new int;
cout << pi << endl;
Will print the address of the pointer. char* is special in that cout will actually print the C-style string that is pointed to, but for other types - you just get the address.
If you want to print 12, you have to dereference the pointer:
int* pi = new int(12);
cout << *pi << endl;
If you want to output 1 and 2, separately, you need an array:
int* pi = new int[2];
pi[0] = 1;
pi[1] = 2;
cout << pi[0] << ", " << pi[1] << endl;
Note that, again, *(p + 1) = 2 in your code is stomping on memory you don't own.

How to create an array of character arrays in c++? (only using iostream)

I am very new to c++.
Say I have this:
char arrOne[10];
char arrTwo[10];
char arrThree[10];
How can I create an array where each element in the array holds a character array like above?
The goal is to be able to call upon the index of the array of arrays to grab one of these character arrays when needed.
Keep in mind. I can ONLY use iostream.
You could create a char pointer array
char * array[3];
char arrOne[10]
char arrTwo[10]
char arrThree[10]
array[0] = arrOne;
array[1] = arrTwo;
array[2] = arrThree;
To access arrayOne ,for example, use array[0].
Hello I think you need to use a for/while loop to access each element in an array
for example
char array[10] = "hello";
int i = 0;
while (i != '\0')
{
if( array[i] = 'l')
{
array[i] = 'x';
}
i++;
}
cout <<"new array string" << array<<endl;