I can't able to understand , so please help me .
Whrn we are passing the array to any function and then we write the array type in function parameter to fetch it but why we are not initialize its size in the parameter .
Of course you could specify (fixed) size of array as function parameter - you have to pass array by reference.
void func(int (&x)[100]);
is passing array of int with size 100.
You could even make a template for it
template<class T, size_t N> void func(T (&x)[N]) {...}
In C++, always prefer containers to raw pointers or arrays when possible.
Array types in function signatures are actually pointers. The following three declarations are all exactly the same:
void foo(int a[10]);
void foo(int a[]);
void foo(int* a);
In all three cases, foo takes a single parameter: a pointer to an int. When you pass an array to that function, it implicitly decays to a pointer to its first element.
When an array decays into a pointer, the length of the array is lost. That means the following code will compile, but is logically wrong:
void foo(int a[10]) {
for (size_t i = 0; i < 10; ++i) {
std::cout << a[i] << '\n';
}
}
int main() {
// Whoops, wrong size array!
int arr[5] = {};
foo(arr);
}
Live Demo
The length declaration, in this case, is a complete and total lie. Writing a meaningless number in the function definition just increases the risk someone will make an error.
If you must use raw pointers for a function parameter accepting an array, your function should also accept a size parameter:
void foo(int* a, size_t length) {
for (size_t i = 0; i < length; ++i) {
std::cout << a[i] << '\n';
}
}
int main() {
int arr[5] = {};
foo(arr, 5);
}
Live Demo
This is also dangerous though, since it's entirely possible for someone to pass the wrong size and cause errors:
void foo(int* a, size_t length) {
for (size_t i = 0; i < length; ++i) {
std::cout << a[i] << '\n';
}
}
int main() {
int arr[5] = {};
//Whoops, passed the wrong size!
foo(arr, 10);
}
Live Demo
For that reason, you should prefer to use a container:
void foo(const std::vector<int>& a) {
for (int i : a) {
std::cout << i << '\n';
}
}
int main() {
std::vector<int> arr(5);
foo(arr);
}
Live Demo
If you don't know what type of container to use; default to std::vector. If your function must support multiple types of containers, use a template:
template <typename Container>
void foo(const Container& a) {
for (int i : a) {
std::cout << i << '\n';
}
}
int main() {
std::vector<int> arr(5);
foo(arr);
std::array<int, 5> arr2 = {};
foo(arr2);
}
Live Demo
Related
I'm trying to write an example code for the following line of code:
int (*(*foo)(const void*))[3];
I got this code from here (at each refresh of the website you get a different piece of code and there is a finite set of them so by reloading a couple of times you will get my example). I wanted to see out of curiosity is it even possible to write some code that would make this line work.
Here is what I wrote so far:
#include<stdio.h>
#include<malloc.h>
int* goo(const void * ptr) {
int* ret = (int*) malloc(sizeof(int) * 3);
if (!ret)
return NULL;
for (int i = 0; i < 3; ++i)
ret[i] = i;
return ret;
}
int doo() { return 0; }
int main(void) {
//NOTE: Following 2 lines have syntax errors
int (*(*foo)(const void*))[3] = &goo;
int* values = foo(goo(doo));
for (int i = 0; i < 3; ++i) {
printf("%d", values[i]);
}
free(values);
return 0;
}
If I understood correctly, foo should be some function that receives as an argument another function and returns an int array of size 3. The problem is I don't know how to make foo in this case point to a function or even how to get the int array.
Is it even possible to make this line of code work?
If I understood correctly, foo should be some function
foo is a pointer to a function.
that receives as an argument another function
No, the parameter type of the function that foo points to must be a pointer to const void i.e. const void*. A pointer to void is an object pointer. It can point to an object of any type.
Functions are not objects, but on some systems, pointers to functions can be reinterpreted as pointers to void.
and returns an int array of size 3.
No; Return types cannot be arrays. The function must return a pointer to an array of 3 ints i.e. int(*)[3].
Is it even possible to make this line of code work?
Here is an example program that uses such foo. It doesn't make much sense, but that's because the goal is to use an obscure function pointer:
#include<iostream>
int arr[] {
1,
2,
3,
};
int (*goo(const void*))[3] {
return &arr;
}
int main() {
int (*(*foo)(const void*))[3] = &goo;
int (*values)[3] = foo(nullptr);
for (int i : *values) {
std::cout << i << " ";
}
}
We can greatly improve readability by introducing type aliases:
using IntArr3 = int[3];
using FooFun = IntArr3*(const void*);
IntArr3* goo(const void*) {
return &arr;
}
int main() {
FooFun* foo = &goo;
IntArr3* values = foo(nullptr);
for (int i : *values) {
std::cout << i << " ";
}
}
This works:
void foo(int (&a)[3]) {
auto ibegin = begin(a);
auto ebegin = end(a);
}
While this doesn't:
void foo(int (*a)[3]) {
auto ibegin = begin(a);
auto ebegin = end(a);
}
I consider int (&a)[3] and int (*a)[3] have the same meaning!
Your code is analogous to:
void foo(vector<int>& a) {
auto ibegin = begin(a);
auto ebegin = end(a);
}
void foo(vector<int>* a) {
auto ibegin = begin(a);
auto ebegin = end(a);
}
The first one works and the second one doesn't for the same reason as it works on int (&a)[3] and doesn't on int (*a)[3]. When you're using pointers to collections instead of references, you need to dereference them when you pass them to the standard library's begin/end.
void foo(vector<int>* a) {
auto ibegin = begin(*a);
auto ebegin = end(*a);
}
void foo(int (*a)[3]) {
auto ibegin = begin(*a);
auto ebegin = end(*a);
}
I consider int (&a)[3] and int (*a)[3] have the same meaning!
Absolutely not. int (&a)[3] declares a reference to array, and int (*a)[3] declares a pointer to array. These are different in most of the same ways a reference to int and a pointer to int are different. (Though when C-style arrays are involved, the automatic array-to-pointer conversion sometimes complicates things.)
I consider int (&a)[3] and int (*a)[3] have the same meaning!
No! The first one is a reference to an array, the second is a pointer to an array.
In C++14 std::begin and std::end are defined as:
template<class T, std::size_t N>
constexpr T* begin(T (&array)[N]) noexcept;
template<class T, std::size_t N>
constexpr T* end(T (&array)[N]) noexcept;
Clearly, the functions take a reference to an array, not a pointer.
You may understand the difference in function overloading where the three are respectively reference to array, pointer to array and array of pointers. So they don't have the same meaning.
#include <iostream>
void foo(int (&a)[3]) {
std::cout << "(&a)[3]" << std::endl;
}
void foo(int (*a)[3]) {
std::cout << "(*a)[3]" << std::endl;
}
void foo(int *a[3]) {
std::cout << "*a[3]" << std::endl;
}
int main() {
int m[3];
int *n[3] = {m + 0, m + 1, m + 2};
foo(m); // (&a)[3]
foo(&m); // (*a)[3]
foo(n); // *a[3]
}
The & symbol is getting the location of the pointer in (&a) you are getting the address of a at location 0 in the array.
While *a is getting the value stored at a[0] this is called dereferencing a pointer. For example:
int * a = {0,1,2};
&a[0] //gets value of the memory pointer of a[0], maybe 0xff123
*a[0] //dereferences the pointer at [0] in this gets case '0'.
For a more complete look at pointers, I'd check out: What does "dereferencing" a pointer mean?
I have this struct:
struct noduri {
int nod[100];
};
and this function:
int clearMatrix(int var)
{
cout << all[1].nod[30];
}
int main()
{
noduri all[100];
cout << all[1].nod[30];
return 0;
}
and I want the struct to be assigned to all 100 elements of array all[], when I do cout << all[1].nod[30]; everything works fine, no errors, it outputs 0. When I call clearMatrix(1) I get this error : error: request for member nod in all[1], which is of non-class type int, what am I doing wrong ?!
The array variable all is local to the main function, so you cannot reference it in clearMatrix unless you pass a pointer to it into the function:
int clearMatrix(int var, noduri *all)
{
cout<<all[1].nod[30];
}
int main()
{
noduri all[100];
clearMatrix(5, all);
return 0;
}
you are reffering in the function that array which is not in its scope, you need to do it as
int clearMatrix(int var,noduri *all)
{
cout<<all[1].nod[30]; // as here you have the base address of the array of type noduri you can refer it.
}
int main()
{
noduri all[100];
clearMatrix(5, all);
return 0;
}
You are using raw arrays. That's not a good idea. Use std::vector if the size if not known at compile time, consider std::array if it is known at compile time and dynamic resizing would cause measurable performance problems.
One of the problems with raw arrays in C++ is that it's not at all(!) as easy to pass them to a function like, say, an int or a double. std::vector and std::array, in contrast, are as easy to pass to a function like any other normal type.
Here's a complete example:
#include <array>
#include <iostream>
struct noduri {
std::array<int, 100> nod;
};
void clearMatrix(std::array<noduri, 100> const &array) {
std::cout << array[1].nod[30];
}
int main() {
std::array<noduri, 100> all;
std::cout << all[1].nod[30];
}
Note that std::array is only available if your compiler supports C++11. For an older compiler, use boost::array or just do it with a std::vector.
The code you showed will not be compiled and has no any sense. If I have understood correctly you want to assign each element of the array by some value in function clearMatrix. If so then the code will look the following way
#include <iostream>
struct noduri
{
int nod[100];
};
int clearMatrix( noduri *matrix, int size, int var )
{
for ( int i = 0; i < size; i++ )
{
for ( int &n : matrix[i].nod ) n = var;
}
}
int main()
{
const int N = 100;
noduri all[N] = {};
std::cout << all[1].nod[30] << std::endl;
clearMatrix( all, N, 10 );
std::cout << all[1].nod[30] << std::endl;
return 0;
}
Here's a simple (and a silly one, yeah) example of what I'm trying to do:
#include <iostream>
void callFunctionsFromAnArray(void *(*)(int), int);
void f1(int);
void f2(int);
void f3(int);
int main()
{
const int n = 3;
void (*functions[n]) (int) = { f1, f2, f3 };
callFunctionsFromAnArray(functions, n);
}
void callFunctionsFromAnArray(void *(*f) (int), int fCount) {
for (int i = 0; i < fCount; i++)
f[i](1);
}
void f1(int a)
{
std::cout << a * 1 << '\n';
}
void f2(int a)
{
std::cout << a * 2 << '\n';
}
void f3(int a)
{
std::cout << a * 3 << '\n';
}
And those are the errors I'm getting when trying to compile:
12:9: error: no matching function for call to 'callFunctionsFromAnArray'
callFunctionsFromAnArray(functions, n);
3:10: note: candidate function not viable: no known conversion from 'void (*[3])(int)' to 'void *(*)(int)' for 1st argument
void callFunctionsFromAnArray(void *(*)(int), int);
17:13: error: subscript of pointer to function type 'void *(int)'
f[i](1);
2 errors generated.
However, if I change argument to be void (*f[3]) (int) it works. But the problem is, it's not always possible to know array's size before run-time (that's why function has 2nd argument after all). Is there any solution?
Since in this case, the array decays into a pointer, you don't have to know its size beforehand -- inside a function argument declaration, and only there, the pointer and the array qualifier (* and []) are equivalent, and the size of the array doesn't matter.
As a result, you can declare your function to take an array of 3 (or however many) pointers, and then you can pass it an array of any pointers:
void callFunctionsFromAnArray(void *(*f[1])(int), int fCount)
{
for (int i = 0; i < fCount; i++)
f[i](i);
}
However, if you don't like this, you can just make it accept a pointer-to-pointer:
void callFunctionsFromAnArray(void *(**f)(int), int fCount); // etc.
However, if this really is C++, you'd be better off passing a const reference to a vector of std::functions:
void callFunctionsFromAnArray(const std::vector<std::function<void *(int)> > &a)
{
// call'em
}
Since you are using C++ and not C, I highly suggest you to use std::vector and std::function instead. They will make your life much easier, especially in this particular case:
#include <functional>
#include <vector>
void f1(int);
void f2(int);
void f3(int);
using function_vector = std::vector<std::function<void(int)>>;
void callFunctions(const function_vector& vec) {
for (const auto& f : vec)
f(1);
}
int main() {
function_vector vec = { &f1, &f2, &f3 };
callFunctions(vec);
}
You can see a live example here.
This is the working program to pass an array in a function, but I am not able to understand that in the print function only the base address of the array is passed but still I am able to access the array with subscript a[i]. I know the correct method will be *(a+i) but why does it work with the subscript too?
#include <iostream>
#include <conio.h>
void print(int *a);
using namespace std;
int main()
{
int arr[3]={1,2,3};
print(arr);
getch();
return 0;
}
void print(int *a)
{
for(int i=0;i<3;i++)
{
cout<<a[i];//how we are able to access array with subscipt a[i]
}
}
Since you are passing a pointer (pointing to a specific memory address) you can treat it as usual even inside the function. Pointers and arrays are very closely related and the use is just fine.
a[0] and *a are the same thing, so are a[1] and *(a+1) etc.
"A pointer is equivalent to the address of the first element that it points to" - from http://www.cplusplus.com/doc/tutorial/pointers/
The array can be passed like that, but the other way is to put name of the array followed by empty []:
#include <iostream>
#include <conio.h>
void print(int *a);
using namespace std;
int main()
{
int arr[3]={1,2,3};
print(arr);
getch();
return 0;
}
void print(int a[])
{
for(int i=0;i<3;i++)
{
cout<<a[i];//how we are able to access array with subscipt a[i]
}
}
both methods pass the address of the first number in array, so both methods work.
//how we are able to access array with subscipt a[i]
a[i] is the same thing as *(a + i).
As it is now, your print will only work for arrays of the exact size 3, so:
If the array happens to have more than 3 elements, some elements will not be printed.
If it happens to have less than 3, you'll access whatever is in memory behind the array, which is undefined behavior (translation: very bad!).
The size of the array gets "forgotten" when you pass the array to a function, so either explicitly pass the size to make the function reusable for arrays of all sizes (reusability is the point of having functions after all!)...
void print(int const* a, size_t a_size) {
for (size_t i = 0; i < a_size; ++i) // size_t is the appropriate type here, not int.
std::cout << a[i] << std::endl; // Use std::endl to be able to discern where teh current number ends and the next starts!
}
// ...
int arr[3] = {1, 2, 3};
const size_t arr_size = sizeof(arr) / sizeof(arr[0]);
print(arr, arr_size);
...or do it in the C++ way and use std::vector...
void print(const std::vector<int>& a) {
for (const auto& s : a) // The new C++11 "for each" syntax.
std::cout << s << std::endl;
}
// ...
std::vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
print(a);
...or even make it generic...
template <typename T>
void print(const std::vector<T>& a) {
for (const auto& s : a)
std::cout << s << std::endl;
}