Do I have to initialize function pointers one by one? - c

When I initialize function pointers in one take, like below, it does not work.
ptr[3]={add, subtract, multiply};
This gives:
[Error] expected expression before '{' token
However, one-by-one initialization works. Why is this?
//array of function pointers
#include<stdio.h>
void add(int a, int b){
printf("%d\n", a+b);
}
void subtract(int a, int b){
printf("%d\n", a-b);
}
void multiply(int a, int b){
printf("%d\n", a*b);
}
int main(){
void (*ptr[3])(int, int);
//ptr[3]={add, subtract, multiply}; this initialization does not work
//but this works
ptr[0]=add;
ptr[1]=subtract;
ptr[2]=multiply;
ptr[2](3,5); //15
}

In the assignment, ptr[3]={add, subtract, multiply}; the RHS is (correctly) a suitable initializer-list for an array of three function pointers. However, the LHS (ptr[3]) is wrong: that's just a single element of an array, and an out-of-bounds element, at that.
Just do the 'assignment' in the declaration, and make it an initialisation:
int main(void)
{
void (*ptr[3])(int, int) = {add, subtract, multiply}; // this initialization does work
ptr[2](3, 5); //15
}
There is actually nothing special, here, related to the fact that your array's elements are function pointers. No array can be "assigned to" (using the = operator) en bloc, at any point other than in its declaration. In a variable declaration, the use of the = token isn't, formally, an assignment operation; it is an initialisation. Useful reading: Initialization vs Assignment in C.

You need to initialize during declaration.
//array of function pointers
#include<stdio.h>
void add(int a, int b){
printf("%d\n", a+b);
}
void subtract(int a, int b){
printf("%d\n", a-b);
}
void multiply(int a, int b){
printf("%d\n", a*b);
}
int main(){
void (*ptr[3])(int, int) = {add, subtract, multiply};
ptr[2](4,5); //20
}

Related

Error in the program to find absolute difference in C

I want to calculate the sum and absolute difference of the two variable in this program.
#include <stdio.h>
#include <stdlib.h>
void update(int *a,int *b) {
// Complete this function
*a= *a+*b;
*b= abs(a-b);
}
int main() {
int a, b;
int *pa = &a, *pb = &b;
scanf("%d %d", &a, &b);
update(pa, pb);
printf("%d\n%d", a, b);
return 0;
}
But for some inputs this doesn't produce correct outputs for the absolute difference.eg.(4,5) produce correct outputs; (2,6) doesn't. I am unable to figure out the mistake. What is the reason?
As pointed out in other answer subtracting two pointers is UB.
To answer other part of problem,
Try to understand what is happening to the pointer values at each point of arithmetic operation,
void update(int *a,int *b) {
// Complete this function
*a= *a+*b; //<< here *a has sum of *a and *b
*b= abs(*a-*b);
//here *a itself is *a +*b
//so entire operation is abs(*a + *b -*b) and hence *b will have value of abs(*a)
}
Try to have local variables to keep intermediate values and assign it at the end,
void update(int *a,int *b) {
int sum = *a + *b;
int diff = abs (*a -*b);
*a= sum;
*b= diff;
}
*b= abs(a-b);
You are subtracting the pointers, which is undefined behavior because they don't point into the same array. You want to be subtracting the numbers they point to. Make this
*b= abs(*a-*b);

Syntax error when using pointers through function calling and parameters in C

