Dynamic memory allocation of array in C & C++ - c++

Look at the user input in C and C++ code (inside for loop).We use *(p+i) in user input in C++ and (p+i) in C. Whats the reason for missing * in C?
Plz explain! Take a look at the COMMENT line... inside for loop
#include <iostream>
using namespace std;
int main()
{
int n,i;
cout << "Ent size" << endl;
cin>>n;
int *p = new int [n];
for(i=0;i<n;i++)
cin>>*(p+i);//LOOK AT THIS LINE
cout<<"------------\n\n";
for(i=0;i<n;i++)
cout<<*(p+i)<<endl;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
printf("Ent size!\n");
scanf("%d",&n);
int *p=(int *)malloc(n*sizeof(int));
int i;
for(i=0;i<n;i++)
scanf("%d",(p+i));//LOOK AT THIS LINE
printf("-------\n\n");
for(i=0;i<n;i++)
printf("%d\n",(p+i));
return 0;
}

The difference exists due to the existence of references in C++.
In C++ operator >> for objects of type int is declared the following way
basic_istream<charT,traits>& operator>>(int& n);
As you see the parameter of the operator has type int &. It means that the argument is passed to the function by reference that is the function deals directly with the argument not with its copy.
So this statement
cin>>*(p+i);
is equivalent to
cin.operator( *( p + i ) );
and the compiler does not creates a copy of the object specified by the expression *( p + i ). It uses the object itself because the object is passed by reference.
In C in fact there is also used a reference to the argument but it is specified as a pointer because the notion of references is not defined in C.
When somebody says that an object is passed by reference to a function in C it means that the object is passed indirectly using a pointer to the object.
In C++ it means that there is used the notion of the reference.
So if you want that function scanf would store the input data in the object itself you have to pass it indirectly to the function by using a pointer to the object.
scanf("%d",(p+i));
Here p + i is a pointer to object *( p + i ).
Consider these two simple programs
C++
#include <iostream>
int main()
{
int x = 10;
int &rx = x;
std::cout << "x = " << std::endl;
rx = 20;
std::cout << "x = " << std::endl;
}
The same in C can be written the following way using a pointer because C does not have the notion of references
C
#include <stdio.h>
int main( void )
{
int x = 10;
int *rx = &x;
printf( "x = %d\n", x );
*rx = 20;
printf( "x = %d\n", x );
}

Related

error: cannot convert ‘int (*)[4]’ to ‘int**’ | SWAPPING ARRAYS

