In this eg,using call by address concept in order to retrieve all the data changes which is happening in the function call...
In main(),
i)passing two arguments
i)int pointer
ii)pointer to constant -> which cannot change the value it is holding...
ii)Changing the values of int * and assigning some values to const void * in the function calls.
*Finally i'm trying to print the values in main()
*getting the int pointer values properly(no issues)
*getting the void pointer value as NULL..
Requirement:
Need to get the output in main() like this
main::ajskdffllagkdjdjdhdjhd(i mean to say that i need to print the void * values like this)
But i'm getting the value as main:: NULL
What shall i need to do inorder to get the expected output?
#include <stdio.h>
#include <stdlib.h>
void func(int *len,const void *pBuf);
void func2(int **len,const void **pBuf);
void func3(int ***len,const void ***pBuf);
int main()
{
int len = 0;
const void *pBuf;
printf("len b4 ::%d\n",len);
printf("%p\n",&pBuf);
func(&len,&pBuf);
printf("len after::%d\n",len);
printf("%p\n",&pBuf);
printf("main::%s\n",(const char *)pBuf);
return 0;
}
void func(int *len,const void *pBuf)
{
*len = 20;
printf("func1 :: %p\n",&pBuf);
func2(&len,&pBuf);
}
void func2(int **len,const void **pBuf)
{
printf("func2::%p\n",&pBuf);
**len = 30;
func3(&len,&pBuf);
}
void func3(int ***len,const void ***pBuf)
{
const void *pMy = "ajskdffllagkdjdjdhdjhd";
**pBuf = pMy;
printf("func3::%p\n",&pBuf);
printf("func3::%s\n",(const char *)**pBuf);
***len = 40;
}
Output:
len b4::0
0x7fffa9c51468
func1 :: 0x7fffa9c51440
func2::0x7fffa9c51420
func3::0x7fffa9c513f0
func3::ajskdffllagkdjdjdhdjhd
len after::40
0x7fffa9c51468
main::(null)
You are right with the string literal. Sorry.
However, you need to change the address where pBuf points to:
void func(int *len,const void **pBuf)
{
*len = 20;
printf("func1 :: %p\n",pBuf);
func2(&len,&pBuf);
}
void func2(int **len,const void ***pBuf)
{
printf("func2::%p\n",pBuf);
**len = 30;
func3(&len,&pBuf);
}
void func3(int ***len,const void ****pBuf)
{
const void *pMy = "ajskdffllagkdjdjdhdjhd";
***pBuf = pMy;
printf("func3::%p\n",&pBuf);
printf("func3::%s\n",(const char *)***pBuf);
***len = 40;
}
len is an int. In order to change it, you need to call func() with the address of that int value.
pBuf is a pointer. To change the address where it points to, you need to call func() with the address of that pointer.
You are catching address of int with single pointer and catching the address of pointer also with single pointer.. This is problem. In functions, change *pBuf as **pBuf and **pBuf as ***pBuf and so on..
Related
I don't understand why is crashing. I send a pointer to an array, alloc that array and then modify array. What is the problem?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void f(unsigned char *data) {
data = (unsigned char *)malloc(200);
}
int main() {
unsigned char *data = nullptr;
int i;
f(data);
memset(data, 0, 200);
}
You are passing data by value to f().
f() sets the value of its parameter.
Because the parameter was passed by value, this does absolutely nothing to the data variable in main(). f() leaks the allocated memory, and when it returns, main()'s data is still nullptr.
You should pass it by reference:
void f(unsigned char *&data)
Or, better yet, return it. f() doesn't need the parameter.
unsigned char *f() {
return (unsigned char *)malloc(200);
}
Change
void f(unsigned char *data) { // ....
to
void f(unsigned char *&data) { // ....
// ^
}
or
void f(unsigned char **data) {
*data = (unsigned char *)malloc(200);
}
and call
f(&data);
// ^
It's all about passing a reference to the data pointer to be initialized from within the function.
Your example passes data by value, and doesn't change the pointer outside of the function.
The call to f does not change the value of the variable data defined in main, as you seem to expect it to. It changes the value of the data defined in f, but because parameters are passed by value, that has no effect on the data defined in main.
My question is how to translate the following example? Is this a function, that returns int pointer?
int* (*function)(int, (int (*k)(int *)));
And can I can't write program that use it?
Thanks in advance!
It is a function-pointer
The function returns a pointer to an int
The function's first arg is an int
The function's second arg is a function-pointer k
k returns an int
k takes a pointer to an int as argument
Sure you can use that in your program. It is not too unusual. There are much worse declarations i have seen.
I renamed your "function" to "F" for clarity. Then you can write:
int* (*F)(int, int (*kFunc)(int *) );
Alternative:
typedef int (*kFunc)(int *);
int* (*F)(int, kFunc);
There are a lot of ways to use pointer to a function, may be a pattern such as Factory could take advantage of the function pointer to create new objects.( Look here : http://www.codeproject.com/Articles/3734/Different-ways-of-implementing-factories)
May be this piece of code could help you and give ideas of how powerfull can be working with function pointers.
#include <stdio.h>
#include <stdlib.h>
#include <map>
// Define the func ptrs
typedef void (*TFunc)(const char *, int);
typedef int (*TFunc2)(int);
int return_value(int i)
{
return i * 5;
}
void a( const char *name, int i )
{
printf ("a->%s %d\n\n", name, i);
}
void b( const char *name, int i)
{
printf ("b->%s %d\n\n", name, i);
}
struct test
{
const char *name;
int i;
TFunc func;
};
static test test_array[2] =
{
{ "a", 0, a },
{ "b", 1, b },
};
int main(int argc, char **argv, char** envp)
{
// Check the simple case, pointer to a function
TFunc fnc = a;
TFunc2 fnc2 = return_value;
fnc("blabla", 5);
fnc = b;
fnc("hello!", 55);
printf ("%d\n\n",fnc2(5));
//Check arrays of structs when there is a pointer to a fnc
test_array[0].func(test_array[0].name, test_array[0].i);
test_array[1].func(test_array[1].name, test_array[1].i);
//Handle a map of functions( This could be a little implementation of a factory )
typedef std::map<int, TFunc > myMap;
myMap lMap;
lMap.insert(std::make_pair(5, a));
lMap.insert(std::make_pair(2, b));
if( lMap.find( 5 ) != lMap.end() )
{
lMap[5]("hello map 5", 1);
}
myMap::iterator lItFind = lMap.find(2);
if( lItFind != lMap.end() )
{
lItFind->second("hello map 2", 2);
}
return(0);
}
I hope that this helps you.
You should remove extra parentheses, this is correct version:
int* (*function)(int, int (*k)(int *));
explanation (using right-left rule):
int* (*fn)(int, int (*k)(int *));
fn : fn is a
(*fn) : pointer
(*fn)(int, int (*k)(int *)) : to a function taking as arguments
- an int and
- function pointer
which takes a pointer to int
and returns int
int* (*fn)(int, int (*k)(int *)) : and returns a pointer to int
below is a short example on how to use it, also you ask for How to define pointer to pointer to function so below this is also included.
http://coliru.stacked-crooked.com/a/d05200cf5f6397b8
#include <iostream>
int bar(int*) {
std::cout << "inside bar\n";
return 0;
}
int* foo(int, int (*k)(int *)) {
std::cout << "inside foo\n";
k(nullptr);
return nullptr;
}
int main() {
int* (*function)(int, int (*k)(int *));
function = foo;
function(0, bar);
// Now, as you asked for, a pointer to pointer to above function
decltype(function) *pff;
pff = &function;
(*pff)(0, bar);
}
I 'm still confused for my problem after spending an amount of time to digging related posts/online resources.
My sample codes (test.cc) are :
void testsub(const int* &xx );
int main ()
{
int* xx;
xx= new int [10];
testsub(xx);
}
void testsub(const int* & xx){}
The compiling error message(pgcpp) read
"test.cc", line 7: error: a reference of type "const int *&" (not const-qualified)
cannot be initialized with a value of type "int *"
testsub(xx);
^
1 error detected in the compilation of "test.cc"."
Why? Your help is appreciated.
Best wishes,
Ting
int* cannot be used where the argument type is const int* &.
Say you have:
const int a = 10;
void foo(const int* & ip)
{
ip = &a;
}
int main()
{
int* ip = NULL;
foo(ip);
*ip = 20; // If this were allowed, you will be able to
// indirectly modify the value of "a", which
// is not good.
}
As the error message says, the argument type is incompatible; the function wants a pointer to const int, while you supply a pointer to int.
If you're asking why that's incompatible: allowing it would allow you to break const-correctness, as in this example:
void testsub(const int* &xx ) {
static const int x;
xx = &x;
}
int* xx;
testsub(xx); // Shouldn't be allowed, because...
*xx = 666; // BOOM! modifying a constant object.
Maybe try this
void testsub(const int* xx );
int main ()
{
int xx [10];
testsub(xx);
}
void testsub(const int* xx){}
You don't need the &, because you are passing a pointer as argument.
When you forward a "C-Array" (your int[10]), you will have a pointer to the first element of this array in your function.
void testsub(const int* xx );
int main ()
{
int* xx;
xx= new int [10];
testsub(xx);
}
void testsub(const int* xx){}
I think you got confused by your book, because they always write something like "Call by reference". That doesn't mean to pass the parameter as a reference with the &.
Often it is useful to pass also the size of the array to the function ... so it would like:
void testsub(const int* xx, size_t arraySize);
int main ()
{
int* xx;
xx= new int [10];
testsub(xx, 10);
}
void testsub(const int* xx, size_t arraySize){}
Now you can access the array in your function and you have the possibility to check the index, if you want to access the array with an index.
void testsub(int* xx, size_t arraySize)
{
for(size_t i=0; i<arraySize; ++i)
// ^ this way you will never try to access
// memory, which does not belong to the array
// => no seg fault, or whatever happens
{
// do sth. with the array ... for example setting values to 0
xx[i] = 0;
}
}
I am trying to understand a certain code where I found something hard to understand for me.
void BPlusTree::GetKey(int key, void*& keyloc) const {
keyloc = keys + key * attrLength;
return 0;
}
This function calculates the location (memory address) of the key value and store it at keyloc variable.
void*& means the reference for a void pointer.
And here reference is used to reflect the changed value of keyloc to the outer function which called `GetKey.
Am I right till now?
So I thought that, in the main function, when it calls GetKey function. It needs to pass (void*) not the (void*&).
int main() {
.....
int currPos = 0;
char* key = NULL;
int result = currNode->GetKey(currPos, (void*&) key);
}
Why is (void*&) used instead of (void*) here?
Thank you.
// And I added here example code...
#include <regex>
#include <iostream>
#include <stdlib.h>
using namespace std;
#include <stdio.h>
void foo(int &a, int &b) {
a = 10;
b = 20;
}
void foo2(int* &c, int* &d) {
*c = 10;
*d = 20;
}
void foo3(void* &c, void* &d) {
*(int*)c = 10;
*(int*)d = 20;
}
int main(void) {
int a = 0;
int b = 0;
int* c = new int;
int* d = new int;
void* e = malloc(sizeof(int));
void* f = malloc(sizeof(int));
foo(a, b);
printf("A is %d and B is %d\n", a, b);
foo2(c, d);
printf("C is %d and D is %d\n", *c, *d);
foo3((void*&)c,(void*&) d); // It works fine
printf("C is %d and D is %d\n", *c, *d);
foo3((void*)c,(void*) d); // But it does not work
printf("C is %d and D is %d\n", *c, *d);
}
Is the (void*) problematic one?? :D
Yes, you're pretty much right in what you do understand. For the last bit, perhaps it'll be easier to use a pointer instead of a reference in explaining...
You could have had
void BPlusTree::GetKey(int key, void** keyloc) const { ... };
and a caller
char* key = NULL;
int result = currNode->GetKey(currPos, (void**) &key);
Here, it should be obvious why you cannot use &(void*) key: (void*) key is an rvalue, and you cannot take its address. It'd be like taking the address of (key + 0). Sure, key + 0 is always just key, but the mere fact that you have an addition there means you're looking at a copy of the pointer value, not the original pointer object.
When dealing with references, there is not an explicit "address of" operation like there is with pointers, but the problem is the same. GetKey(currPos, (void*) key) doesn't work because (void*) key is an rvalue, not an lvalue. (void*&) key casts key to "reference to void*", and pretty much means *(void**) &key. It is done to pretend that key was actually defined as void*.
Note: this is generally considered very bad practice. key would be better actually defined as void*, and then no cast is required to call GetKey.
I am stuck in the following pointer problem:
Say you have a function:
void Function (unsigned char *ubPointer)
{
ubPointer++;
}
int main (void)
{
unsigned char *PointerX;
Function( PointerX );
}
What I want is that the ++ is reflected in PointerX, without declaring it as a global variable.
Thank you very much.
In C++, pass your pointer by reference (and don't forget to specify a return type for your function):
void Function (unsigned char*& ubPointer)
// ^
{
ubPointer++;
}
This won't require any further change in the calling code. When returning from the function, the side-effects on ubPointer will be visible to the caller.
In C, you can achieve the equivalent result by passing a pointer to your pointer:
void Function (unsigned char** ubPointer)
// ^
{
(*ubPointer)++;
// ^^^^^^^^^^^^
}
This will require you to change the way you are calling your function:
int main()
{
unsigned char* p;
Function(&p);
// ^
}
Or, if you want to do it C-style
void Function (unsigned char **ubPointer)
{
(*ubPointer)++;
}
because
Function (unsigned char **ubPointer)
{
ubPointer++;
}
would be increasing the address pointed to.
void Function (unsigned char *ubPointer)
{
(*ubPointer)++;
}
int main (void)
{
unsigned char *PointerX;
Function( PointerX );
}
This is the correction