diffrent results when trying to find length of an array using pointer arithmetic inside a function and inside of main - arrays

for some odd reason when I run this code:
int func(int arr[],int n) {
int a = *(&arr + 1) - arr;
printf("%d",a);
}
I get an address,
and when I run the same code inside main I get the length of the array.
any idea why?
I ran it inside main and it gave me the length of an array, and when I ran it inside a function it gave me an address.

This function declaration
int func(int arr[],int n){
is adjusted by the compiler to
int func(int *arr,int n){
On the other hand. the array passed to the function as an argument expression is implicitly converted to a pointer to its first element of the type int *.
So within the function you actually deal with a pointer instead of an array.
In any case the expression with pointers used in this line within the function
int a = *(&arr + 1) - arr;
is invalid and invokes undefined behavior.

Related

array returning error in c

I am getting an error in the return line. "Incompatible pointer to integer conversion returning 'int (*)[2]' from a function with result type 'int'" can someone explain what is theory behind this error and how to fix it? still I am getting right result, but don't know about this error. (hints: I am very beginner )
here is my testing code.
#include <stdio.h>
#include<string.h>
/* two diminsanl array testing*/
int array_function(int phase,int array[][2]);
int main()
{
int phase =1;
int array[][2]={};
array_function(phase, array);
phase =2;
array_function(phase, array);
return 0;
}
int array_function(int phase, int array[][2])
{
if(phase==1)
{
array[0][0]=1;
array[0][1]=2;
array[1][0]=3;
array[1][1]=4;
}
if(phase==2)
{
printf("%d\n",array[0][0]);
}
return array; //<------------- error line
}
Well, first of all, your function is expecting an int return, but you're trying to return an int[][].
And, you can't return an array by value in c. You'll need to return a pointer, or wrap the array as part of a struct.
You have int as return type of function ( int array_function() ) but are trying to return a pointer(return array;). Since it look that you don't need to return anything just have the return type as void or return 0. Since array is passed by reference it automatically gets the changes that you do to it inside the function.
If you statically create an array you have to specify both dimensions.
Arrays are passed as pointers and if you pass a static array it is good practice to give the dimensions in the parameters of the function. Simply pass the arrays name to any function even if you allocated it dynamically. If you want to return an array you should return an int* or int** for a 2D array.
Let's say you want to create an array in a function and let the caller have it.
int *createArray(int size)
{
int *array = malloc(size * sizeof(int));
return array;
}
You can call this function from your main.
int *list;
list = createArray(2);
And modify list like any other array.
This is your code properly.
#include <stdio.h>
/* two diminsanl array testing*/
void array_function(int phase, int array[2][2]);
int main()
{
int phase = 1;
int array[2][2];
array_function(phase, array);
phase = 2;
array_function(phase, array);
return 0;
}
void array_function(int phase, int array[2][2])
{
if (phase == 1)
{
array[0][0] = 1;
array[0][1] = 2;
array[1][0] = 3;
array[1][1] = 4;
}
if (phase == 2)
{
printf("%d\n",array[0][0]);
}
}
First this line, is not a legal assignment:
int array[][2]={};
For what you are doing, this line would work:
int array[][2]={0,0,0,0};
second As others have pointed out, this line is attempting to return int[][]. Two problems with this, 1) C cannot return the value representation of an array of ints, (although it can return pointers, such as int **, you don't need to here. See note at bottom). And 2) the prototype clearly calls for int
return array; //<------------- error line
For now, simply change the line to:
return 0;
Those two changes will result in your code populating array[][] with no errors.
Note: because you are passing your array by reference, ( array_function(phase, array); ) the values assigned to array within array_function() are made available back in the main() function without having them returned as a return. (i.e. int ** array_function(phase, array) )
So, first of all, the type of the expression array in array_function is int (*)[2], or "pointer to 2-element array of int".
Except when it is the operand of the sizeof or unary & operator, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
When you call phase_array from main, like so:
array_function(phase, array);
the expression array has type "2-element array of 2-element array of int"; since it is not the operand of the sizeof or unary & operators, it is converted to an expression of type "pointer to 2-element array of int", and its value is set to the address of the first element (&array[0]). This pointer value is what gets passed to array_function.
In the context of a function parameter list, declarations of the forms T a[N] and T a[] will be interpreted as T *a; all three declare a as a pointer to T. So,
int array_function(int phase, int array[][2])
is the same as
int array_function(int phase, int (*array)[2])
Which brings us to your error message: you've declared array_function to return an int (which you don't ever use in your main function, btw), but the type of the expression array is int (*)[2]; hence the error message. The two types are not *compatible", and the compiler flags this as an error.
Since you've passed the address of the first element of array to array_function, any changes you make to the array contents will be reflected in main, so you really don't need to return the array. As others have suggested, just change the type of the function to void and don't return anything.

Why printing a static 2D array in C gives me seg fault?

I just want to print out a static array (2D array) in C using functions. I use gcc as my compiler. When I try to run my code it gives me a seg fault and I dont have any idea why:
#include <stdio.h>
void print_out_an_array(int n, int m, int tab[n][m])
{
int i,j;
for(i=0; i<n; i++)
for(j=0; j<m; j++)
printf("tab[%d][%d] = %d\n", i, j, tab[i][j]);
}
int main(int argc, char **argv)
{
int tab[2][4] = {{1,2,3,4}, {5,6,7,8}};
print_out_an_array(tab, 2, 4);
return 0;
}
your function call and function definition doesnt match
your function call
print_out_an_array(tab, 2, 4);
but in function definition your first argument is int
void print_out_an_array(int n, int m, int tab[n][m])
make the arguments same, like:
change function call to
``print_out_an_array(2, 4, tab);`
update:
check this code it works
and also read this for reference C, passing 2 dimensional array
In your function definition, first parameter is int type but you are calling your function with first argument as int **. Change your function call to
print_out_an_array(2, 4, tab);
About the question in your comment:
Ok, but how about this code: http://ideone.com/Z4mHkb why it gives me an error?
Function parameters **tab and tab[n][m] are not equivalent. Compiler, on seeing tab [m][n] as function parameter, interprets it as
void fun(int (*)[m]tab, int n, int m)
i.e , it interprets tab as a pointer to an array of m integers. While on seeing int **tab, it simply interprets tab as a pointer to a pointer to integer (or an array of pointers ( int *tab[]) to int ).
Instead of answering the original solution whose solution is obvious, I answer the other one from your comment.
Your array is a
int[][N]
while you pass a
int ** to your function.
These are completely different from each other:
An int[][N] has all values from all dimensions beneath each other.
An int **, however, points to one or more pointers, in turn pointing to the real values.
At int[][], you can omit one level of indirection and can turn it into a
int (*)[N]
i. e. a pointer to an array. This array must be of determined size, which isn't fulfilled in your case as well.

SubArray, passing address to a function

I have a question regarding passing address of first element of an array to a (recursive) function:
selectionSort( &b[1], size-1);
When address is passed to a function, function parameter must be a pointer as I know. selectionSort method gets int b[] as argument. Not a pointer.
But code works without any problems. Also this code generates subarrays. When we pass the 1st element does it become the subarray's zeroeth element?
void selectionSort(int b[], int size)
{
int temp,i;
if (size>=1)
{
for (i = 0; i < size; i++)
{
if (b[i]<b[0])
{
temp=b[0];
b[0]=b[i];
b[i]=temp;
}
}
selectionSort( &b[1], size-1 );
}
}
Whenever you have a function like:
void f(int b[]);
this is the same as
void f(int *b);
The [] syntax for function parameters is just a special syntax to let the reader know that you intend to use the parameter like an array, but it is actually just a pointer. You can't pass an actual array to a function. Pointers and arrays work very similarly in C, so for the most part you can work with a pointer as if it were an array (but be careful -- there are important exceptions).
For example, when you access an element of an array like this:
array[index]
this is the same as
*(array+index)
and it doesn't matter whether array is a real array or just a pointer.
So &b[1] is the same as &*(b+1), which is the same as b+1.
If we were to write the code so that we see the b parameter as a pointer, it would look like this:
void selectionSort(int *b, int size){
.
.
.
selectionSort( b+1, size-1 );
.
.
.
}
Now, you can see that selectionSort is being passed a pointer to an int, and it calls itself with a pointer to the next int.
Yes, the code will create 'sub arrays' you should use:
A pointer to an array of integers
selectionSort(int (*b)[], int size)
And call the function using:
selectionSort( &b[1], size-1 );

How to use an array pointer in a function?

I had to write a program which has a function that sums all positive number in an array, but using function parameter array as an pointer. There in main function a problem occurs, when i try to call sum function. here is my source code:
#include <stdio.h>
#include <conio.h>
int posit(int *x[], int n){
int s=0;
for(int i=0; i<n; i++){
if(*x[i]>0){
s=s+*x[i];
}
}
return s;
}
int main(){
int k;
scanf("%d",&k);
int a[k];
for(int i=0; i<k; i++){
scanf("%d",&a[i]);
}
int b=posit(&a,k);
printf("%d\n", b);
getch();
return 0;
}
When an array is passed to a function it decays to a pointer to its first element. Change the signature of the function to:
int posit(int* x, int n){ /* Equivalent to 'int posit(int x[], int n)' */
and change the element access syntax of the array in the function from *x[i] to just x[i]. The invoke the function:
int b=posit(a,k);
Another point worth mentioning is to check the return value of scanf(), which returns the number of assignments made, to ensure &a[i] is actually being assigned and the program is subsequently not using uninitialized variables.
You may find the Arrays and Pointers section of the C FAQ useful.
Actually in your example you are passing to function pointer to pointer (please note that similar notation is very often used with main argument char *argv[]).
As mentioned in hmjd post while passing array to function this is converted to address of its first element. Instead of explicitly using pointer (int *x) you can also use array notation (int[] or even int[k]) but those are the same.
Please also note that in second method (int[k]) size provided doesn't matter and inside function it will be not known. This is only important to include size when you are dealing with multiple dimension arrays, but this is other story...
From K&R2
When an array name is passed to a function, what is passed is the
location of the initial element. Within the called function, this
argument is a local variable, and so an array name parameter is a
pointer, that is, a variable containing an address.
So you will be passing only the first element to the function.
Once this is understood your source can be modified as follows
int posit(int *x, int n)
and to call this function from main you can use
int b=posit(a,k); //Note only the location of the first element is being passed

I'm trying to make 2d array, pass it to function and then update the modified array in main

The compiler shows:
Warning: passing argument 1 of 'fun' from incompatible
pointer type; note: expected 'int ()[5]' but argument
is of type 'int (*)[5][5]'
Code:
#include<stdio.h>
void fun(int * b[][5])
{
int x=11,y=90;
printf("here");
*b[1][3] = x;
*b[3][1] = y;
*b[2][2] = x + ++y;
}
int main()
{
int a[5][5];
a[1][3] = 12;
a[3][1] = 145;
fun(&a);
printf("%d %d %d",a[1][3],a[3][1],a[2][2]);
}
You do not need the asterisk in your function parameters, and you don't need to dereference the array b in your function. Arrays are passed by reference (so get rid of the ampersand in foo(&a) as well), because C treats them as pointers to the first element in the sequence.
Multidimensional arrays are treated as arrays of pointers to the start of smaller sub-arrays, i.e. arrays-of-arrays. Same explanation as above applies.
Your code should look like this in the end:
void fun(int b[][5]) // can also be (int (*b)[5]), i.e. array of 5 pointers
{
int x=11,y=90;
b[1][3] = x;
b[3][1] = y;
b[2][2] = x + ++y;
}
int main()
{ // ...
fun(a);
// ...
}
int a[5][5]; //is an 2d int array
When arrays are passed to a function, what really gets passed is a pointer to the arrays first element.
So calling the fun() function with fun(a) will actually pass the pointer to the a first element, in this case an int array of size 5. The function fun() will receive a pointer to an int array of size 5, that is to say int (*b)[5]. Note that int *b[5] is not the same and is an array of size 5 containing int pointers.
Your fun function can either have:
void fun(int b[][5])
or
void fun(int (*b)[5])
The first way to do it says that the function will receive a 2d array of ints, but since we know that what actually will be sent to the function is a pointer to the first element of the array a, the compiler will quietly compile the function as if the parameter were a pointer, since it's a pointer that it will receive.
The second way to do it explicitly shows what type it will receive, a pointer to an array of size 5.

Resources