Following is the code I wrote for reading a value at run time to dynamically allocated memory:
void main()
{
clrscr();
int *p = new int[5];
int *a = new int();
cin >> *a; // **line 5**
cout << *a << "\n"; // **line 6**
cout << &p; // line 7
cout << *p; // line 8
cout << "\nEnter 5 no for array\n";
for (int i = 0; i <= 4; i++)
{
cout << &p[i] << " :- ";
cin >> p[i]; // LINE 12
}
for (i = 0; i <= 4; i++)
cout << "\n" << p[i]; // LINE 16
delete[] p;
delete a;
getch();
}
I would like to know that while entering data for user in integer, we have to use *a with cin and cout for entering data in line 5 & 6 but in case of array we just gave the pointer variable name in line 12 & 16. Can anyone please tell me why we are having this difference?
Moreover can anyone also please tell me the difference between output of line 7 & 8.
You don't "have to"; you could have written cin >> a[0].
For built-in types and pointers and such, a[b] is *(a+b) is *(b+a) is b[a] and you can interchange them all.
It's only convention that leads to a choice. Like generally if you'd allocated more than one int you'd use "array notation" (a[i]) and if you'd allocated only one int you'd use a straight-up dereference (*(a+0), or *a).
But the language doesn't really care how many elements you allocated because either way you just have a pointer to "one or more" consecutive elements.
tl;dr this is just how the syntax was designed.
As for your second question, &p and *p give different results because they mean different things, and I'll leave discerning that difference as an exercise to the reader.
Related
I'd like to ask you if you think about this code, whether it is totally bad or i'm doing a bad use of the memory
This is the code
// Ask for capacity
int capacity ;
cout << "capacity: ";
cin >> capacity;
// Declare the array with pointers, this line is very important
int *arr = new int;
// For 0 until capacity-1 print ask for the numbers
for (int i = 0; i < capacity; i++)
{
cout << "number: ";
cin >> *(arr + i);
}
// Print them
for (int i = 0; i < capacity; i++)
{
cout << "[" << i << "]: " << *(arr + i) << " in " << arr + i << endl;
}
And this is an example of its output
capacity: 9
number: 1
number: 2
number: 3
number: 4
number: 5
number: 6
number: 7
number: 8
number: 9
[0]: 1 in 0x55dee480c690
[1]: 2 in 0x55dee480c694
[2]: 3 in 0x55dee480c698
[3]: 4 in 0x55dee480c69c
[4]: 5 in 0x55dee480c6a0
[5]: 6 in 0x55dee480c6a4
[6]: 7 in 0x55dee480c6a8
[7]: 8 in 0x55dee480c6ac
[8]: 9 in 0x55dee480c6b0
Look that, effectively it's saving the numbers in the correct positions in memory (4 bits, the size of an int)
But what's the limit? How can I know if I'm touching memory that I shouldn't touch?
Because look that I'm declaring the array as
int *arr = new int
Is that okay?
the same with this code, but this could be a little bit worse because it's a string, an array of characters as you may know
// Declaring the pointer name as new char and ask for it
char *name = new char;
cout << "name in: ";
cin >> name;
cout << "name out\n";
for (int i = 0; *(name + i) != '\0' ; i++)
{
printf("[%i]: %c\n", i, *(name + i));
}
Example:
name in: Gilberto
name out
[0]: G
[1]: i
[2]: l
[3]: b
[4]: e
[5]: r
[6]: t
[7]: o
The code only allocates one int object. Fix:
int* arr = new int[capacity];
*(arr + i) can be simpler: arr[i].
The code needs to delete the array at the end:
delete[] arr;
Or, better, use a smart pointer to avoid having to delete manually:
std::unique_ptr<int[]> arr(new int[capacity]);
Or, even better, use std::vector<int> arr(capacity);.
Raw (owning) pointers and manual memory management is almost never a good idea in modern C++. You should use containers like std::array and std::vector rather than C-style arrays any day. And ownership and lifetime of dynamic resources is much better modeled with smart pointers like std::unique_ptr, std::shared_ptr & std::weak_ptr rather than raw pointers. Don't write code that's easy to get wrong. Use the facilities we have available, to write code that's easy to get right and hard(er) to get wrong.
I'm writing a program that gets an array of integers and its logical size. When called it creates a new array containing only the positive numbers from the arrays.
Now, in order to do this I need to write a void type function takes the following parameters:
(int* arr, int arrSize, int** outPosArrPtr, int* outPosArrSizePTR)
I'm supposed to use the pointer int** outPosArrPtr to update the base address of the array containing the positive numbers, and the pointer outPosArrSizePtr to update the array's logical size.
now when I run my code on the xcode compiler the logical size gets updated to a very larger number. So, when I tried to run the program using the online gdb compiler I got the error "Segmentation fault."
From reading what Segmentation fault means I learnt that it means that I'm trying to access memory that "does not belong to me" or memory that is not in the call stack or in the heap portion of the program.
I tried to debug my code by seeing if I was referening any null pointers or see if I was referencing any dangling pointers but it seems like the problem is another one.
My code:
#include <iostream>
typedef int* IntArrPtr;
using namespace std;
int main() {
int arrSize;
int *ptrSize;
ptrSize = &arrSize;
cout << "How many integers will this array hold:\n ";
cin >> arrSize;
IntArrPtr a;
a = new int[arrSize];
fillArr(a, arrSize);
getPosNums4(a, arrSize,&a, ptrSize);
cout << "The new size in main is: " << arrSize << endl;
cout <<"The new array with positive integers is:\n";
/*for(int i =0; i<arrSize;i++) // this runs for a large size of arrSize
cout<< a[i] << " ";
cout<<endl; */
return 0;
}
void fillArr(int a[], int size){
cout << "Please enter " << size << " Integers separated by spaces\n";
cout << "Press enter when finished >\n";
int i;
for (i=0;i<size;i++)
cin >> a[i];
}
void getPosNums4(int* arr, int arrSize, int** outPosArrPtr,int* outPosArrSizePtr){
IntArrPtr newArr;
newArr = new int[arrSize];
int i;
int newIndx = 0;
outPosArrSizePtr = &newIndx;//initiliaze the pointer.
for(i=0;i<arrSize;i++){
if(arr[i] > 0){
newArr[newIndx] =arr[i];
newIndx++;
}
}
arrSize = newIndx;
*outPosArrSizePtr = arrSize;
cout << "The new size is of *outPosArrSizeptr is: " << *outPosArrSizePtr << endl;
for(int j=0;j<newIndx;j++)
outPosArrPtr[j] = &newArr[j];
delete []newArr;
newArr = NULL;
for(int i=0;i<newIndx;i++)
arr[i] = *outPosArrPtr[i];
}
an example When I run this program on Xcode:
How many integers will this array hold:
6
Please enter 6 Integers separated by spaces
Press enter when finished >
3 -1 -3 0 6 4
The new size is of *outPosArrSizeptr is: 3
The new array with positive integers is:
The new size in main is: 7445512
The program ended with exit code: 0
There are quite a few problems there, but the most crucial one is that assigning a value to a function's argument has no effect on the variable whose value you passed as the argument.
It doesn't matter that the argument is a pointer – there is nothing special about pointers.
What I think is happening is that your "copy back and forth" loop (I can't understand what it's supposed to do) in the function is writing outside the input array, causing undefined behaviour and, in this case, overwriting variables in main.
You're overcomplicating your function quite a bit. It should
Create a new array
Copy the positive values to this array
Update the output parameters with the address of this array and its (logical) size
(Think of out parameters as return values and handle them last.)
Something like this:
void getPosNums4(int* arr, int arrSize, int** outPosArrPtr,int* outPosArrSizePtr){
int* newArr = new int[arrSize];
int newIndx = 0;
for (int i = 0; i < arrSize; i++){
if (arr[i] > 0){
newArr[newIndx] = arr[i];
newIndx++;
}
}
*outPosArrPtr = newArr;
*outPosArrSizePtr = newIndx;
}
You should also not pass pointers to your "originals" for this function to modify, you should use new variables.
int main() {
int arrSize = 0;
cout << "How many integers will this array hold:\n ";
cin >> arrSize;
int* a = new int[arrSize];
fillArr(a, arrSize);
int * positives = nullptr;
int positiveSize = 0;
getPosNums4(a, arrSize, &positives, &positiveSize);
cout << "The new size in main is: " << positiveSize << endl;
delete [] a;
delete [] positives;
}
Modern C++ uses vector rather than manually allocating arrays. Manual allocation is prone to a variety of errors that are very difficult to debug.
The logic in your getPosNums4 method appears to be the trouble. If I understand the requirement, it should look for positive integers in the input array and copy them to a newly allocated output array. Over-allocating the output array is non-optimal but not an actual bug.
void getPosNums4(int* arr, int arrSize, int** outPosArrPtr,int* outPosArrSizePtr){
IntArrPtr newArr;
newArr = new int[arrSize];
int i;
int newIndx = 0;
for(i=0;i<arrSize;i++){
if(arr[i] > 0){
newArr[newIndx] =arr[i];
newIndx++;
}
}
*outPosArrSizePtr = newIndx;
cout << "The new size is of *outPosArrSizeptr is: " << *outPosArrSizePtr << endl;
*outPosArrPtr = newArr;
}
Note the the newly allocated array will need to be delete[] by the calling function or a memory leak will result.
Here is the same program in modern C++. Note that there is no use of new/delete which saves a lot of misery.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> integer_vector;
vector<int> positive_vector;
cout << "Type in integers. Type a Q to continue:" << endl;
int an_int;
while(cin >> an_int)
integer_vector.push_back(an_int);
for_each(integer_vector.begin(),integer_vector.end(),[&](int const& n){
if(n > 0)
positive_vector.push_back(n);
});
cout <<"The new array with positive integers is:\n";
for(auto const & element:positive_vector)
cout<< element << " ";
cout<<endl;
return 0;
}
I have been trying for such code
#include <iostream>
using namespace std;
int main()
{
int t=1;
cout<<t<<" ";
int *b = new int(t);
cout<<*b++<<" ";
cout <<*b<<" ";
cout<<t<<" ";
return 0;
}
It is giving me output as 1 1 0 1. I cant understand 0 in the output. Please explain me why this is happening ?
The precedence of the ++ operator is higher than that of the * operator in this case. You are thus incrementing the pointer b itself rather than the memory being pointed to (which is presumably your intention).
To get the behaviour you want:
cout<<(*b)++<<" ";
After the line
cout << *b++ << " ";
b points to memory beyond what was allocated.
The line after that,
cout << *b << " ";
dereferences memory beyond valid limits. Hence, it is cause for undefined behavior.
I am trying to output the values present in the array, that are accepted during runtime, onto the console. But when I run this program I get the 5 values in the array as the last value only.
For example: if i give 0 1 2 3 4 as the five values for this program then the output is shown as 4 4 4 4 4.
#include "stdafx.h"
#include<iostream>
using namespace std;
int main()
{
int arrsize = 5;
int *ptr = new int[arrsize];
*ptr = 7;
cout << *ptr << endl;
cout << "enter 5 values:";
for (int i = 0; i < arrsize; i++)
{
cin >> *ptr;
cin.get();
}
cout << "the values in the array are:\n ";
for (int i = 0; i < arrsize; i++)
{
cout << *ptr << " ";
}
delete[] ptr;
cin.get();
return 0;
}
Both of your loops:
for (int i = 0; i < arrsize; i++)
...
loop over a variable i that is never used inside the loop. You are always using *ptr which refers always to the first element of the dynamically allocated array. You should use ptr[i] instead.
A part from that, dynamic allocation is an advanced topic. I'd recommend sticking with simpler and more commonly used things first:
std::cout << "Enter values:";
std::vector<int> array(std::istream_iterator<int>(std::cin), {});
std::cout << "\nThe values in the array are:\n";
std::copy(begin(array), end(array), std::ostream_iterator<int>(std::cout, " "));
Live demo
Following issues I think you could tackle:
The first include can be omitted I think. Your code works without that.
You use cin.get(), not sure why you need that. I think you can remove that. Even the one at the very end. You could put a cout << endl for the last newline. I am using Linux.
And use ptr like an array with index: ptr[i] in the loops as mentioned in the other answer. ptr[i] is equivalent to *(ptr+i). You have to offset it, otherwise you're overwriting the same value (that is why you get that result), because ptr points to the first element of the array.
P.S.: It seems that if you're using Windows (or other systems) you need the cin.get() to avoid the console to close down or so. So maybe you'd need to check it. See comments below.
Trying to figure out the reasoning behind the mechanics of c strings.
char** text;
text = new char*[5];
for(int i = 0; int < 5; int++) {
cout << endl << "Enter a phrase: ";
cin >> text[i];
cout << text[i];
}
I'm not entirely sure as to why this works for the first 2 iterations, even successfully displaying them, but gets a segfault error on the 3rd iteration.
You are using uninitialized memory. You are experiencing undefined behavior.
The line
text = new char*[5];
allocated memory for five pointers but those pointers haven't been initialized to point to anything valid. Before you can use text[i] to read data, you have to allocate memory for it.
for(int i = 0; int < 5; int++) {
cout << endl << "Enter a phrase: ";
text[i] = new char[SOME_SIZE_LARGE_ENOUGH_FOR_YOUR_NEED];
cin >> text[i];
cout << text[i];
}
Then, it should work.
You've allocated memory for 5 pointers, but you are not allocating anything that those five pointers point to. Assuming that you're using a modern 64-bit CPU with 8 byte-wide pointers, your new operator allocated exactly 40 bytes, five eight-byte pointers. Their initial contents are random, uninitialized memory, and when you write to them, they get interpreted as pointers to random memory addresses, which end up being corrupted with what you've read from std::cin. You got lucky initially, and the first two iterations scribbled over some memory somewhere, but your program continued to limp along, but you won the lottery on the third try; hitting a random address that does not exist, and segfaulting.
Although you can rewrite this to do proper allocation, if you're really trying to write C++, rather than C, here, there's no reason to allocate anything. Why do you want to deal with allocating memory, when C++ will happily do it for you?
std::vector<std::string> text;
for(int i = 0; int < 5; int++)
{
std::cout << std::endl << "Enter a phrase: ";
std::string s;
if (std::getline(std::cin, s).eof())
break;
text.push_back(s);
std::cout << s << std::endl;
}