in C addresses do not work in functions , why is that? - c

When trying to use a C++ style in C:
void square(int &x){
x = x * x;
};
This gets an error.
error: expected ';', ',' or ')' before '&' token
i'm most comfortable with c++, but i'm learning C, is there a way to to have adressess in void functions
Tried switching from void -> int, double, char. It only works when i take away the & symbol, but i would like to have an address there. Is there a way to do that?
Should i just use * instead of &, like this :
void square(int *x){
x = (*x) * (*x);
};

C language does not have C++ references. You need to use pointers
void square(int *x)
{
*x = *x * *x;
}
Your second code is invalid as you assign a local pointer with integer converted to pointer.

Even in C++ the sign & does not denote an address in a declaration. It denotes a reference.
This declaration in C++
void square(int &x){
//...
}
means that the function accepts its argiment by reference.
In C passing by reference means passing an object indirectly through a pointer to it. So dereferencing a pointer within a function you get a direct access to the original object passed to the function through the pointer.
So this function in C++
void square(int &x){
x = x * x;
}
accepts an object of the type int by reference.
In C this function
void square(int *x){
*x = *x * *x;
}
accepts an object of the type int by reference indirectly through a pointer to it.
Pay attention to that the assignment statement in the second function
void square(int *x){
x = (*x) * (*x);
}
is incorrect. You are trying to assign an integer expression to a pointer. You have to write
*x = *x * *x;
as already shown above. That is you need to change the passed object of the type int to the function indirectly through a pointer to it.

Related

Conversion of function pointers

I was wondering if we can create a generic function pointer, which would point to a function with any return type in C. I tried it through this code:
typedef void (*func_ptr)(int, int);
int func1(int a, int b) {
return a * b;
}
int func2(int a, int b) {
return a + b;
}
int main() {
func_ptr ptr1, ptr2;
ptr1 = func1;
ptr2 = func2;
printf("Func1: %d\n", *(int *)(*ptr1)(4, 5));
printf("Func2: %d\n", *(int *)(*ptr2)(4, 5));
return 0;
}
If the func_ptr was of type int, the code would work. But what is wrong with this approach? Why can't we assign void * pointer to integer functions?
If the func_ptr was of type int, the code would work
More precisely: if the func_ptr type definition specified a return type of int, the initialization code would be correct, but the invocation would still be invalid because the *(int *) cannot be applied to the void return value and invoking the function with a prototype different from its calling convention has undefined behavior anyway. func_ptr should be cast as ((int(*)(int, int))func_ptr) for the call to be correct.
There is no such thing as a generic function pointer, but a function taking no arguments and returning void is a close as can be. Functions with different prototypes can be stored into incompatible function pointers as long as you use a proper cast and the pointer must be cast back to the exact prototype of the function it points to at the call sites. This is possible for C, but more tricky for C++.
Beware that function call is a postfix operation, so it binds stronger than prefix operations such as a cast: (int(*)(int, int))func_ptr(3, 4) does not work. You must write:
((int(*)(int, int))func_ptr)(3, 4)
Here is a modified version:
#include <stdio.h>
// define a generic function pointer of no arguments with no return value
typedef void (*func_ptr)(void);
// actual function type: function of taking 2 ints, returning an int
typedef int (*func_of_int_int_retuning_int)(int, int);
int func1(int a, int b) {
return a * b;
}
int func2(int a, int b) {
return a + b;
}
int main() {
func_ptr ptr1, ptr2;
// use explicit casts for assignment (with or without the typedef)
ptr1 = (func_ptr)func1;
ptr2 = (void (*)(void))func2;
// at call sites, the function pointer must be cast back to the actual
// type for invocation with arguments and handling of return value
// again you can use a typedef or not
printf("Func1: %d\n", ((int (*)(int, int))ptr1)(4, 5));
printf("Func2: %d\n", ((func_of_int_int_retuning_int)ptr2)(4, 5));
return 0;
}
You are allowed to convert between different function pointers, but you are not allowed to call a function pointer unless it's compatible with the pointed-to type. You can force the assignment to compile by using a cast (which will get you a warning), but as soon as you try to call ptr1 or ptr2 you get Undefined Behavior.
You can call them if you first convert them back to the correct function type. This is correct:
typedef void (*func_ptr) (int, int); // literally any function type would work
typedef int (*real_func_ptr) (int, int);
int func1(int a, int b) { return a * b; }
int func2(int a, int b) { return a + b; }
int main() {
func_ptr ptr1, ptr2;
ptr1 = (func_ptr) func1;
ptr2 = (func_ptr) func2;
int a = ((real_func_ptr)ptr1)(4, 5);
int b = ((real_func_ptr)ptr2)(4, 5);
return a + b;
}
A few more points about your post:
I see this a lot, where students say "void function" and "int function", as if the function type is its return type. This is wrong and very misleading. The function type is: "function taking two arguments of type int and returning int" (aka int (int, int))
your typedef is: pointer to function taking 2 int arguments and returning void. It's not returning void *.
There is no generic function pointer type similar to void* for object pointers. However, the C standard actually guarantees that we can convert between any two function pointers and back, as long as we call the function through the correct kind of function pointer. This means that any function pointer type can actually be used as a generic function pointer type.
There are many problems on these lines: *(int *)(*ptr1)(4, 5).
You may not call ptr1 since it is of type void(*)(int,int) but it points at a function of type int(*))(int, int). You need to cast back to the correct type before calling. (A separate variable like an enum might be used to keep track of which type the pointer actually points at.)
Either way the *(int *) cast would just cast the result after the function call, so it doesn't do what you want.
Generic programming with function pointers generally involves deciding a certain function type to use as template, then implement all functions accordingly.
Or we can use _Generic inside a macro to sort out the types at compile-time, like for example this:
#define func(x,y) \
_Generic((x), int: _Generic((y), int: int_func, default: 0), \
char*: _Generic((y), char*: string_func, default: 0) ) (x,y)
int main (void)
{
printf("Func1: %d\n", func(4,5));
printf("Func2: %s\n", func("hello","world"));
}

