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.
Related
I am a beginner coder in C.
I have the following code:
int main()
{
struct* Array[malloc(10*sizeOf(struct)];
/* I then fill the struct. (int num,float points)
* I then want to pass this array that I've filled up to a sortList function,
* which then outputs the sorted array back to main().
*
* Then I want to output the array as: "number, points" */
}
struct struct
{
int number;
float points;
}
void sortList()
{
/*sort Array, then return sorted array*/
}
How would I pass the array and then back?
Any links or suggestions are greatly helpful.
How to pass an array by reference ...?
When an array a is passed to a function foo(a), it is the actual argument. In C, when an array is passed to a function, rather than the entire array being given to foo(), the expression a is converted to the address of the first element of the array.
Except when it is the operand of the sizeof operator, the _Alignof 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. ... C11dr §6.3.2.1 3
So foo() is given an address of type int *. Let us assume the value is 1234.
Inside the function void foo(int *fa), the formal parameter fa takes on the value 1234.
From the caller's point-of view, this is pass-by-reference as a is affected by foo() and the function received a "reference". From the function's point-of-view, this is pass-by-value as fa gets a copy of the converted a. In C, it is this second-point-of view that is usually spoken of when folks says that C does not pass anything by reference. In both cases, fa is an int * and not an array.
foo() had the address of main's a in the variable fa. So code fa[0] = 456 sets a value that is still seen after foo() completes.
void foo(int *fa) {
fa[0] = 456;
}
int main(void) {
int a[5];
a[0] = 123;
printf("%d\n", a[0]); // prints 123
foo(a);
printf("%d\n", a[0]); // prints 456
return 0;
}
I used a simply int array to explain things. Yet original code had other problems. Below are ideas on how to allocate memory.
// struct* Array[malloc(10*sizeOf(struct)];
struct ok12type* ok12Array = malloc(sizeof *ok12Array * 10);
....
// Do stuff with ok12Array
...
free(ok12Array);
ok12Array = NULL;
// Do _not_ do stuff with ok12Array
Code seems to be wrong.
In C, arrays are always pass by reference.
First off you should name your struct. I gave it the name typename in my examples below.
To allocate the memory, you want:
struct typename *Array = malloc(10*sizeof(struct typename));
Passing the array to a function is easy, just declare your function as:
void sortList(struct typename *Array)
{
}
You can then work on the array directly in the function, because arrays are always pass by reference, never pass by value.
So your program might look like:
struct typename
{
int number;
float points;
}
int main()
{
struct typename *Array = malloc(10*sizeof(struct typename));
Array[0].number = 5;
Array[0].points = 7;
Array[1].number = 2;
Array[1].points = 11;
/* Fill the rest of the array. */
/* Sort it. */
sortList(Array);
}
void sortList(struct typename *Array)
{
/* Do your sorting here. */
}
#include <stdio.h>
void test(int arr[]);
int main ()
{
int *arr[3];
int ar1[2] = { 1, 2 };
int ar2[3] = { 3, 4, 5 };
int vla[ar2[1]];
arr[0] = ar1;
arr[1] = ar2;
arr[2] = vla;
for (int i = 0; i < 3; i++)
{
test(arr[i]);
}
}
void test(int arr[])
{
printf("%zu\r\n", sizeof(arr));
}
As the title say: is this valid? and if so, is there a way to make test() output different values by using sizeof on function argument handed in like on array?
Yes it is valid and will give the size of an int pointer (that's what the type of the arr parameter is, there are no array parameters in C) in bytes. 1
To get the size of an array in bytes with sizeof, the argument has to be an actual array, not a pointer.
Consequently, it's not possible to get the size of an array passed as a parameter inside a function without passing an extra parameter specifying the size.
So,
is there a way to make test() output different values by using sizeof on function argument handed in like on array?
no. (Without editing the function body.)
1 If you're wondering how it's possible to pass an array as a pointer parameter, it's because of the implicit array-to-pointer conversion, known as array decaying.
Is this:
void test(int arr[]) {
printf("%d\r\n", sizeof(arr));
}
valid?
It is NOT a valid1 code, however it is equivalent to: sizeof(int*), not size of the array, arr, because as you pass the array as an argument it decays to a pointer2 i.e. it looses the information about the size of the whole array. The only way to convey this information into a function is through an additional, second, parameter.
Is there a way to make test() output different values by using sizeof on function argument handed in like on array?
If you want to print the size of the array you are passing, you could use something like: sizeof(array) as an second argument of the function, where the function signature would be:
void test(int arr[], size_t size);
you could insert the above as second argument and get the size of the first argument.
1. There is a type mismatch between size_t(the returning type of sizeof()) and int (the expected type matching the specifier "%d" in the printf(),, which leads to undefined behaviour.
2. arr[] outside the function represents the whole array as an object and that is why if you apply sizeof() you will get the size of the whole array, however, when passed as argument, arr decays to a pointer of the array's first element and if you apply sizeof() you'll get the size of the type of the pointer.
Is this code well defined by using sizeof operator?
Pedantically: No
sizeof() returns type size_t. "%d" expects type int. Using mis-match type results in undefined behavior (UB). Step 1: Use matching specifier
// printf("%d\r\n", sizeof(arr));
printf("%zu\r\n", sizeof(arr));
// or
printf("%d\r\n", (int) sizeof(arr));
The following prints the size of a pointer arr. The code in main() is not relevant.
void test(int arr[]) {
printf("%zu\r\n", sizeof(arr));
}
// or simply: remove (), \r of dubious value
printf("%zu\n", sizeof arr);
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.
When passing an Array Argument to a Function, it's memory address is copied into an Array Parameter. Because of this:
sizeof() returns the size of the entire array for the Array Argument (inside caller)
sizeof() returns the size of a pointer for the Array Parameter (inside called Function)
My question is, what type is the Array Parameter inside the Function? And more specifically, what type is returned when using the & Operator on an Array Parameter? It's not a Pointer to Array of Type, nor is it a Pointer to Type, as shown in this code (labeled BAD):
void doSomething(int arrayParam[10]);
int main()
{
int array[10] = { 0 };
int (*arrayPtr)[] = &array; // OK
printf("%p\n", array); // 0x7fff5fbff790
doSomething(array);
return 0;
}
void doSomething(int arrayParam[10])
{
printf("%p\n", arrayParam); // 0x7fff5fbff790
int (*arrayPtr)[] = &arrayParam; // BAD: Initialization from incompatible pointer type
int * element0Ptr = &arrayParam; // BAD: Initialization from incompatible pointer type
element0Ptr = arrayParam; // OK
element0Ptr = &arrayParam[0]; // OK
}
Thanks for any help you can offer! :)
Most of the time, when you use an array, it decays to a pointer to its initial element. So, if you have:
void f(int* x);
int array[10];
int* initial_element_of_array = array; // array decays to a pointer to initial element
f(array); // same here
f() gets a pointer to the initial element of array.
Something that is rather confusing at first is that if a function has a parameter that is of an array type (like if you had void f(int x[])), this is actually converted such that it is exactly the same as void f(int* x). There is no difference between them: array type parameters are the same as pointer type parameters.
Once you pass an array to a function, all you have is a pointer to its initial element, so if you apply the & operator to the int*, you get an int** (a pointer to an int*).
I would like to know if there is any way to return an char array.
I tried something like this "char[] fun()" but I am getting error.
I don't want a pointer solution.
Thanks!
You can return an array by wrapping it in a struct:
struct S {
char a[100];
};
struct S f() {
struct S s;
strcpy( s.a, "foobar" );
return s;
}
Arrays cannot be passed or returned by value in C.
You will need to either accept a pointer and a size for a buffer to store your results, or you will have to return a different type, such as a pointer. The former is often preferred, but doesn't always fit.
C functions cannot return array types. Function return types can be anything other than "array of T" or "function returning T". Note also that you cannot assign array types; i.e., code like the following won't work:
int a[10];
a = foo();
Arrays in C are treated differently than other types; in most contexts, the type of an array expression is implicitly converted ("decays") from "N-element array of T" to "pointer to T", and its value is set to point to the first element in the array. The exceptions to this rule are when the array expression is an operand of either the sizeof or address-of (&) operators, or when the expression is a string literal being used to initialize another array in a declaration.
Given the declaration
T a[N];
for any type T, then the following are true:
Expression Type Decays to Notes
---------- ---- --------- -----
a T [N] T * Value is address of first element
&a T (*)[N] n/a Value is address of array (which
is the same as the address of the
first element, but the types are
different)
sizeof a size_t n/a Number of bytes (chars) in array =
N * sizeof(T)
sizeof a[i] size_t n/a Number of bytes in single element =
sizeof(T)
a[i] T n/a Value of i'th element
&a[i] T * n/a Address of i'th element
Because of the implicit conversion rule, when you pass an array argument to a function, what the function receives is a pointer value, not an array value:
int a[10];
...
foo(a);
...
void foo(int *a)
{
// do something with a
}
Note also that doing something like
int *foo(void)
{
int arr[N];
...
return arr;
}
doesn't work; one the function exits, the array arr technically no longer exists, and its contents may be overwritten before you get a chance to use it.
If you are not dynamically allocating buffers, your best bet is to pass the arrays you want to modify as arguments to the function, along with their size (since the function only receives a pointer value, it cannot tell how big the array is):
int a[10];
init(a, sizeof a / sizeof a[0]); // divide the total number of bytes in
... // in the array by the number of bytes
void init(int *a, size_t len) // a single element to get the number
{ // of elements
size_t i;
for (i = 0; i < len; i++)
a[i] = i;
}
arrays aren't 1st class objects in C, you have to deal with them via pointers, if the array is created in your function you will also have to ensure its on the heap and the caller cleans up the memory
A Very very basic code and very very basic explanation HOW TO Return
array back from a user defined function to main function..Hope It
helps!! Below I have given complete code to make any one understand
how exactly it works? :) :)
#include<iostream>
using namespace std;
char * function_Random()
{
int i;
char arr[2];
char j=65;//an ascII value 65=A and 66=B
cout<<"We are Inside FunctionRandom"<<endl;
for(i=0;i<2;i++)
{
arr[i]=j++;// first arr[0]=65=A and then 66=B
cout<<"\t"<<arr[i];
}
cout<<endl<<endl;
return arr;
}
int main()
{
char *arrptr;
arrptr=function_Random();
cout<<"We are Inside Main"<<endl;
for(int j=0;j<2;j++)
{
cout<<"\t"<<arrptr[j];
}
return 0;
}