#include<iostream>
using namespace std;
int number(int (&a)[10])
{
int n= sizeof(a)/sizeof(a[0]);
return n;
}
int main()
{
int n;
cout << " Enter the number of elements ";
cin >> n;
int a[10];
cout << "Enter array elements : ";
for(int i=0;i<n;i++)
cin>>a[i];
cout<<" The number of elements according to main is "<< sizeof(a)/sizeof(a[0])<<endl;
cout<<" The number of elements in the function number is " << number(a);
}
In the above code in the main function "number(a)" Here what exactly are we passing and what is taken by the method. and how does the code work in the function.and what is happening if we are not using "&" symbol in the number function.
My understanding is we are passing a pointer to the first element into the function but I dont know properly.
When you call number(a), you are passing a reference to the array of 10 ints.
Let's take a simpler function.
void foo(int& ref) { }
You can call it with
int i = 20;
foo(i);
Here, a reference to the variable i passed to the function. You can access the value of the variable i in foo through ref. Any changes you make to ref in foo will be visible in the calling function.
Similarly, your function takes a reference to a variable whose type is "an array of 10 ints". The only thing the function does with the reference is compute the number of elements of the array.
It uses a bit of redundant logic. You can simplify that function to:
int number(int (&a)[10])
{
return 10;
}
The function is limited in what it can work with. It is not going to work if you have an array of type float or if you have an array of 20 elements. You can create a template function to make it more general.
template <typename T, size_t N>
size_t number(T (&arr)[N])
{
return N;
}
The above function will work with arrays of different object types and sizes.
Related
I am trying to write a function that prints out the elements in an array. However when I work with the arrays that are passed, I don't know how to iterate over the array.
void
print_array(int* b)
{
int sizeof_b = sizeof(b) / sizeof(b[0]);
int i;
for (i = 0; i < sizeof_b; i++)
{
printf("%d", b[i]);
}
}
What is the best way to do iterate over the passed array?
You need to also pass the size of the array to the function.
When you pass in the array to your function, you are really passing in the address of the first element in that array. So the pointer is only pointing to the first element once inside your function.
Since memory in the array is continuous though, you can still use pointer arithmetic such as (b+1) to point to the second element or equivalently b[1]
void print_array(int* b, int num_elements)
{
for (int i = 0; i < num_elements; i++)
{
printf("%d", b[i]);
}
}
This trick only works with arrays not pointers:
sizeof(b) / sizeof(b[0])
... and arrays are not the same as pointers.
Why don't you use function templates for this (C++)?
template<class T, int N> void f(T (&r)[N]){
}
int main(){
int buf[10];
f(buf);
}
EDIT 2:
The qn now appears to have C tag and the C++ tag is removed.
For C, you have to pass the length (number of elements)of the array.
For C++, you can pass the length, BUT, if you have access to C++0x, BETTER is to use std::array. See here and here. It carries the length, and provides check for out-of-bound if you access elements using the at() member function.
In C99, you can require that an array an array has at least n elements thusly:
void print_array(int b[static n]);
6.7.5.3.7: A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to
type’’, where the type qualifiers (if any) are those specified within the [ and ] of the
array type derivation. If the keyword static also appears within the [ and ] of the
array type derivation, then for each call to the function, the value of the corresponding
actual argument shall provide access to the first element of an array with at least as many
elements as specified by the size expression.
In GCC you can pass the size of an array implicitly like this:
void print_array(int n, int b[n]);
You could try this...
#include <cstdio>
void
print_array(int b[], size_t N)
{
for (int i = 0; i < N; ++i)
printf("%d ", b[i]);
printf("\n");
}
template <size_t N>
inline void
print_array(int (&b)[N])
{
// could have loop here, but inline forwarding to
// single function eliminates code bloat...
print_array(b, N);
}
int main()
{
int a[] = { 1, 2 };
int b[] = { };
int c[] = { 1, 2, 3, 4, 5 };
print_array(a);
// print_array(b);
print_array(c);
}
...interestingly b doesn't work...
array_size.cc: In function `int main()':
array_size.cc:19: error: no matching function for call to `print_array(int[0u])'
JoshD points out in comments below the issue re 0 sized arrays (a GCC extension), and the size inference above.
In c++ you can also use a some type of list class implemented as an array with a size method or as a struct with a size member(in c or c++).
Use variable to pass the size of array.
int sizeof_b = sizeof(b) / sizeof(b[0]); does nothing but getting the pre-declared array size, which is known, and you could have passed it as an argument; for instance, void print_array(int*b, int size). size could be the user-defined size too.
int sizeof_b = sizeof(b) / sizeof(b[0]); will cause redundant iteration when the number of elements is less than the pre-declared array-size.
The question has already some good answers, for example the second one. However there is a lack of explanation so I would like to extend the sample and explain it:
Using template and template parameters and in this case None-Type Template parameters makes it possible to get the size of a fixed array with any type.
Assume you have such a function template:
template<typename T, int S>
int getSizeOfArray(T (&arr)[S]) {
return S;
}
The template is clearly for any type(here T) and a fixed integer(S).
The function as you see takes a reference to an array of S objects of type T, as you know in C++ you cannot pass arrays to functions by value but by reference so the function has to take a reference.
Now if u use it like this:
int i_arr[] = { 3, 8, 90, -1 };
std::cout << "number f elements in Array: " << getSizeOfArray(i_arr) << std::endl;
The compiler will implicitly instantiate the template function and detect the arguments, so the S here is 4 which is returned and printed to output.
In my understanding array in int array[]={1,2,3,4,5} is just a pointer to the first element of array. It means that array can be assigned to a pointer ptr of type int*.
Parameter int* &p in hoo will pass the argument by reference. It means we can change the passed argument to point to another value from within the hoo.
void hoo(int* &p, int n)
{
for (int i = 0; i < n; i++)
cout << p[i] << endl;
}
int main()
{
int array[] = { 1,2,3,4,5 };
// I can do this
int* ptr = array;
hoo(ptr, 5);
// but not this.
//hoo(array, 5);
}
Question
Why can't we pass int array to hoo without ptr ?
In my understanding array in int array[]={1,2,3,4,5} is just a pointer to the first element of array.
This is not correct. Arrays are arrays and pointers are pointers. They are distinct types with distinct properties. They are often confused because an array has the property that it will eagerly decay to a pointer to its first element.
hoo(array, 5); tries to convert array to an int* but the result of that conversion is an rvalue and can't be bound to a non-const reference. If, for example, you changed hoo to take a const reference it will compile fine :
void hoo(int* const &p, int n) { }
int main()
{
int array[] = { 1,2,3,4,5 };
hoo(array, 5);
}
In that case, you cannot change what p points to, making the use of a reference pointless.
When a function takes an int* & parameter, that is, a (non-move) reference to a pointer-to-an-int - then there needs to be a bona fide pointer variable to which that reference is referring. It can't be a temporary pointer value. Thus you can't do:
int x;
hoo(&x, 123);
because there's no pointer variable to refer to - just the temporary. It's essentially the same thing with your int[5]. There isn't actually an int* variable anywhere - there are just 5 ints. When you pass array to hoo(), what C++ does with that identifier is an array-to-pointer decay: It actually passes &(array[0]). So just like in the previous case, that won't compile.
The other answers already explain the problem. I want to suggest a change of coding practice.
Use of void hoo(int* &p, int n) as function declaration is very very old style. Using templates, you can let the compiler deduce the size and get a reference to the array, which obviates the need for using a pointer.
template <size_t N>
void hoo( int (&p)[N]) // The argument is a reference to an array of N elements.
{
for (int i = 0; i < N; i++)
cout << p[i] << endl;
}
The call to the function becomes natural.
int array[] = { 1,2,3,4,5 };
hoo(array);
If your function needs to be able to support dynamically allocated arrays as well, you can overload the function as follows.
void hoo(int* p, size_t N)
{
for (int i = 0; i < N; i++)
cout << p[i] << endl;
}
template <size_t N>
void hoo( int (&p)[N]) // The argument is a reference to an array of N elements.
{
hoo(p, N);
}
using namespace std;
#include<iostream>
int passarr(int b[],int s)
{
//Some Modification in the array b
b[0]=0;
b[s-1]=0;
//Printing the array b
for(int i=0;i<s;i++)
{
cout<<b[i]<<" ";
}
cout<<endl;
}
int main()
{
int arr[100];
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>arr[i];
}
//Function call and passing array a to the function`
passarr(arr,n);
//Printing the array arr
for(int i=0;i<n;i++)
{
cout<<arr[i]<<" ";
}
}
In this code, I have passed array arr to function passarr() which performs some modifications. The problem is that modifications reflect on the original array too. Is there any way to pass the array to a function so that the original array does not get changed while performing any operation in the function?
Is there any way to pass the array to a function so that the original array does not get changed while performing any operation in the function?
Choices that I can think of:
Make a copy of the array in the function and modify the copy. Leave the input array untouched.
Pass a std::vector by value. Any changes to the argument won't affect the object in the calling function.
If you know the size of the array at compile time, pass a std::array by value. Any changes to the argument won't affect the object in the calling function.
As indicated by the answer of R Sahu, if you do not want to make a copy, there is not much you can do within the constraint of the Standard.
However, you could keep track of your changes in a different data-structure. A possibility would be std:map<class key, class value>:
The key of the map would be the array index of type int
The value is the modified value of your original array.
From this point forward you only need to do a conditional check if the array index is in the map. This could be done using 'std::map::find'. Thus :
If the array index is in the std::map, return the value in std::map
If the array index isn't in the std::map, return the original array value
If you do a sequential array traversal, this can be sped up by using the property of the map traversal. In the presented example, this could be :
int passarr(int b[],int s) {
std::map<int,int> mod;
std::map<int,int>::iterator it;
//Some Modification in the array b
mod[0]=0;
mod[s-1]=0;
//Printing the array b
it=mod.begin();
for(int i=0;i<s;i++) {
if (i == it->first) {
std::cout << it->second << " ";
it++;
else { std::cout<<b[i]<<" "; }
}
std::cout<<endl;
}
I am a student who is doing an assignment for C++ and I have encountered something I am very unfamiliar with. I have an int array with no size but a list of numbers. After it's creation, there is a function call inside a function that has that array as a parameter with an index in it.
For example:
for (int x = 0; x < CAPACITY, x++)
functionCall(array[x]);
Now I am supposed to create a function so the call can work. However when I make my function:
void functionCall(int array[]);
It does not work because it cannot turn an int to an int[].
I guess my question is, how am I supposed to get that list of numbers created originally by the array if I have to call it in my function as if it isn't an array.
Right now if I just put as an int but not an array like it wants me to do it just gives me the number 5 but not any of the numbers in the array. For example:
void functionCall(int array);
Sincere thank you for anything and I apologize if this sounds confusing.
functionCall(array[x]);
This passes the xth element in the array to the function, so a single int.
array[2] = 5;
functionCall(array[2]); // This is the same as functionCall(5);
So in the function, you get the current element of the array. Not the array itself.
You cannot get the list inside the function, because you only give a single element of that list each time you call it.
Taking a wild guess, I suspect you are looking for something like the MCVE below:
#include <iostream>
void functionCall(int v) {
std::cout << v << " ";
}
void func(int array[], size_t CAPACITY) {
for (size_t x = 0; x < CAPACITY; x++)
functionCall(array[x]);
}
int main() {
int list[] = { 1,2,3,4,3,0, 42 };
func(list, std::distance(std::begin(list), std::end(list)));
return 0;
}
I was studying LISTs and playing with function, this program gives 10 number and each time if the entered number is the bigger than the maximum value in our list, that number will be added to our list and finally after 10 tries all members will show up. The program works fine, but what I don't understand is why do I need use "&" in the line 6: " void insertMax(list &lst, int n) {"??
#include <iostream>
#include <list>
using namespace std;
void insertMax(list<int> &lst, int n) {
lst.sort();
int max = lst.back();
if (n > max) {
lst.push_back(n);
}
}
void disply(list<int> lst) {
list<int>::iterator iter = lst.begin();
while (iter!=lst.end()){
cout << *iter << endl;
iter++;
}
}
int main()
{
list<int> numbers;
numbers.push_back(0);
int input=0;
for (int j = 1; j < 11; j++){
cout << "Enter a number: " << endl;
cin >> input;
insertMax(numbers, input);
}
cout << "Now that's all: " << endl;
disply(numbers);
return 0;
}
Thanks in advance.
So you pass a reference to the list rather than a copy of it.
Google "pass by reference" and "pass by value".
Pass by reference means you don't have to make a copy of the whole data structure you are passing (which could be slow - especially if you have a big list)
Having said that, you're question is not quite clear: "Why is & needed during calling this list?" - Line 6 is not a call, it's the declaration of the function signature. So it's saying "When you call me I expect you to pass a reference to a list of ints"
By putting the ampersand (&) in, you specify that the list be taken as a reference, instead of being copied into the function scope. By taking it as a reference you can manipulate the external object.
http://www.cprogramming.com/tutorial/references.html
If I have understood correctly the line 6 is the starting line of the function definition
void insertMax(list<int> &lst, int n) {
lst.sort();
int max = lst.back();
if (n > max) {
lst.push_back(n);
}
}
Symbol & in the first parameter declaration means that the parameter will be a refence to the original argument. So any changes of the list in the function impact on the original argument.
If to remove this symbol & as for example
void insertMax(list<int> lst, int n) {
//...
the it will mean that the function will deal with a copy of the original argument. In this case any changes of the parameter that is pf the copy of the argument will not impact the original argument.
So the new item will be added to a copy of the list but the list itself will not be changed. It is its copy that will be changed.
If you don't add the '&' (pass by reference), any changes you make to the List inside the InsertMax function will not impact the list in your main method.
This is the reason why you'll sometimes see C++ method signatures declared as
void DoSomething(const std::string &value)
{
/*Method Body*/
}
This is done so all that data in the value string is not copied to a new place in memory. If the DoSomething method needs to modify the value string, it will need to make a copy of it first inside of the function. The const modifier makes sure that the reference is read-only by the method.
For example:
std::string DoSomething(const std::string &value)
{
std:string result = value + "some other data";
return result;
}