Confusion about pointer to an array as a function parameter - c++

In my textbook about c++ I have the following code example:
using std::cout;
using std::endl;
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 2,3,1 };
cout << "Append: " << endl;
printArray(aArr, 4); cout << " + "; printArray(bArr, 3);
int* cArr = append(&aArr, bArr);
cout << " = "; printArray(cArr, 7); cout << endl;
return 0;
}
Does the "&" symbol in front of "aArr" in the call to append in main mean that the address of aArr is passed, or that a reference to aArr is passed.
The question then asks for me to implement a function append which takes two arrays: the first array (in the first argument) of size 4 by array pointer and the second array (in the second argument) of size 3 by reference and returns a pointer to an array of size 7. I have declared that function as (in the appropriate header file)
int* append( int foo[4], int (&secondArray) [3] );
Has the author perhaps misplaced the order of the "&" symbol in the append method (that it should be in front of "bArr")?

The compiler can help you out in cases like this.
Lets assume that this is the function prototype for your append function:
int* append( int foo[4], int (&secondArray) [3]);
I can test this out with this simple bit of code:
int* append( int foo[4], int (&secondArray) [3])
{
return 0;
}
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 2,3,1 };
int* cArr = append(&aArr, bArr);
return 0;
}
But the compiler doesn't like this, failing with this error:
test.cpp(9): error C2664: 'int *append(int [],int (&)[3])':
cannot convert argument 1 from 'int (*)[4]' to 'int []'
As you can see it doesn't like the &aArr argument 1 at line 9 as it does not match the argument 1 defined by the function at line 1. From the error message it is even nice enough to give a reason why it thinks they don't line up.
Now using the hint from the compiler it is clear the function should in fact look like this:
int *append(int (*foo)[4], int secondArray[3])
{
return 0;
}
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 2,3,1 };
int* cArr = append(&aArr, bArr);
return 0;
}
With that change the compiler is happy to accept the code as correct.
Now comparing the two you can see the difference is in the first case the first argument was passed as an array of 4 integers, whereas in the second case it is passed as the address of an array of four integers.
Just from the english you can tell these are two very different things.
EDIT: Here is an extension of that example that shows how to access the data inside the function.
#include <stdio.h>
int *append(int (*foo)[4], int secondArray[3] )
{
int *foo1 = *foo;
for (int i = 0; i < 4; ++i)
{
printf("foo: %d\n", foo1[i]);
}
for (int j = 0; j < 3; ++j)
{
printf("secondArray: %d\n", secondArray[j]);
}
return 0;
}
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 12,13,11 };
int* cArr = append(&aArr, bArr);
return 0;
}
Compiling an running this code produces this output:
foo: 3
foo: 4
foo: 2
foo: 3
secondArray: 12
secondArray: 13
secondArray: 11

Related

Calling name for passing two arrays (a string and an int) to a function in C++

I'm aware that when you write the call for your function you write it as displayArray(seasons,10)
with the name of one array and its size. I'm stuck on how you would right the arguments to pass the two arrays listed in my code, seasons and cartoons.
#include<iostream>
#include<string>
#include<iomanip>
using namespace std;
void displayArray(string car[], int sea[], int size);
int main()
{
int seasons[] = {5,10,8,2,12,7,31,9,3,4};
string cartoon[] = { "Steven Universe","Adventure Time","Regular Show","Gravity Falls",
"Spongebob Squarepants","Futurama","The Simpsons","Bob's Burgers","Avatar: The Last Airbender","Rick and Morty"};
displayArray() // Error Message here
}
void displayArray(string car[], int sea[], int size)
{
for (int x = 0; x < size; x++)
{
cout << " " << car[x] << "\t\t" << sea[x] << right << endl;
}
}
So you have to first create an array to pass your values with. Then just pass the array.
void function(int arr[]) {}
int arr[] = { 1, 2, 3, 4, 5 };
function(arr);
So in your code above, it should look like this:
int main()
{
int seasons[] = {5,10,8,2,12,7,31,9,3,4};
string cartoon[] = { "Steven Universe","Adventure Time","Regular Show","Gravity Falls",
"Spongebob Squarepants","Futurama","The Simpsons","Bob's Burgers","Avatar: The Last Airbender","Rick and Morty"};
displayArray(cartoon, seasons, 10);
}
Hope this helps :)
displayArray(cartoon, seasons, 5);
This seems to work fine for me. You just pass each array in according to whichever is declared first in the function argument list. Am I misunderstanding your question?

A pointer to const int in c++

