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 << " ";
}
}
Related
When we use arrays and pointers this way:
int *g() {
int arr[] = {1, 2, 3};
return arr;
}
int f() {
int *value = g();
for (size_t i = 0; i < 3; i++) {
std::cout << value[i] << " ";
}
std::cout << std::endl;
}
int main(int argc, const char **argv) {
f();
return 0;
}
It is deleted from the stack after function g returns, so we get a segment error in the function f()
But using std::vector this same logic works without any problem:
std::vector<int> g() {
std::vector<int> arr = {1, 2, 3};
return arr;
}
int f() {
std::vector<int> value = g();
for (size_t i = 0; i < value.size(); i++) {
std::cout << value.at(i) << " ";
}
std::cout << std::endl;
}
int main(int argc, const char **argv) {
f();
return 0;
}
I was thinking that this is something related to the fact that we have the std::vector class acting as a container to the array but using a struct as a container delete the array either:
struct T {
int *arr;
};
T g() {
T t;
int arr[] = {1, 2, 3};
t.arr = arr;
return t;
}
int f() {
T value = g();
for (size_t i = 0; i < 3; i++) {
std::cout << value.arr[i] << " ";
}
std::cout << std::endl;
}
int main(int argc, const char **argv) {
f();
return 0;
}
And in this case, g++ allow us to overflow the array pointer memory limits with the index subscription.
Why vectors doesn't share the same problem?
All the elements in the vector essentially count as part of the vector. And notice you are returning the vector, not a pointer to the vector. But you are returning a pointer to (the start of) the array.
When the function g returns, the vector arr is destroyed but that's okay because that's not the same one that is returned. A copy of arr is returned. (Actually, the compiler is clever enough to reuse the same vector instead of copying it and then deleting one - but you can imagine that it makes a copy)
Then f prints values from its own local variable value - no problem.
By contrast, in the pointer version, f is printing values from the local variable arr inside g, which has already been destroyed. If g would return a pointer to a vector, it would have the same problem.
Your intuition was somewhat right it has something to do with the containment of the array inside a struct, what you misunderstand however is the difference between (int[]) and (int*) and probably you don't understand well where memory resides as well.
To clarify:
In C++ C-style array types (int[]), (char[]) etc cannot be returned from a function.
Your function does not return (int[]) it returns int* which is a pointer that points to an an (int[]'s zero element in the stack space of some function f() ) and hence the existence of this (int[]) stops past the lifetime of the function f(), but a dangling pointer was copied to the caller's site;
Try
using int_array = int[4];
int_array f()
{
int_array arr { 1, 2, 3, 4};
return arr; // Does not compile cannot return array
}
int* f2()
{
int_array arr { 1, 2, 3, 4};
return arr; // Compiles because int[4] is implicitly cast to int*
}
In the case of vector, it contains a pointer to a dynamically allocated memory block, acquired through some means(new, malloc, custom user defined allocator, etc) hence this memory block is not bound to the lifetime of a function call, but it is managed by the owner of it. When you return the vector to the caller, the memory block behind continues to exist until a (delete, free, custom-delete) is called on it. The vector does this in it's destructor ( ~vector() ), but before that happening a vector( const vector& ) constructor call occurs that copies the content of one vector to the other. Most compilers will optimize away this operation, as mentioned by another answer.
In the case where you return the struct, the problem is the same, you are not returning an array (int[]) you are returning a pointer. If you were to contain an array inside the struct it would be successfully copied back to caller, because the restriction only applies for arrays and not for user defined types.
Try:
struct Foo {
int arr[4];
};
Foo f()
{
Foo obj{ 1, 2, 3, 4 }; // brace initialization of struct
return obj;
}
int main()
{
Foo obj = f();
for(int i = 0; i < 4; i++)
std::cout << i << ' '; // outputs 1 2 3 4 with no issues
}
As you can see no issues with memory here. That's why the std::array<> from header exists - to wrap C-Style arrays so they can be copied over.
I hope this explains well enough.
In the second method returning vector<int>. The std::vector<int> arr was copied to another a temporary vector<int>, then std::vector<int> arr was destroyed.
Finally, the vector<int> value was assigned with temporary vector<int>, after assigning completed, temporary vector<int> was destroyed as well.
That's what i think happening with your example.
the result of this program (process 9164) exited with code -1073741819.
the program finished and nothing happens.....what should I do to make it run using only pointer without *x[] or x[][2]
#include <iostream>
#include<string>
#include <fstream>
using namespace std;
void sum(int **x) {
int s = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
cout << *(*(x + i) + j) << " ";
s += *(*(x + i) + j);
}
cout << "\n";
}
cout << s;
}
int main() {
int x[3][2] = { {11,15},{19,28},{5,8} };
sum((int**)x);
return 0;
}
Whenever you feel the need to do a C-style cast (like you do with (int**)x) you should take that as a sign you're doing something wrong.
An array of arrays is not the same as a pointer to a pointer.
What happens is that you pass an invalid pointer, and the program will experience undefined behavior and crash.
What should happen is that the array x decay to a pointer to its first element, i.e. plain x is the same as &x[0]. That will be a pointer to an array, with the type int (*)[2] (in the case of x in your question). That is the type you need to use for the function argument:
void sum(int (*x)[2]) { ... }
And call like
sum(x);
You can also generalize to accept any kind of "2D" array, by using template arguments for the dimensions and passing the array by reference:
// For std::size_t
#include <cstdlib>
template<std::size_t A, std::size_t B>
void sum(int (&x)[A][B])
{
// Use A and B as the sizes for the arrays...
...
}
While the above template version is better, the "proper" solution in C++ should be using std::array, as in:
std::array<std::array<int, 2>, 3> = { ... };
and then pass it as a constant reference to the function.
If the sizes aren't known at compile-time, or if the arrays should be dynamic, then use std::vector instead.
A good book and and good teacher would teach these classes before going into pointers or C-style arrays.
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
So, for an assignment I have to write a template function that will successfully swap two values of any type. I also have to verify that pointers can be used by this function as well. Apparently, thorough output will demonstrate swapping of the pointers, but not swapping of the values they point-to.
I have a general idea of how to start, but not where to go afterwords.
Here's what I have so far.
template <typename T>
void swap(T*& first, T*& second)
{
T* a = nullptr;
a = first;
first = second;
second = a;
std::cout << first << " " << second << " ";
}
I've got the function prototype, but don't know what to do from here, any suggestions on how to call this function and if it would actually provide me the desired output?
Here's my main
int main()
{
swap(10, 20);
system("pause");
}
Thanks!
Your template function wants pointers to T as parameters. Your code
int main()
{
swap(10, 20);
system("pause");
}
doesn't call it with pointers but integer literal values. What you should use to call your function is
int main() {
int var1 = 42;
int var2 = 15;
int* pvar1 = &var1;
int* pvar2 = &var2;
swap(pvar1,pvar2);
}
Please tell me the use of cascading, and when to use & before function like this int &func()
Where should i use that please give me small example, Thanks. I think it does return an address but no idea how to use.
You are about to commit a very common newbie mistake in C++, namely returning references to dead objects.
int &GetNumber()
{
int number = 123;
return number;
}
int main()
{
int x = GetNumber();
int y = x + 1;
}
Looks innocent but will create so-called undefined behaviour. This means that the program may do whatever it wants to - it will likely crash, or it will sometimes crash. In any case, it won't be safe. Your compiler may even warn you if you attempt to do this. The reason is that by the time GetNumber has finished, the local number is destroyed, and you end up with a reference to a destroyed object.
Usually, you will want to return a copy instead of a reference. This is the "normal" thing to do in C++:
int GetNumber() // now OK
{
int number = 123;
return number;
}
int main()
{
int x = GetNumber();
int y = x + 1;
}
Returning references is only safe when you know that the object referred to will continue to exist after the function returns. One example is when you are just returning a reference you were passed:
int &MyFunction(int &number)
{
// do something
return number;
}
This then allows you to chain functions:
struct Example
{
Example &MyFunction(Example &example)
{
// do something
return example;
}
};
int main()
{
Example example;
example.MyFunction(example).MyFunction(example).MyFunction(example);
}
Now, if this example strikes you as particularly useless (as it should), look at how the standard library handles << calls with std::ostream for a realistic use case.
std::cout << 1 << "a" << 0.5;
This syntax works because each operator<< call returns a reference to std::cout.
when to use &
Return by value vs return by reference
You usually return a reference when you want a caller to be able to change the original variable. Example can be returning elements of an array
struct Array
{
int values[ 10];
};
// Returns a reference to the nIndex element of rArray
int& Value( Array &rArray, int nIndex)
{
return Array.values[ nIndex];
}
int main()
{
Array myArray;
// Set the 10th element of sMyArray to the value 5
Value( myArray, 10) = 5;
assert( myArray.values[ 10] == 5); // OK
return 0;
}
Another example is returning reference to class member. You want to return original variable, not a copy of it. Consider:
struct A {
int something;
int f() { return something; }
int& g() { return something; }
};
int main()
{
A myA;
int i = myA.f(); // return by value: not original
// int but its copy with same value
i = 200;
assert( myA.something == 200); // fail
return 0;
}
but:
int main()
{
A myA;
int& i = myA.g(); // return by reference: original
// variable is referenced by i now
i = 200;
assert( myA.something == 200); // OK
return 0;
}
Operator chaining
Operator chaining is made to allow for expressions like:
a = b + c + d;
or
std::cout << "this" << " and " << "this";
Usually there is choice between returning by value or by reference made by considering the meaning of the operator or independent factors like for example that std::istream and std::ostream are not copyable, so trying to return objects of those types by value is an error.