I am getting a syntax error when trying to allocate space for a multidimensional matrix. I am new to coding in C, so anything will help. The error occurs when trying to access the matrix structure elements in the read_matrix function. The syntax error is "expression must have struct or union type". Where the error is produced is commented out in the read_matrix function.
typedef struct {
int *elements;
int rows;
int columns;
} matrix;
void main() {
matrix a, b, c;
void read_matrix(matrix *);
void deallocate(matrix *);
void print(matrix);
matrix add(matrix, matrix);
matrix subtract(matrix, matrix);
matrix multiply(matrix, matrix);
read_matrix(&a);
read_matrix(&b);
c = add(a, b);
deallocate(&c);
c = subtract(a, b);
deallocate(&c);
c = multiply(a, b);
}
void read_matrix(matrix *z) {
int d1, d2, i, x, y, val;
printf("What is the first dimension of the array? ");
scanf("%d", &d1);
printf("What is the second dimension of the array? ");
scanf("%d", &d2);
*z.elements = (int *)calloc(d2, sizeof(int));
*z.rows = d1;
*z.columns = d2;
/* error here. It isn't letting me access the
elements/rows/columns of the matrix */
/* additional code below here */
}
Operator . has higher precedence than unary operator *, which means that if you want to access struct members through a pointer z using *-and-. combination, you have to use parentheses. It your case it should be
(*z).elements = ...
Alternatively you can use -> operator
z->elements = ...
And it is supposed to be int main(), not void main()

Passing multidimensional arrays as arguments in functions in C

I am currently doing the fifteen exercise in CS50's Problem set 3. However, I am stuck in figuring out the syntax to pass a multi-dimensional array as an argument to a function. For instance, the following code (which prints out some numbers in an array) compiles and works:
#include <stdio.h>
void func(int array[], int size);
int main()
{
int size = 3;
int array[3] = {1,2,3};
func(array,size);
printf("Done\n");
}
void func(int array[], int size)
{
printf("%i %i %i\n", array[0],array[1], array[2]);
}
But this doesn't:
#include <stdio.h>
void func(int array[][], int size);
int main()
{
int size = 3;
int array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
func(array,size);
printf("Done");
}
void func(int array[][], int size)
{
printf("%i %i %i\n", array[0][0],array[1][1], array[2][2]);
}
This is the error provided by clang:
test.c:3:20: error: array has incomplete element type 'int []'
void func(int array[][], int size);
^
test.c:13:20: error: array has incomplete element type 'int []'
void func(int array[][], int size)
Can anyone explain to me what's wrong with my syntax? I don't quite understand the error messages given to me by clang.
The function func() expects a pointer to int but you are passing a pointer to an array. Hence, the errrors.
It's because an array gets converted into a pointer to its first element when you pass it to a function.
You can change the function prototype and definition to receive a pointer to an array:
void func(int (*array)[3], int size);
int main()
{
int size = 3;
int array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
func(array,size);
printf("Done");
}
void func(int (*array)[3], int size) {
...
}
Note that your array is initialized with size 3x3. So the array size has to 3x3 at least.
C99 allows to you pass dimensions. So you can write it like this too:
void func(int x, int y, int a[x][y]);
int main()
{
int size = 3;
int array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
func(3, 3, array);
printf("Done");
}
void func(int x, int y, int array[x][y])
{
printf("%i %i %i\n", array[0][0],array[1][1], array[2][2]);
}
An array is not a type in C! Internally, it is always handled as a pointer, hence, a pointer to the array is passed as argument and not the array itself.
If you intend to pass arrays as arguments (and not just pointers), you should rethink your design!
If you still need to do this wrap the array into a structure and pass the structure.
struct astruct
{
int size;
int array[3];
};
A declaration like int a[][] isn't sensible, since the compiler must know the size of all dimensions (except of the outermost) to calculate the memory address on access.
I.e. if an array is declared as
int array[][a][b];
The memory address for access to
array[2][1][3];
is calculated by
base_address + (2*a*b + 1*b + 3) * sizeof int
Without knowing a and/or b, this calculation would not be possible.
Simply tell the function to expect a multi-dimensional array:
void func (int array[3][3], int size);
Or if you want the function to be completely flexible:
void func (int x, int y, int array[x][y]);
You need to specify size of array when declaring prototype as well as while defining function . Right now it is of incomplete type .
Try this instead -
void func(int array[][3], int size)

Return statement with more than one arguments