In c++ I have the next code
int main() {
int i = 1;
cout<<"i = "<<i<<endl; //prints "i = 1"
int *iPtr = &i;
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 1"
(*iPtr) = 12; //changing value through pointer
cout<<"i = "<<i<<endl; //prints "i = 12"
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 12"
system("pause");
return 0;
}
Now the same code with constant integer i
int main() {
const int i = 1;
cout<<"i = "<<i<<endl; //prints "i = 1"
int *iPtr = (int*)&i; //here I am usint a type conversion
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 1"
(*iPtr) = 12; //changing value through pointer
cout<<"i = "<<i<<endl; //prints "i = 1"
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 12"
system("pause");
return 0;
}
As you can see, in second case with constant integer, there are two different values for *iPtr and const i, but the pointer *iPtr shows to constant i.
Please tell me what happens in the second case and why?
Your second code has undefined behavior. You can't change const data via a pointer-to-non-const. You are lucky your code didn't simply crash outright when trying to modify a read-only value.
In any case, the result you are seeing is because the compiler knows that i is const and has a value that is known at compile time. So the compiler is able to optimize away i in the cout statement and use 1 directly instead. That is why you see 1 when printing i and see 12 when printing *iPtr.
You are trying to remove the const qualifier of your variable.
In C++, you should use const_cast to do that.
However, const_cast can only be used in some precise circomstances: constness should only be removed from pointers/references to data which have been declared non-const at top level, otherwise the compiler may optimize the variable and modifying it through the pointer/reference would result in undefined behaviour.
For example, this is not legal :
const int i = 1;
const int *iPtr = &i;
int *iSuperPtr = const_cast<int*>(iPtr);
*iSuperPtr = 2; // Invalid : i is first declared const !!
But this is totally legal :
void modifyConstIntPtr(const int *iPtr) {
int *iSuperPtr = const_cast<int*>(iPtr);
*iSuperPtr = 2; // Valid : i is first declared non-const !!
}
void modifyConstIntRef(const int &iRef) {
int &iSuperRef = const_cast<int&>(iRef);
iSuperRef = 3; // Valid : i is first declared non-const !!
}
int main() {
int i = 1;
modifyConstIntPtr(&i);
std::cout << i << std::endl;
modifyConstIntRef(i);
std::cout << i << std::endl;
}
This aspect of C++ is well detailed here: https://stackoverflow.com/a/357607/3412316)

Error in program with structures and pointers (Structures, C++)

I have a structure , which contains three variables under the object list.-Names, registration nos, amount.
struct vendor
{
int reg, amt;
char add[30];
}list[10];
I have made a function to find the minimum amount(amt) ,using the referencing concept.
int low(vendor *p, int n)
{
int i;
min = (p->amt);
for(i =1;i<n;i++)
{
if(min > *(p->amt))
{
min = *(p->amt);
}
p++;
}
return min;
}
In the main I have included the syntax:
low(list, n);
I am getting an error:
Invalid argument of unary '*' operator.
I have tried using the dot operator also and is not working.
This is my first program in pointers in structs with functions.
Can you please point out the error in the code.
Thank You very much
Anupam
(Update) the full code:
#include <iostream>
using namespace std;
struct vendor
{
int reg, amt;
char add[30];
}list[10];
int low(vendor *p, int n)
{
int i;
min = (p->amt);
for(i =1;i<n;i++)
{
if(min > (p->amt))
{
min = (p->amt);
}
p++;
}
return min;
}
int main()
{
int i;
int fa;
int n,fr;
cin >> n;
for(i =0;i<n;i++)
{
cin >>list[i].reg>>list[i].add>>list[i].amt;
// Enter reg no. , address and amount.
}
low(list, n); // Calling function
for(i = 0;i<n;i++)
{
if(fr == list[i].amt)
// This is to check for position of least amount.
// For printing the reg no. and address of least amt.
{
fa = i;
}
}
cout << fr <<"\n" << fa <<endl;
// print the reg no. and address of least amt.
}
Errors:
Overloaded function with no contextual type information.
Invalid operands of types <unresolved overloaded function
Cannot resolve overloaded function
The declaration for min is missing in low() function.
int min = (p->amt);
This should help you compile your code.
p is a pointer to a vendor. *p is a vender. p->amt is an int.
So when you want the amt of an object that is pointed to by p you can do it in one of two ways: p->amt or (*p).amt
You fix your code by using p->amt or (*p).amt. *p->amt or *(p->amt) are invalid.
p is a object of vendor which type is pointer . "->" is used to use pointer object . So use p->amt .
you can also use (*p).amt .
Updated Answer :
decleration of min is missing . please use this :
int min = p->amt ;
or use this :
int min = (*p).amt;

why cannot pass parameter like this?

