what's the difference between int (* f [])(); and int f[](); - c

i find this in Pointers on C
int f[](); /* this one is illegal */
and:
int (* f [])(); /* this one legal. */
i really want know what's the usage of the second one.
thank you.

The second example is quite valid, if you use initialization block. For example:
#include <stdio.h>
int x = 0;
int a() { return x++ + 1; }
int b() { return x++ + 2; }
int c() { return x++ + 3; }
int main()
{
int (* abc[])() = {&a, &b, &c};
int i = 0,
l = sizeof(abc)/sizeof(abc[0]);
for (; i < l; i++) {
printf("Give me a %d for %d!\n", (*abc[i])(), i);
}
return 0;
}

I'm not sure if the second example is legal, since the size of the function array is not known, but what it is supposed to be is an array of function pointers, and here is a possible example of usage if the size would be known:
int a()
{
return 0;
}
int main(int argc ,char** argv)
{
int (* f [1])();
f[0] = a;
}

int f[](); // this is illegal because of you can't create array of functions . It's illegal in C
But second is legal
int (* f [])(); It says that f is an array of function pointers returning int and taking unspecified number of arguments

int f[](); /* this one is illegal */
That's trying to declare an array of functions, which is impossible.
int (* f [])(); /* this one NOT legal, despite what the OP's post says. */
That's trying to declare an array of function pointers, which would be perfectly legal (and sensible) if the array size were specified, e.g.:
int (* f [42])(); /* this one legal. */
EDIT: The type int (* f [])() can be used as a function parameter type, because for function parameter types, array-to-pointer conversion takes place immediately, meaning we don't ever need to specify the dimension of the innermost array of a (possibly multidimensional) array:
void some_func(int (* f [])()); /* This is also legal. */

Related

Can we initiate an array literal with variables in C?

I have been searching if we can initiate an array literal with variables but couldn't find it. Bit of context, I want to pass an array literal to a function. Below is what I am trying to do:
int fun(int * a, int num){
int sum=0;
for (int i=0; i< num; ++i){
sum = sum + a[i];
}
return sum;
}
int main(){
int a = 3, b =2, c = 1 ;
int x[3] = {a,b,c}; // Is this legal? It compiles fine on all compilers I tested.
int p = fun( (int[3]){a,b,c} , 3); // I want to do something like this. pass a literal to the fucntion
return 0;
}
From the C Standard (6.7.9 Initialization)
4 All the expressions in an initializer for an object that has static
or thread storage duration shall be constant expressions or string
literals.
The string literal defined in this record
int p = fun( (int[3]){a,b,c} , 3);
has automatic storage duration. So you may initialize it with non-constant expressions in particularly using the variables a, b, and c.
Pay attention to that as the function does not change the passed array then the first parameter should have the qualifier const and to avoid overflow it is better to declare the return type as long long int.
Here is a demonstration program.
#include <stdio.h>
long long int fun( const int * a, size_t n )
{
long long int sum = 0;
for ( size_t i = 0; i < n; ++i )
{
sum += a[i];
}
return sum;
}
int main( void )
{
int a = 3, b = 2, c = 1 ;
printf( "%lld\n", fun( ( int[] ){a, b, c} , 3 ) );
}
Your code (sans the extra x array) compiles just fine with -std=c99 so yes, I'd say it's standard C99 code.
#include <stdio.h>
int fun(int a[], int num) {
int sum = 0;
for (int i = 0; i < num; ++i) {
sum = sum + a[i];
}
return sum;
}
int main() {
int a = 3, b = 2, c = 1;
int p = fun((int[3]){a, b, c}, 3);
printf("%d", p);
return 0;
}
This would not be allowed if the initializer is static, since the value needs to be assigned before the program executes. From C99:
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
Otherwise, each initializer needs to be an "assignment-expression" or, in other words, a valid expression that can be assigned to an object.
So yes, this is legal in C.
Well, yes. The array is being initialized as it should which can be tested by printing it.
The array is also being sent to the function properly as p returns 6. However, do note that you are making a new array to send to the function.

Regarding question about function pointer in C?