I am trying to write a function that swap two arrays in O(1) time complexity. However, when i try to write the function parameters, I get the error:
error: cannot convert ‘int (*)[4]’ to ‘int**’
Here is my code:
#include <iostream>
using namespace std;
void swap_array_by_ptr(int* a[], int* b[]) {
int* temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int fr[] = {1,2,3,4};
int rv[] = {4,3,2,1};
swap_array_by_ptr(&fr, &rv);
for (int i = 0; i < 4 ; i++) {
cout << fr[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << rv[i] << " ";
}
}
However, when i tried to define the arrays with 'new' command, this works as expected as below:
#include <iostream>
using namespace std;
void swap_array_by_ptr(int** a, int** b) {
int* temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int fr = new int[4]{1,2,3,4};
int rv = new int[4]{4,3,2,1};
swap_array_by_ptr(&fr, &rv);
for (int i = 0; i < 4 ; i++) {
cout << fr[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << rv[i] << " ";
}
}
Is there any way that i can define the arrays with [] method and swap the arrays by sending these arrays with '&array' method ?
As I believe, there must be a way to do that, I only achieve this when I'm trying to do with 'new' method. However, is there any way to swap two arrays in O(1) complexity with sending parameters as
swap_array_by_ptr(&fr, &rv);
?
Thanks for help.
You can not swap two arrays with O( 1 ). You need to swap each pairs of corresponding elements of two arrays.
In the first program
int fr[] = {1,2,3,4};
int rv[] = {4,3,2,1};
swap_array_by_ptr(&fr, &rv);
the expressions &fr and &rv have type int( * )[4] while the corresponding function parameters in fact has the type int **
void swap_array_by_ptr(int* a[], int* b[]) {
after adjusting the parameters having array types to pointers to the array element types by the compiler.
So the compiler issues an error.
You could use standard function std::swap declared in the header <utility> the following way
std::swap( fr, rv );
But in any case its complexity is O( n ).
In the second program there are at least typos. Instead of
int fr = new int[4]{1,2,3,4};
int rv = new int[4]{4,3,2,1};
you have to write
int *fr = new int[4]{1,2,3,4};
int *rv = new int[4]{4,3,2,1};
In this case you are not swapping arrays themselves. That is the arrays will still store their initial values. You are swapping pointers that point to the dynamically allocated arrays.
To be sure that arrays are not swapped consider the following demonstration program.
#include <iostream>
using namespace std;
void swap_array_by_ptr(int** a, int** b) {
int* temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int fr[] = { 1,2,3,4};
int rv[] = {4,3,2,1};
int *p1 = fr;
int *p2 = rv;
swap_array_by_ptr( &p1, &p2 );
for (int i = 0; i < 4 ; i++) {
cout << p1[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << p2[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << fr[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << rv[i] << " ";
}
cout << endl;
}
It is a syntactic quirk inherited from C that a declaration of a function parameter as an array is automatically converted to a declaration as a corresponding pointer. This is not as odd as it might first seem, however, because it dovetails with the automatic conversion of function arguments of array type to corresponding pointers, also inherited from C.*
Thus, this declaration ...
void swap_array_by_ptr(int* a[], int* b[]) {
... is equivalent to this one:
void swap_array_by_ptr(int **a, int **b) {
. But the arguments you are passing do not match. This, for example,
int fr[] = {1,2,3,4};
declares fr as an array of 4 int. If it were passed as a function argument, it would be automatically converted to a pointer to the first element, thus of type int *. Types int * and int ** are not compatible.
On the other hand, what you actually try to pass, &fr is the address of an array 4 int, of type int(*)[4]. This also is incompatible with int **, because arrays are not pointers.
You could write your function like this:
void swap_array_by_ptr(int (*a)[4], int (*b)[4]) {
int temp[4];
memcpy(temp, a, sizeof(a));
memcpy(a, b, sizeof(b));
memcpy(b, temp, sizeof(temp));
}
That would be compatible with the call in your code. Do note, however, that that is specific to array size 4, and you're not really gaining anything useful from that. You could, however, convert it to a template:
template<class T, std::size_t n>
void swap_array(T (*a)[n], T (*b)[n]) {
T temp[n];
memcpy(temp, a, sizeof(a));
memcpy(a, b, sizeof(b));
memcpy(b, temp, sizeof(temp));
}
That handles arrays of any element type and size,** as long as the sizes match. Of course, it scales as O(N) with array size, in both time and auxiliary space.
Such time scaling is unavoidable. To swap two objects you need to read each at least once and write each at least once, and that requires time proportional to the size of the objects. But you could reduce the space overhead to O(1) by swapping the arrays element by element in a loop. That would very likely be slower, but the time complexity would still be O(N).
Of course, you can also use std::swap() on arrays. It is quite similar to the template above, but uses references to the arrays instead of pointers to them.
*This is a specific case of a much more general behavior.
**So long as the temporary array does not turn out to be too large for the stack.
Change the swap_array_by_ptr function from 'swap_array_by_ptr(int** a, int** b)'
to 'swap_array_by_ptr(int* a, int* b)'.
void swap_array_by_ptr(int* a, int* b) {
int* temp = *a;
*a = *b;
*b = temp;
}
here's a link to a similar question: Swapping 2 arrays in C

Calculates the position of the max element for array. function returns the max element. pass the array by the pointer and the pos. by the reference

i have a little problem with my college assignment. I don't really understand what's going on with pointers and reference. Could someone point me where I am making a mistake??
using namespace std;
int i, n, maax, *position;
void tablica()
{
int tab[n];
cout<<"enter data:"<<endl;
for (i=0; i<n; i++)
{
cin>>tab[i];
}
maax = tab[0];
for (i=0; i<n; i++)
{
if (maax<tab[i])
{
maax=tab[i];
*position=i+1;
}
}
}
int main()
{
cout<<"array size:"<<endl;
cin>>n;
tablica();
cout<<"max el. position is: "<<&position<<endl;
return 0;
}
Sure we can help you a little bit. But the whole topic of pointers and references cannot be covered in a short answer here on SO. You need to read a book.
The following will be very simplified and there is much more in reality. But let's start with this simple explanantion.
Let me give you a typical example that is often used in C or very early C++ books. Look at the function swap that should exchange the values of 2 variables.
#include <iostream>
void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int a = 1, b = 2;
swap(a, b);
std::cout << "a: " << a << "\tb: " << b << '\n';
}
We hope that after the call to the function swap, "a" will contain 2 and "b" will be 1. But it is not. Because in this case (and per default) the variables that are given to the function swap, are passed by value. So, the compiler will generate some code and copies the value of variables "a" and "b" into some local internal storage, also accessible with the name "a" and "b". So, the original "a" and "b" will never be touched or modified. By passing a variable by value, a copy will be mdae. This is often intended, but will not work in this example.
The next development stage was the pointer. The pointer is also a variable that contains a value. But this time it is the address of another variable somehwere in memory. If you have a variable like int a=3; then the 3 is somewhere stored in memory (decided by the compiler of the linker) and you can access the memory region with the name "a".
A pointer can store the memory address of this variable. So not the value 3 of the variable "a", but the address of the variable "a" in memory. The pointer points to that memory region, where the 3 ist stored. If you want to access this value, then you need to dereference the pointer with the * operator. And to get the address of variable 'a', you can write &a. But how does this help?
It helps you indirectly to get modified or result values out of a function. Example:
#include <iostream>
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int a = 1, b = 2;
swap(&a, &b);
std::cout << "a: " << a << "\tb: " << b << '\n';
}
In main we take the address of variable "a" and "b" and give this to the function. The address of the function (the pointer) will be given to the function as value now. A copy of the pointer will be made (not in reality) but this does not harm, because we can now modify the original values of the variable, by derefencing the pointer. Then the function ends and we will find the correct values in the original variables "a" and "b".
But, pointers are notoriously difficult to understand and very error prone. Therefore the "reference" has been invented. It is kind of an alias for a normal variable. And the good point is that if you pass a reference to the function, then you can modify immediately the original value. That makes things very convenient.
The function swap could then be written as
#include <iostream>
void swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int a = 1, b = 2;
swap(a, b);
std::cout << "a: " << a << "\tb: " << b << '\n';
}
And this gives the intented result. And is by far simpler.
Now to your code. First, VLAs (variable length arrays), namely the int tab[n]; where 'n' is no compile time constant, are a not a ppart of the C++ language. You canot use them. You could and should use a std::vector instead, but you did not yet learn about it. So we will use new, to allocate some memory dynamically. Please note: In reality, new, raw pointers for owned memory and C-Style arrays should not be used. But anyway.
Then let us look at your requirements
function returns the max element. pass the array by the pointer and the pos. by the reference
So, we need a function to calculate the max element in an array, then return this value, and additionally copy the position of the max element in a variable, given to the function as reference. We will add an additional parameter for the size of the array, because we will not use VLAs here. The array will be given by pointer.
So the prototype of your function will be:
int getMaxElement(int *array, int sizeOfArray, int& positionOfMaxValue)
To implement such a function, we create an internal variable to hold the max value, which we will later return. Then, we compare all values in a loop against this max value and, if we find a bigger one, then we store this new result. As the initial value, we can simply take the first value of the array.
Example:
#include <iostream>
int getMaxElement(int* array, int sizeOfArray, int& positionOfMaxValue) {
int resultingMaxValue = 0;
if (sizeOfArray > 0) {
resultingMaxValue = array[0];
for (int i = 0; i < sizeOfArray; ++i) {
if (array[i] > resultingMaxValue) {
resultingMaxValue = array[i];
positionOfMaxValue = i;
}
}
}
return resultingMaxValue;
}
int main() {
// Get array size from user
std::cout << "\nPlease enter the array size: ";
int arraySize = 0;
std::cin >> arraySize;
// Create an array
int* array = new int[arraySize];
// Read all values into the array
for (int i = 0; i < arraySize; ++i)
std::cin >> array[i];
// Now calculate the max value and position of the max value
int position = 0;
int maxValue = getMaxElement(array, arraySize, position);
// Show result
std::cout << "\n\nResult:\nThe maximum value '" << maxValue << "' is at position " << position << '\n';
delete[] array;
}
Please remember: This is a very simplified explanation
You shouldn't use global variables (see Are global variables bad?). int tab[n]; is not standard C++, its a variable length array that is only available as extension on some compilers (see Why aren't variable-length arrays part of the C++ standard?). The segfault is because you never allocate memory for the position, it is initialized because its a global, but it doesnt point to an int (see Is dereferencing a pointer that's equal to nullptr undefined behavior by the standard?).
You do not need any array to get the max value and position. And there is no need to use a pointer in your code. Determine the maximum value and position in the same loop that is reading the input and return the result from the function instead of using the global variable:
#include <iostream>
int tablica(int n) {
std::cout<<"enter data:\n";
int max = 0;
int max_pos = 0;
std::cin >> max;
for (int i=1; i<n; i++) {
int number = 0;
std::cin>>number;
if (max<number) {
max=number;
max_pos = i;
}
}
return max_pos;
}
int main()
{
std::cout<<"input size:\n";
int n;
std::cin>>n;
int position = tablica(n);
std::cout<<"max el. position is: "<< position << "\n";
return 0;
}
Look at what the function should do:
"function returns the max element. pass the array by the pointer and the pos. by the reference"
It should not read any array elements.
It should not receive or return values in global variables.
It should not use a pointer to the position.
It should be passed an array (as a pointer) and somewhere to store the maximum position (as a reference), and return the maximum value.
That is, its prototype should look like
int tablica(const int* input, int size, int& max_position)
and main should look something like this:
int main()
{
int n = 0;
cout << "Array size: " << endl;
cin >> n;
int* data = new int[n];
for (int i = 0; i < n; i++)
{
cin >> data[i];
}
int position = -1;
int max_element = tablica(data, n, position);
cout << "The maximum element is " << max_element << ", at index " << position << endl;
delete [] data;
}
Implementing tablica left as an exercise.

Error ISO C++ forbids comparison between pointer and integer

I got this error:
[Error] ISO C++ forbids comparison between pointer and integer [-fpermissive]
My code:
#include <stdio.h>
int main()
{
int i[1];
int r = 4;
{
printf("enter a number between 1-10\n");
while (i != r);
{
scanf("%d,&i[0]");
}
printf("good job\n :)");
}
}
The problem is that the variable i in your code above, is an array of int which decays to a pointer to an int due to type decay. On the other hand, the variable r is an int. So when you wrote:
while (i != r)
this means you're trying to compare a pointer to an int with an int and hence the said error.
To solve this you can use the following program:
#include <iostream>
int main()
{
int arr[4] = {}; //create an array named arr of size 4 with elements of type int all initialized to 0
//iterate through the array and take input from user
for(int &element : arr)
{
std::cout << "Enter number:" << std::endl;
std::cin >> element;
}
return 0;
}

X is used uninitialized in this function

Why am i getting this warning?:
warning: 'row1[3]' is used uninitialized in this function [-Wuninitialized]
I've been googling this for some time but but i can't find any answers, probably just because i'm inept at searching answers on Google.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int setfunc(int x);
int main()
{
int row1[3]{0,0,0};
setfunc(row1[3]);
}
int setfunc(int x[])
{
string sub;
int rowset;
stringstream rs;
string snums;
int elementnum = sizeof(x) / sizeof(0);
for(int z = 1; z <= elementnum; z++)
{
int find = snums.find(",");
if(find == -1)break;
else
{
sub = snums.substr(0, snums.find(","));
rs << sub;
rs >> rowset;
snums.erase(0, snums.find(",") +1);
}
x[z] = rowset;
cout << x[z] << endl;
}
return 0;
}
All help appreciated
The behaviour of int row1[3]{0,0,0}; setfunc(row1[3]); is undefined. This is because the indexing runs from 0 to 2, so row1[3] is accessing the array outside its bounds. The compiler is helping you here, although in my opinion, the warning is a little misleading.
sizeof(x) / sizeof(0); is also incorrect. sizeof(0) is the size of an int since 0 is an int type. The normal idiom is sizeof(x) / sizeof(x[0]). But you can't do this either in your case since the function parameter x will have decayed into a pointer. You ought to pass the number of elements into the function explicitly.

Getting segmentation fault with c++ pointers

So I'm trying to familiarise myself with c++ pointers by running the following code.
#include <iostream>
using namespace std;
int main(void){
int* x;
cout << &x << endl;
return 0;
}
which works fine and prints the pointer value of x but
#include <iostream>
using namespace std;
int main(void){
int* x;
*x = 100;
cout << &x << endl;
return 0;
}
gives me a segmentation fault when I try to tun it. Why is this? I don't see how that extra line should change anything about the address of x.
You did not allocate an object which you are going to assign.
int* x;
The value of x is unspecified and can be any arbitrary value. So the next statement
*x = 100;
is invalid.
You have to write
x = new int;
*x = 100;
Or
x = new int( 100 );
Or even
x = new int { 100 };
provided that your compiler supports the list initialization for operator new which was introduced in the C++ 2011..
and prints the pointer value of x but
Not exactly.
std::cout << &x; it prints x's address (the pointer's address);
std::cout << x; prints the address, x points to;
std::cout << *x; prints what x points to;
int* x;
*x = 100;
Here, x is just a pointer, you need to allocate memory for the 100. For example
int* x = new int;
*x = 100;
std::cout << *x;
Or just
int* x = new int( 100 );
std::cout << *x;
Without allocating memory and leaving x uninitialized, by *x = 100 you're trying to change some random memory, which leads to undefined behavior.
You have undefined behaviour.
Your first example is fine since &x (which has type int**) is the address of a stack allocated pointer. One of the << overloads in cout is defined to output that correctly.
In the second example, you are dereferencing a pointer that is not pointing to anything. That's undefined behaviour; hence the crash. If you'd written
int y;
int* x;
x = &y;
*x = 100; /*this means that y is now 100*/
then all would have been well since now x is pointing to something.