I have a function:
int getCaseNum(float isovalue,float *F,int **point,int *dims,float *F_value)
{
int digtial_point[8];
int case_num=0;
int i = 0;
for(i=0;i<8;i++)
{
F_value[i] = F[GetPointIndex(point[i],dims)];
if(F_value[i]>isovalue)
{
digtial_point[i] = 1;
case_num = case_num + powf(2,i);
}
else
{
digtial_point[i] = 0;
}
}
return case_num;
}
Then I want to call this function in another function like this:
int pointID[8][3];
int case_num = getCaseNum(isovalue,F,pointID,dims,F_value);
However, when I compile my code, it says:
/Users/liyuanliu/Documents/lecture/sicvis/final_6b/mc510/proj6B.cxx:862:24: error:
no matching function for call to 'getCaseNum'
int case_num = getCaseNum(isovalue,F,pointID,dims,F_value);
^~~~~~~~~~
/Users/liyuanliu/Documents/lecture/sicvis/final_6b/mc510/proj6B.cxx:816:5: note:
candidate function not viable: no known conversion from 'int [8][3]' to
'int **' for 3rd argument
int getCaseNum(float isovalue,float *F,int **point,int *dims,float *F_value)
^
Why this happens ? Cannot I pass parameter like this?
// Create a dynamic 2D int array
int **pointID=new int*[8];
for(int i=0;i<8;i++) {
pointID[i]=new int[3];
}
int case_num=getCaseNum(isovalue,F,pointID,dims,F_value);
you need to get a pointer to first entry in 2D array.
Since array is contiguous, you can use below logic to iterate
int getCaseNum(float isovalue,float *F,int* point,int *dims,float *F_value)
{
for (i = 0; i < 24; i++)
{
cout << *(point+i*sizeof(int));
}
}
caller:
int case_num = getCaseNum(isovalue,F,&pointID[0][0],&dims,F);

Class accept and return array

I try to create a class that accept and return an array but I got some problem. I'm not sure if it is legal to return an array from a class. Or it could be done by returning an pointer to the array. Thank for any solution to the problem.
#include <iostream>
using namespace std;
class myclass {
private:
int Array[10];
public:
myclass (int temp[10]) {
for (int i = 0; i < 10; i++) {
Array [i] = temp [i];
}
}
int returnArray () {
return Array; // error here, I'm not sure if it is legal to return an array.
}
int* returnArray2 () {
return this->Array; // hope it will return a pointer to the array
}
};
int main () {
int Array[10] = {1,2,3,4,5,6,7,8,9};
myclass A(Array);
cout << A.returnArray() << endl; // try to return an array and print it.
myclass* ptr = &A;
cout << *ptr->returnArray2 << endl; // error here
return 0;
}
First of all it is better to write the constructor either like
myclass ( const int ( &temp )[10] ) {
for (size_t i = 0; i < 10; i++) {
Array [i] = temp [i];
}
}
or like
myclass ( int temp[], size_t n ) : Array {} {
if ( n > 10 ) n = 10;
for (size_t i = 0; i < n; i++) {
Array [i] = temp [i];
}
}
Or even you may define the both constructors.
As for the returning value then you may not return an array. You may return either a reference to an array or a pointer to the entire array or a pointer to its first element
For example
int ( &returnArray () )[10] {
return Array;
}
In this case you can write in main
for ( int x : A.returnArray() ) std::cout << x << ' ';
std::cout << std::endl;
As for this statement
cout << *ptr->returnArray2 << endl; // error here
then you forgot to place parentheses after returnArray2. Write
cout << *ptr->returnArray2() << endl;
And the following member function is wrong because the expression in the return statement has type int * while the return type of the function is int
int returnArray () {
return Array; // error here, I'm not sure if it is legal to return an array.
}
So either the function will coincide with the the second member function if you specify its return type like int *. Or you could change the return expression to *Array
int returnArray () {
return Array; // error here, I'm not sure if it is legal to return an array.
}
This is illegal because Array is not of int type. Your returnArray2 is valid, however. As for this line:
cout << *ptr->returnArray2 << endl; // error here
This is illegal because returnArray2 is a function; you must call it to return the int*:
cout << *ptr->returnArray2() << endl; // prints the first value in the array
Other notes:
Your capitalization is backwards; you should call your class MyClass and your member array arr or arr_, or you will confuse a lot of people.
return this->Array; this is redundant, you can simply return Array;
If you haven't heard of std::vector and std::array you should research those, as they are generally superior to C-style arrays.
In general, I would suggest to read a c++ book to get your basics correct as there are lot of issues in the code you posted.
Regarding your main question about exposing C style arrays in class public API, this is not a very robust mechanism. Do it if it is absolutely essential because of existing code but if possible prefer to use std::vector. You will mostly always end up with better code.
Other answers have corrected your coding errors, so i won't repeat that.
One other thing, your code suggests that the array size is fixed. You can pass and return the array by reference as well. Refer to: General rules of passing/returning reference of array (not pointer) to/from a function?