Something passed to a function as pointers to type [duplicate]

Before I start I want to tell you I am learning to program.
What is the difference between Passing the variable to function and passing an array to the function in C?
When we pass a variable to function we are just passing the value of function. But when we pass an array we are passing somehow a pointer because when we do some changes on an array inside a function, actual array gets changed.
In order to make my question clear I am attaching code which will explain what I am asking-
Code 1:
//Passing variable to function
#include<stdio.h>
void swap(int x, int y);
int main(void)
{
//Nothing is happening to real values of variables
int x, y;
x = 1;
y = 2;
swap(x, y);
printf("%d = x \n %d = y", x, y);
}
void swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
Code 2:
//Here you can see the values of arrays are swapped.
#include<stdio.h>
void swap(int arr[]);
int main(void)
{
int idx, array[2];
for(idx = 0; idx < 2; idx++ )
{
scanf("%d", &array[idx]);
}
swap(array);
for(idx = 0; idx < 2; idx++, printf("\n"))
{
printf("%d", array[idx]);
}
}
void swap(int arr[])
{
int temp;
temp = arr[0];
arr[0] = arr[1];
arr[1] = temp;
}
Maybe my question is still unclear but I just want to know why the values of the array gets changed in main function as when we call the function we are just passing a function value of that variable.
In the both cases when a variable as you are saying is passed to a function or an array is passed to a function there is passed a value.
But in the first case there is passed the value of the variable while in the second case there is passed the value of the pointer to first element of an array.
Arrays used in expressions with rare exceptions are converted to pointers to their first elements.
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array object
has register storage class, the behavior is undefined.
So having a pointer to an object you can change the pointed object.
Let's assume that you have two functions.
void f( int x )
{
x = 10;
}
and
void g( int *px )
{
*px = 10;
}
and their calls
int n = 0;
f( n );
g( &n );
You can imagine the function definitions and their calls the following way
int n = 0;
f( n );
g( &n );
//...
void f( /* int x */ )
{
int x = n;
x = 10;
}
void g( /* int *px */ )
{
int *px = &n;
*px = 10;
}
That is the both functions deal with copies of values of the expressions used as function arguments. But in case of the function g as the function gets the value of the address of the pointed object n you can change the pointed object n using the pointer (address).
In the terms of C passing an object to a function indirectly through a pointer to the object is called passing by reference.
From the C Standard
— A pointer type may be derived from a function type or an object
type, called the referenced type. A pointer type describes an object
whose value provides a reference to an entity of the referenced
type. A pointer type derived from the referenced type T is sometimes
called ‘‘pointer to T’’. The construction of a pointer type from a
referenced type is called ‘‘pointer type derivation’’. A pointer type
is a complete object type.
Pay attention to that a function declaration like this
void f( int a[], size_t n );
is equivalent to the following declaration
void f( int *a, size_t n );
And the both declare the same one function.
If you have an array as for example
#define N 10
//...
int a[N];
then it is passed to the function like
f( a, N );
then as it is followed form the first quote from the C Standard the array designator is converted to pointer to its first element. And having this pointer in the function you can change any element of the array because each element of the array in fact is passed by reference. Using the pointer arithmetic you can change any element of the pointed array. For example
void f( int *a, size_t n )
{
for ( int i = 0; i < n; i++ )
{
a[i] = i;
// that is the same as
// *( a + i ) = i;
}
}
When you pass an array, you are actually passing the base address of the same, which is a pointer to the first array element in the memory. It is inherently a call by reference, so you don't need to explicitly use a reference or & while passing into your swap function. arr decays to &(arr[0]).
On the other hand, variables are not by default passed by value, and you need to explicitly use a & to pass them by reference to get their values swapped in their memory locations and not just specific to the scope of the swap function.
What is the difference between Passing the variable to function and passing an array to the function in C?
You cannot pass an array as it is to a function. The C syntax does not allow that. When you provide the identifier of an array as argument it decays to a pointer to the first element of the array - so you pass the array by reference to its first element.
If the relative parameter of the function is of the matching pointer type, here int * or int a[], this is permissible.
Instead when providing a variable as argument you pass it by value. Means you do not access the variable provided as argument in the function itself. Rather the value is copied into a local variable of the function.
If you want to change the value of the variable passed itself, you need to use the & ampersand operator to gather the address of the variable itself. This is only permissible if the relative parameter is of matching pointer type as above.
Thus, In the first example you do not swap the values of x and y in main(). You only change x and y inside of swap() which is pretty useless.
If you want to swap xand y in main you need to define swap() as:
void swap(int* x, int* y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
and call swap() like:
swap(&x, &y);
I suggest you to learn more about pointers.
You are not passing the array as copy. It is only a pointer pointing to the address where the first element is in memory.
When passing an array as a parameter, this
void arraytest(int a[])
means exactly the same as
void arraytest(int *a)
so you are modifying the values in main. However in C function arguments are always passed by value. In case of an array (variable), while passed as a function argument, it decays to the pointer to the first element of the array. The pointer is then passed-by-value, as usual.
An array is a special variable. When you pass a regular variable to a function as an argument, its value is copied to a local variable pertaining to the function.
When you pass an array to a function as an argument, the address of the first element of the array is copied to a local variable pertaining to the function.
That is basically the difference between passing a regular variable and passing an array to a function.
There is one issue with your perception though. If you want to modify a regular variable to be passed to a function, then you need to pass its address to the function, thus the function should take a pointer type. So just use the pointer notation, i.e int *p as opposed to int p[], even though, they are equivalent as function parameters.
Your code should look like this:
#include<stdio.h>
void swap(int *x, int *y);
int main(void)
{
int x, y;
x = 1;
y = 2;
swap(&x, &y);
printf("%d = x \n %d = y", x, y);
}
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}