After compiling my C code with -Wall activated, the following warnings appeared
left operand of comma operator has no effect
which are related with the the multiple arguments presented in my return statements. The story is the following:
Assume to have a bunch of dynamically allocated 3D arrays (A,B and C) and want to do some manipulation on them. The arrays are defined as pointer to pointer to pointer and allocated using malloc (the standard procedure). The manipulation of them will occur in seperate functions. For some reason I declare the function as a triple pointer and as follow:
***func( double ***A, double ***B, double ***C)
{
do some work here on A, B and C
return(A, B, C);
}
I know that the arrays are passing into the function as reference so essentially there is no need of returning something from this function. But, can you tell me why someone would declare a function this way. This staff confuses me. Thanks in advance
return(A, B, C) is not C, you can use a struct to return more than one arguments.
struct array3d{
double* A;
double* B;
double* C;
};
struct array3d* func(struct array3d* p) {
/* do some work here on p->A, p->B and p->C */
return p;
}
Here is an working example with *** pointers:
#include <stdio.h>
#include <malloc.h>
struct array3d {
double*** A;
double*** B;
double*** C;
};
struct array3d* func(struct array3d* p) {
/* do some work here on A, B and C */
***p->A /= 42.0;
***p->B /= 42.0;
***p->C /= 42.0;
return p;
}
int main()
{
struct array3d arr;
struct array3d* p_arr;
double A[] = { 1.0, 3.0}; // ...
double B[] = {-1.0, -2.0};
double C[] = { 2.0, 4.0};
double* p1A = A;
double* p1B = B;
double* p1C = C;
double** p2A = &p1A;
double** p2B = &p1B;
double** p2C = &p1C;
arr.A = &p2A;
arr.B = &p2B;
arr.C = &p2C;
p_arr = func(&arr);
printf("(A = %f, B = %f, C = %f)\n", ***p_arr->A, ***p_arr->B, ***p_arr->C);
return 0;
}
The code
***func( double ***A, double ***B, double ***C)
{
do some work here on A, B and C
return(A, B, C);
}
is simply wrong, even though it compiles:
If the function returns everything via its arguments A, B, and C, it should not have a return type. I. e., it should be declared to return void:
void func( double ***A, double ***B, double ***C) {
The syntax return(A, B, C) does not do what you think it does. It does not construct a list, or pass three values to return. Instead, it evaluates the expression A, throws its value away, evaluates B, throws its value away, evaluates C, takes the value of C as the value of the expression (A, B, C), and finally returns that value from the function. (Google "C comma operator" for more information.)
If your function is declared as returning void (as it probably should be), there is simply no need for a return statement.

Function Pointer in C

How can I create a "function pointer" (and (for example) the function has parameters) in C?
http://www.newty.de/fpt/index.html
typedef int (*MathFunc)(int, int);
int Add (int a, int b) {
printf ("Add %d %d\n", a, b);
return a + b; }
int Subtract (int a, int b) {
printf ("Subtract %d %d\n", a, b);
return a - b; }
int Perform (int a, int b, MathFunc f) {
return f (a, b); }
int main() {
printf ("(10 + 2) - 6 = %d\n",
Perform (Perform(10, 2, Add), 6, Subtract));
return 0; }
typedef int (*funcptr)(int a, float b);
funcptr x = some_func;
int a = 3;
float b = 4.3;
x(a, b);
I found this site helpful when I was first diving into function pointers.
http://www.newty.de/fpt/index.html
First declare a function pointer:
typedef int (*Pfunct)(int x, int y);
Almost the same as a function prototype.
But now all you've created is a type of function pointer (with typedef).
So now you create a function pointer of that type:
Pfunct myFunction;
Pfunct myFunction2;
Now assign function addresses to those, and you can use them like they're functions:
int add(int a, int b){
return a + b;
}
int subtract(int a, int b){
return a - b;
}
. . .
myFunction = add;
myFunction2 = subtract;
. . .
int a = 4;
int b = 6;
printf("%d\n", myFunction(a, myFunction2(b, a)));
Function pointers are great fun.
You can also define functions that return pointers to functions:
int (*f(int x))(double y);
f is a function that takes a single int parameter and returns a pointer to a function that takes a double parameter and returns int.

Resources