I was reading about function pointer. That it contains address of instructions. And there I encountered one question to find an element in array using function pointer. Here is the code.
#include <stdio.h>
#include <stdbool.h>
bool compare(const void* a, const void* b)
{
return (*(int*)a == *(int*)b);
}
int search(void* arr, int arr_size, int ele_size, void* x, bool compare(const void*, const void*))
{
char* ptr = (char*)arr; // Here why not int *ptr = (int*)arr;
int i;
for (i = 0; i < arr_size; i++)
{
if (compare(ptr + i * ele_size, x))
{
return i;
}
}
return -1;
}
int main()
{
int arr[] = { 2, 5, 7, 90, 70 };
int n = sizeof(arr) / sizeof(arr[0]);
int x = 7;
printf("Returned index is %d ", search(arr, n, sizeof(int), &x, compare));
return 0;
}
In the search function char *ptr = (char*)arr; is used which is giving perfect answer = 2.
But when I have used int *ptr = (int*)arr; it gives -1 as answer.
Why is this? Can anyone explain this?
A char is the smallest addressable unit in any C program, and on most system it corresponds to a single byte. That treats the array as a generic sequence of bytes, and uses the ele_size to calculate the byte-position of each element with ptr + i*ele_size.
If you use int *ptr then the byte-position calculation will be wrong by a factor of sizeof(int) (typically 4), since the pointer arithmetic will be done in units of the base type (int instead of char).
The function search knows nothing about what is the type of elements of the array pointed to by the pointer arr of the type void *.
So casting the pointer to the type int * does not make a sense. If to do so then the expression ptr + i*ele_size where the pointer arithmetic is used will produce an incorrect result.
That it contains address of instructions
There is a subtle difference between normal (object) pointers and function pointers. It is not possible to access the single instructions of a function - they do not have the same length.
With other pointers the increment (arithmetic) is adapted to the type, whether as p[i] or p + i or *(p+i).
Side note: there still is int at the bottom of the call chain:
return (*(int*)a == *(int*)b);

Passing multidimensional array in another way?