Function Pointers Casting in C

Why do i need to remove the function pointer casting to use the function as shown below ?
This Compiles:
#include <stdio.h>
int print_int(int i){
printf("%d", i);
return i;
}
typedef int (*print_int_func) (int);
int main(){
void** p = malloc(1*sizeof(print_int_func*));
p[0] = (print_int_func*)print_int;
((print_int_func)p[0])(2); // This Compiles
((print_int_func*)p[0])(2); // This does NOT
return 0;
}
The declaration typedef int (*print_int_func) (int); declares print_int_func to be a pointer to a specific type of function. So (print_int_func)p[0] casts p[0] to such a pointer to a function, but (print_int_func*)p[0] casts p[0] to a pointer to a pointer to a function. Thus, the result is a pointer to an object (that object being a pointer to a function). Since it is an object, not a function (or pointer to a function), it cannot be called like a function.
Additionally, avoid using void * for pointers to functions. void * is a pointer to an object, and the C standard does not define conversions between pointers to objects and pointers to functions. To create a “generic” pointer to a function, simply choose any function type and use a pointer to that type:
Convert to the chosen type when storing the pointer.
Convert to the actual function type when calling the function type.
For example, you can declare an arbitrary type:
typedef void (*CommonFunctionPointer)(void);
and make an array of them:
CommonFunctionPointer *p = malloc(N * sizeof *p);,
and then you can store any function pointer in the array:
p[i] = (CommonFunctionPointer) print_int;
and use a pointer from the array by casting it back to its correct type:
((int (*)(int)) p[i])(2);.

passing pointer as size of an array in C