#include <stdio.h>
void arraypass(int from, int to, int a[][2]);
int main()
{
setbuf(stdout, NULL);
int t1 = 0, t2 = 0;
int testArray[10][2];
for (t1 = 0; t1 < 10; t1++)
{
testArray[t1][t2] = t1 + 1;
}
t2++;
for (t1 = 0; t1 < 10; t1++)
{
testArray[t1][t2] = t1 + 10;
}
arraypass(1,5,testArray);
return 0;
}
void arraypass(int from, int to, int a[][2])
{
int b;
for (b = from; b <= to; b++)
{
printf("%d ",a[b][0]);
printf("%d\n",a[b][1]);
}
}
Why is it that
int a[][2]
works, but not
int a[][]
for the argument definitions in this?
void arraypass(int from, int to, int a[][2]);
And, is there a way to possibly pass an entire multidimensional array at once, or do I need to perform some kind of loop?
For the compiler, a vector is a hidden pointer to its first item.
For example:
int a[2];
a[0]=0;
a[1]=1;
is the same of:
int a[2];
*(a+0)=0;
*(a+1)=1;
When you pass a multidimensional array (o a simple array) you should use pointers instead of a vector:
void arraypass(int from, int to, int **a);
and then if you want to use it you could do something like this:
void arraypass(int from, int to, int **a){
int i,j;
for(i=from; i<end; i++) {
for(j=0; j<2; j++) {
printf("%d",a[i][j]);
}
}
You have to remember that arrays decays to pointers. That means, when they are (for example) passed as arguments to functions the function receives a pointer.
What int a[][2] does, is the same as int (*a)[2], which means that a is a pointer to an array of two int. That is different from a pointer to an array of any other dimension, which is why you don't have to specify the primary "dimension" (as that to the compiler is the same as a pointer) but you do have to specify the other "dimension(s)".
This is related to this answer in the C FAQ.
Because the function receives a pointer when an array is passed to a function, the compiler needs to know the dimensionality of the array that the pointer will be to (in this case, two), but doesn't care how long the sequence of pointers to two-element arrays is going to be.

Logic array in C

I am trying to test a logic function from four inputs a,b,c and d.
Each input is either 0 or 1.
I have been trying to accomplish this with arrays.
I want to pass back a 1 if a column in logicXY array matches that of the combLogic array.
int comb(int** combLogic, int** logicXY){
int x, y, logicOut;
for ( x = 0; x < 4; x++ ){
if (logicXY[0][x] == combLogic[x]){
logicOut = 1;
}
}
return logicOut;
}
int main void(){
int** combLogic[4] = {a,b,c,d}; /*logic input*/
int** logic[4][4] = {{1,0,0,1}, {1,0,1,1}, {0,1,0,0}, {0,1}}; /*return 1 if any of these combinations match the logic input*/
int comb(combLogic, logicXY); /*send to function*/
}
I know the function is not complete but I don't think I am passing the arrays correctly. I have read a number of tutorials but I cant seem to grasp the theory.
EDIT
I have got a few steps forward but it still isn't working. This is what I have now.
Function declaration in .h
int comb(logicInput,logicTest);
Function in .c
/* Function - Combination */
int comb(int** logicInput, int** logicTest){
int x, y, logicOut;
for ( x = 0; x < 4; x++ ){
if (logicTest[0][x] == logicInput[x]){
logicOut = 1;
}
}
return logicOut;
}
The loop in part of the main.c
int output = 0;
int logicInput[4] = {0,1,1,1};
int logicTest[4][4] = {{1,0,0,1}, {1,0,1,1}, {0,1,0,0}, {0,1,1,1}};
int comb(logicInput,logicTest);
output = comb;
The code steps over the int comb(logicInput,LogicTest) and never carries out the function.
If I take out int from the line then it carries out the function, returns the value but when the value is written to output it is nothing like the value that was returned from the function.
EDIT
I have made a few changes to the code so it does appear to work and with only one warning from the compiler for the function declaration in .h that I cannot seem to fix.
warning: parameter names (without types) in function declaration [enabled by default]
Function declaration in .h
int comb(logicInput,logicTest);
Function in .c
int comb(int** logicInput, int** logicTest){ /*Points to the arrarys in the main program*/
int x, i, logicOut;
for(i = 0; i < 4; i++){ /*test each column*/
for ( x = 0; x < 4; x++ ){ /*test each row*/
if (logicTest[i][x] == logicInput[i][x]){
logicOut = 1;
break;
}
}
if(logicOut == 1)break; /*Break when logicOut == 1 the first time it happens*/
}
return logicOut;
}
Loop in main.c
int output;
int logicInputC1[4] = {0,1,0,1};
int logicTestC1[4][4] = {{1,0,0,1}, {1,0,1,1}, {0,1,0,0}, {0,1,0,1}};
output = comb(logicInputC1,logicTestC1);
If I deviate from this code I just seem to end up with the compiler failing to build and even more warnings.
int * comblogic[4] = {a, b, c, d} //where a, b, c, and d, are arrays of size 4; aka int a[4];
int logicArray[4][4] = values;
in your loop:
int comb(int** combLogic, int** logicXY){
int x, y, logicOut;
for(int i = 0; i < 4; i++){
for ( x = 0; x < 4; x++ ){
if (logicXY[i][x] == combLogic[i][x]){
logicOut = 1;
break;
}
}
if(logicOut == 1)break; //incase you want to break when logicOut == 1 the first time it happens
}
return logicOut;
}
This is wrong:
int comb(int** logicInput, int** logicTest)
Try this:
int comb(int logicInput[4], int logicTest[4][4])
The difference is that int ** expects a pointer to a pointer (or an array of pointers), but when you define an array like you have then there are no pointers at all, so it doesn't work.
OK, technically, when you pass an array to a function it takes the address of that array and passes it by reference. This means you have a pointer to an array, but there are still no pointers inside that array.
When you pass an array you must always say what the dimensions of all but the first axes are, or else the compiler will not know how many entries to skip to get to the next row. In this case I gave the example as int [4][4], but it could just as well have been int [][4], should you have wished to give an unknown number of data rows.
The confusion arrises becuase C uses the same a[x] notation to access both int ** and int[n][m], but they do not look the same in memory.

Passing two-dimensional array to a function by refrence (C Programming) [duplicate]

This question already has answers here:
Manipulate multidimensional array in a function
(4 answers)
Closed 8 years ago.
I'm learning pointers, and gotten stuck for an hour now, with this code,
#include <stdio.h>
int determinant(int **mat) /* int mat[3][3] works fine.. int *mat[3] doesn't.. neither does int *mat[] */
{
int det;
int a=*(*(mat+0)+0); // printf("\n%d",a);
int b=*(*(mat+0)+1); // printf("\n%d",b);
int c=*(*(mat+0)+2); // printf("\n%d",c);
int d=*(*(mat+1)+0); // printf("\n%d",d);
int e=*(*(mat+1)+1); // printf("\n%d",e);
int f=*(*(mat+1)+2); // printf("\n%d",f);
int g=*(*(mat+2)+0); // printf("\n%d",g);
int h=*(*(mat+2)+1); // printf("\n%d",h);
int i=*(*(mat+2)+2); // printf("\n%d",i);
det = a*(e*i-h*f) - b*(d*i-g*f) + c*(d*h-e*g);
return det;
}
int main()
{
int mat[3][3];
int i,j;
printf("Enter the 3 X 3 matrix:\n\n");
for (i=0;i<3;i++)
{
for (j=0;j<3;j++)
{
scanf("%d",*(mat+i)+j);
}
}
printf("\nThe determinant of the given 3 X 3 matrix is %d",determinant(mat));
return 0;
}
I don't think anything is wrong with the function call. Maybe the problem is while accepting the arguments. Idk, isn't mat a pointer to an 1-dimensional array, which would again be a pointer to the array element, making mat a pointer to a pointer?
When I print some text at places (just to check), i find that the execution goes till after int det in the function, and the program crashes in the next step.
mat [3][3] works well, but i wanna use some * there, because as i said, i'm 'learning'..
Please help!
Thanks :)
The correct prototype for your function is
int determinant(int mat[][3]);
or
int determinant(int (*mat)[3]);
(both are equivalent because of a special rule for arrays as function arguments)
Then you can simply access your matrix elements with something like mat[i][j].
This is because 2 dimensional array and pointer to pointer are not same.
No matter how much dimension does an array have, its 1 dimensional in actual memory. So we can access it serially.
#include <stdio.h>
#include <conio.h>
int determinant(int *matrix1stMember)
{
int a, b, c, d, e, f, g, h, i;
a = *(matrix1stMember + 0);
b = *(matrix1stMember + 1);
c = *(matrix1stMember + 2);
d = *(matrix1stMember + 3);
e = *(matrix1stMember + 4);
f = *(matrix1stMember + 5);
g = *(matrix1stMember + 6);
h = *(matrix1stMember + 7);
i = *(matrix1stMember + 8);
return ( a*(e*i-h*f) - b*(d*i-g*f) + c*(d*h-e*g) );
}
int main()
{
int matrix[3][3]; // int matrix[y][x]; not [x][y]
int i, j;
printf("\nEnter 3x3 Matrix : ");
for(j = 0; j < 3; j++)
{
for(i = 0; i < 3; i++)
{
scanf("%d", &matrix[j][i]);
}
}
// call function determinant(int*) using first member of array
printf("\nDeterminant = %d", determinant(&matrix[0][0]));
getch();
return 0;
}
If we have to access via row and column then we can do following
data = *(_1stMemberofArray + rowIndex*totalColumn + columnIndex);
For Example,
data = matrix[2][1];
where datatype of matrix is
int matrix[3][3];
is identical to.
data = *(matrixPointer + 2*3 + 1);
where 3 is total column 2 is row(vertical or y) and 1 is column(horizontal or x).
and datatype of matrixPointer is,
int* matrixPointer;
and it should point to first member of matrix;
2D array dont decay to pointer to pointer. You can decay them to pointers so your code should look like
int determinant(int *mat) {
int det;
int a=*((mat+0)+0); // printf("\n%d",a);
int b=*((mat+0)+1); // printf("\n%d",b);
int c=*((mat+0)+2); // printf("\n%d",c);
int d=*((mat+1*3)+0); // printf("\n%d",d);
int e=*((mat+1*3)+1); // printf("\n%d",e);
int f=*((mat+1*3)+2); // printf("\n%d",f);
int g=*((mat+2*3)+0); // printf("\n%d",g);
int h=*((mat+2*3)+1); // printf("\n%d",h);
int i=*((mat+2*3)+2); // printf("\n%d",i);
det = a*(e*i-h*f) - b*(d*i-g*f) + c*(d*h-e*g);
return det;
}
The above code is just for illustration, showing how 2-D array decays to 1-D array.
When you try to access the array using braces like a[2][1] then compiler does is unfolding for you. By unfolding I mean, the multiplication by sizeof(type) (as shown above multiply by 3). So if you decaying to 1-D you have to do it yourself.
One more thing to add, always pass the size of the dimension to the function who is has to tread the 1-D array as 2-D. like
int determinant(int *mat, int cols, rows);
Edit 1:
Just to add that #JensGustedt ans is also ok if you want to keep the arrays intact across function calls.
The correct signature for the function would be
int determinant(int mat[][3])
or
int determinant(int (*mat)[3])
In the context of a function parameter declaration, T a[] and T *a are exactly equivalent.
With either option, you can subscript mat normally in the function as you would in main:
int a = mat[0][0];
int b = mat[0][1];
...
Since a subscript operation implicitly dereferences the pointer (a[i] == *(a + i)),
you don't have to do the explicit dereference dance, making your code easier to read and understand (and potentially faster; I've seen some compilers generate more instructions for *(*(a + i) + j) than a[i][j], but don't rely on that being true everywhere).
Remember that when an expression of "N-element array of T" appears in most contexts, it is converted to an expression of type "pointer to T" and its value is the address of the first element in the array. Since the expression mat in the call to printf has type "3-element array of 3-element arrays of int", it is replaced with an expression of type "pointer to 3-element array of int".
If we pass a multidimensional array to a function:
int a2[5][7];
func(a2);
We can not declare that function as accepting a pointer-to-pointer
func(int **a) /* WRONG */
{
...
}
The function ends up receiving a pointer-to-an-array, not a pointer-to-a-pointer.

Resources