I want to pass a pointer as a size element of an array
example:
void hello(int array1[how can i refer pointer "ptr" here][2])
{
// i want to access the array used in the main() here
printf("hi");
}
int main()
{
int c=5;
int *ptr=&c;
a[*ptr][2];
a[0][1]=0;
a[0][2]=4;
}
I apologize for not being clear with my question here , i want to access the array used in the main() function in my hello() function.
You will have to use the value pointed to by the pointer:
a[*ptr][2];
ptr is the address pointed to by the pointer not the value stored there. You use the dereference operator * to get the value.
Of course, ptr is not of type int, it's of type int * (integer pointer). An array subscript must be of type int.
Maybe what you want is a[*ptr][2].
You need to deference the pointer by using *ptr so
int c = 5;
int *ptr = &c;
a[*ptr][2];
otherwise you are not using the value of ptr you are using its address in memory which returns an error.
Use the dereference operator *:
a[*ptr][2];
The expression *ptr tells the compiler to use the value pointed to by ptr.
As for your updated question, that's not possible. But it's not needed either, as it's passed as a pointer anyway.
When declaring a function, this:
void foo(int a[5][5])
is the same as this:
void foo(int a[][2])
And also the same as this:
void foo(int (*a)[2])
It has pretty much been answered already, you can't call an adress in the array a[0x3950f2][2]
Always use the pointer* to get the position in the array a[*ptr][2] to get the expected value - in this case: a[*ptr][2] == a[5][2]. You may read this.
Edit to your updated question: You can't to this. You can use the pointer when you call the function or when using the variable in the function.
Your second edit:
void hello(int **array1)
{
// i want to access the array used in the main() here
printf ("hi");
a[0][0] = 24;
}
int main()
{
int c = 5;
int *ptr = &c;
int **a;
a[*ptr][2];
a[0][1] = 0;
a[0][2] = 4;
hello (a);
return 0;
}

What is double star (eg. NSError **)?

So, I saw this:
error:(NSError **)error
in the apple doc's. Why two stars? What is the significance?
A "double star" is a pointer to a pointer. So NSError ** is a pointer to a pointer to an object of type NSError. It basically allows you to return an error object from the function. You can create a pointer to an NSError object in your function (call it *myError), and then do something like this:
*error = myError;
to "return" that error to the caller.
In reply to a comment posted below:
You can't simply use an NSError * because in C, function parameters are passed by value—that is, the values are copied when passed to a function. To illustrate, consider this snippet of C code:
void f(int x)
{
x = 4;
}
void g(void)
{
int y = 10;
f(y);
printf("%d\n", y); // Will output "10"
}
The reassignment of x in f() does not affect the argument's value outside of f() (in g(), for example).
Likewise, when a pointer is passed into a function, its value is copied, and re-assigning will not affect the value outside of the function.
void f(int *x)
{
x = 10;
}
void g(void)
{
int y = 10;
int *z = &y;
printf("%p\n", z); // Will print the value of z, which is the address of y
f(z);
printf("%p\n", z); // The value of z has not changed!
}
Of course, we know that we can change the value of what z points to fairly easily:
void f(int *x)
{
*x = 20;
}
void g(void)
{
int y = 10;
int *z = &y;
printf("%d\n", y); // Will print "10"
f(z);
printf("%d\n", y); // Will print "20"
}
So it stands to reason that, to change the value of what an NSError * points to, we also have to pass a pointer to the pointer.
In C everything is pass by value. If you want to change the value of something you pass the address of it (which passes the value of the memory address). If you want to change where a pointer points you pass the the addres of the pointer.
Take a look here for a simple explanation.
In C, a double star is a pointer to a pointer. There are a couple of reasons to do this. First is that the pointer might be to an array of pointers. Another reason would be to pass a pointer to a function, where the function modifies the pointer (similar to an "out" parameter in other languages).
The double star (**) notation is not specific to initializing a variable in a class. It is simply a double indirect reference to an object.
float myFloat; // an object
float *myFloatPtr; // a pointer to an object
float **myFloatPtrPtr; // a pointer to a pointer to an object
myFloat = 123.456; // initialize an object
myFloatPtr = &myFloat; // initialize a pointer to an object
myFloatPtrPtr = myFloatPtr; // initialize a pointer to a pointer to an object
myFloat; // refer to an object
*myFloatPtr; // refer to an object through a pointer
**myFloatPtrPtr; // refer to an object through a pointer to a pointer
*myFloatPtrPtr; // refer to the value of the pointer to the object
Double pointer notation is used where the caller intends that one of its own pointers need to be modified by a function call, so the address of the pointer, instead of the address of the object, is passed to the function.
An example might be the use of a linked list. The caller maintains a pointer to the first node. The caller invokes functions to search, add, and remove. If those operations involve adding or deleting the first node, then the caller's pointer has to change, not the .next pointer in any of the nodes, and you need the address of the pointer to do that.
If it is anything like C then ** means a pointer to a pointer.

Resources