Im relatively knew to C, i am used to program in Java so i find C a little bit difficult in what concerns arrays. I still cofuse myself with this cases:
int a [];
int* a;
int *a;
In java, i would do something like this to return an array in a function:
int [] returnArr(int [] a){
... modify a ...
return a;
}
int [] a = {...};
int [] b = returnArr(a); ##
How can i do the same in C, specially the parts with ##.
EDITED:
I have this function:
float *normalizeValues(float *v, float maxY){
int size = sizeof(v) / sizeof(float);
float max = findMax(v);
float ratio = maxY / max;
int i;
for(i = 0; i < size ; ++i){
v[i] = v[i] * ratio;
}
return v;
}
And im doing the following:
float vert [] = {306, 319, 360, 357, 375, 374, 387, 391, 391, 70, 82, 94, 91, 108, 114, 125, 127, 131};
int i = 0;
float *vert2;
vert2 = normalizeValues(vert, 0.7);
for(i = 0; i < sizeof(vert2) / sizeof(float); ++i){
fprintf(stdout,": %f\n",vert2[i]);
}
And the output is only 1 element.
EDIT: To directly answer your updated question: you have to pass in the size of the array. C has no mechanism to store the size of arrays like Java does. If the compiler knows about the size of the array because the array is a global or local variable, not dynamically allocated, then you can use the sizeof() operator. Otherwise, you have to know the size separately, or use sentinel values in your array (such as a 0.0 at the end, or a NULL).
As for arrays, pointers and arguments in general, see below:
You will be returning a pointer to the array, which is indicated with the '*' syntax:
int *returnArr(int[] a) {
// modify a...
return a;
}
int a[] = { ... };
int *b;
b = returnArr(a);
A few things to note:
You can't do assignments in variable declarations that involve non-constant expressions (e.g., function calls). This might have changed in C99, though.
The brackets go after the variable name, unlike in Java where they are part of the type. Even though Java's syntax is more consistent, it doesn't quite make sense in C where you often give the array size in the brackets in the variable declaration:
int a[3] = { ... };
There's no way to specify that a function returns an array as opposed to a plain pointer. In C, array references decay to pointers (though pointers and arrays are NOT the same thing, as is commonly claimed). That means that whenever you pass an array around, C only provides a means to a pass a pointer to the array. The whole array isn't actually copied. As it happens, the name of the array is also a pointer to the first element of the array.
Please also take note of what user268396 says in their answer. If you are planning to create a new array and return it, you'll need to either allocate the array dynamically, or have a pointer to an already allocated array be passed in (which is what it seems like you are kind of doing anyway).
You can't. When the function returns the stack frame will be wiped out (typically) and your generated array will be clobbered by that. You can however edit the function prototype to accept a pointer to the array to modify. That kind of function argument is known as an "output parameter". Example:
void function func(int a, int b, int[2] to_modify)
{
to_modify[0] = a;
to_modify[1] = b;
}
int main()
{
int foo[2];
func(1, 2, foo);
printf("Result: foo[0] = %d, foo[1] = %d\n", foo[0], foo[1]);
return 0;
}
This will print "Result: foo[0] = 1, foo[1] = 2".
Hope this helps
#include<stdio.h>
void change(int *c)/*Pointer c now has the first location of the array a[]*/
{
*(c+0) = 0;/*assign values to the array by adding step-size to the first array position*/
*(c+1) = 1;
*(c+2) = 2;
*(c+3) = 3;
*(c+4) = 4;
}
main()
{
int a[5]={10,20,30,40,50}; /* Declare and Assign an array a[] of size 5.*/
int *b = a; /*Declare and assign a Pointer to the location of the array.*/
change(b); /*pass the pointer(which is now pointing to first position of array) to the change() function.*/
printf("%d,%d,%d,%d,%d,",a[0],a[1],a[2],a[3],a[4]);/*Print the changed value.*/
}
Output: 0,1,2,3,4,
From Java point of view, Pointers are simply like(not exactly) Object references.
Object O;
O = New SomeClassName();
Like Object Reference O is pointing to some Actual Object of type SomeClassName, so does pointers in C:
int *b;
b = &a;
Variable b is simply pointing to the address location to a.
Taking a deep dive into array concepts:
int a[5];
int *b = a;
Here we are just saying like Mr.*b point to the first location of group a i.e. a[0].
Now the power pointer in C is that from now on, here after:
*b means a[0]
*(b+1) means a[1]
*(b+2) means a[2]
*(b+3) means a[3]
*(b+4) means a[4]
This means you change in *(b+4), you're changing a[4].
int* returnArr(int a[]){
//modify a
return a;
}
One need mention is when you use an array in the parameter list of a function, it will be converted into a pointer. So in main(...)'s declaration, char *argv[] and char **argv are actually same. In this case, int a[] and int* a are same. But array and pointer is not the same thing.
Take the following code as an example:
int a[10];
int main(){
int *p = a;
p[5] = 4;
return p[5];
}
p is a pointer, when we access p[i], note that the address of p is not the address of a, the content of p is the address of a. Then the code will:
access the memory to get the content of p, i.e. the address of a.
compute the offset based on i and type of the pointer(int).
access the memory to get the result.
a is an array of int, if we access a[i], the address of a is just the address of a[0], the code will:
Compute the offset based on i and the type int.
Access the memory.
Pointer and array are different types. So if you declare int *p in one file and use it in that file, but define the p as an array in another file, that will cause problem.
You may also wonder about int *p = a, in ANSI, if you use an array(its name) as an expression, the compiler will convert it into a pointer, pointing to the very first element of the array.
Update based on Jim Balter's comments:
If you use an array(its name) as an expression, the compiler will not always convert it into a pointer, pointing to the very first element of the array. For instance, in sizeof(p->q->a), p->q->a is an expression but if a is an array it isn't converted into a pointer.
"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.
In C, you can only return a pointer of an array in a function.
For example, if you want to return a string(array of char) in a function, you can return a pointer to a null-ended string. If you want to return an array of some other type(int, user-defined struct, etc), you can alloc some memory to store the array, and return the pointer of the array, return the size of the array in the parameter.
example:
int *function(int *size)
{
*size = 10;
int *intP = (int *)malloc((*size)*sizeof(int));
return intP;
}
Related
Bellow there is a simple code which asks the last name, and 2 grades for 5 persons separately. It also
finds the mean of all the grades and who has the higher grade.The question is about " * " symbol.
My professor is calling a function which is called readstudent(Tstudent *pstu);
What does * before pstu means, and why is it necessary?
Also when we go through readstudent(Tstudent *pstu) why there is "&" for grade 1 and 2 and there is no "&" for the name?
#include <stdio.h>
#include <string.h>
typedef struct student
{
char name[20];
float grade1;
float grade2;
} TStudent;
void readstudent( TStudent *pstu );
void printstudent( TStudent stu );
int main( void )
{
int N = 5;
TStudent a[N]; int i, imax; float max, mo, sum;
for(i=0; i<N; i++)
readstudent( &a[i] );
printf("\n Oi karteles twn foitntwv einai:\n");
for(i=0; i<N; i++)
printstudent( a[i]);
sum = 0;
for(i=0; i<N; i++)
sum = sum + (a[i].grade1+a[i].grade2)/2;
mo = (float)sum / N;
printf("\nO mesos oros bathmologias tns taksns einai %2.2f\n", mo);
imax = 0;
max = (a[0].grade1+a[0].grade2)/2;
for(i=0; i<N; i++)
if ((a[i].grade1+a[i].grade2)/2 > max)
{
max = (a[i].grade1+a[i].grade2)/2;
imax = i;
}
printf("\nO/H foitntns/tria me ton ypsnlotero meso oro (%4.2f) einai o/h %s.\n", max, a[imax].name);
return 0;
}
void readstudent( TStudent *pstu)
{
printf("Eisagwgh foitntn/trias: epwnymo <keno> bathmos1 <keno> bathmos2 <keno>: \n");
scanf("%s", pstu->name);
scanf("%f", &pstu->grade1);
scanf("%f", &pstu->grade2);
}
void printstudent( TStudent stu)
{
printf("Epwnymo: %s\n", stu.name);
printf("Bathmos-1: %4.2f\n", stu.grade1);
printf("Bathmos-2: %4.2f\n", stu.grade2);
}
Thanks for your time, appreciate your help!
So, quick crash course on pointers in C.
First of all, why do we use pointers in C? Basically, we have to use pointers for the following reasons:
To allow functions to modify their parameters
To track dynamically allocated memory
Pointers come in handy in other ways, because they offer a form of indirection. They allow us to manipulate other objects without having to know the other objects' names.
Indirection is a powerful tool in programming, one that you've already seen if you've dealt with arrays. Instead of creating 100 unique integer variables, we can create an array of integers, and use subscripting to refer to a specific object. That is, instead of writing
int var0 = 0;
int var1 = 1;
int var2 = 2;
...
int var99 = 99;
we can write
int var[100];
for ( int i = 0; i < 100; i++ )
var[i] = i;
Array subscript notation allows us to refer to an object indirectly, rather than by a unique name. It provides a shortcut for managing large numbers of objects by referring to them with a single expression. Pointers serve much the same purpose. Suppose we have several integer variables named x, y, and z. We can create a pointer p to refer to each one in turn:
int x = 10;
int y = 20;
int z = 30;
int *p;
Let's start by playing with x. We set p to point to x using the unary & address-of operator:
p = &x; // int * = int *
The type of the variable p is int *. The type of the expression &x is int *, and the value of the expression is the address of x. We can then change the value of x through p using the unary * indirection operator:
*p = 15; // int = int
Since the type of the variable p is int *, the type of the expression *p is int, and that expression designates the same object that the expression x does. So in the line above, we're changing the value stored in x indirectly through p. We can do the same thing with y and z:
p = &y;
*p = 25;
p = &z;
*p = 35;
Okay, cool, but why not just assign to x, y, and z directly? Why go through the pain of assigning their addresses to p and assigning values through *p?
Normally we wouldn't do it that way, but there's a case where it can't be avoided. Suppose we want to write a function that modifies the value of one or more of its parameters, like so:
void foo( int x )
{
x = 2 * x;
}
and call it like this:
int main( void )
{
int val = 2;
printf( "before foo: %d\n", val );
foo( val );
printf( "after foo: %d\n", val );
return 0;
}
What we want to see is
before foo: 2
after foo: 4
but what we get is
before foo: 2
after foo: 2
It doesn't work because C uses a parameter-passing convention called "pass-by-value" - in short, the formal parameter x in the function definition designates a separate object in memory than the actual parameter val. Writing a new value to x doesn't affect val. In order for foo to modify the actual parameter val, we must pass a pointer to val:
void foo( int *x ) // x == &val
{ // *x == val
*x = *x * 2;
}
int main( void )
{
int val = 2;
printf( "before foo: %d\n", val );
foo( &val );
printf( "after foo: %d\n", val );
return 0;
}
Now we get the output we expect - val is modified by foo. The expression *x refers to the same object that val does. And now we can write something like
foo( &y ); // x == &y, *x == y
foo( &z ); // x == &z, *x == z
This is our first use case - allowing a function to modify its parameters.
There are times during a program's execution where you need to allocate some extra memory. Since this allocation occurs at runtime, there's no way to specify a name for this extra memory the same way you do for a regular variable. IOW, there's no way to write
int x = new_memory();
because variable names don't exist at runtime (they're not preserved in the generated machine code). Again, we must refer to this dynamically allocated memory indirectly through a pointer:
int *p = malloc( sizeof *p ); sizeof *p == sizeof (int)
This allocates enough space for a single int object, and assigns the address of that new space to p. You can allocate blocks of arbitrary size:
int *arr = malloc( sizeof *arr * 100 );
allocates enough space for 100 int objects, and sets arr to point to the first of them.
This is our second use case - tracking dynamically allocated memory.
A quick note on pointer syntax. There are two operators associated with pointer operations. The unary & operator is used to obtain the address of an object, while the unary * dereferences a pointer. Assume we have an int object named x and a pointer to an int named p:
p = &x; // assign the address of x to p
*p = 10; // assign a new value to whatever p points to
In a declaration, the unary * indicates that the thing being declared has pointer type:
int *p; // p has type "pointer to int"
When you initialize a pointer in a declaration like
int *p = &x;
p is not being dereferenced. That is the same as writing
int *p;
p = &x;
The * operator binds to the thing being declared, not to the type specifier. You can write that same declaration as
int* p;
int * p;
int*p;
and it will always be parsed as int (*p);.
For any type T, the following are true:
T *p; // p has type "pointer to T"
T *p[N]; // p has type "array of pointers to T"
T (*p)[N]; // p has type "pointer to array of T"
T *p(); // p has type "function returning pointer to T"
T (*p)(); // p has type "pointer to function returning T"
Complex pointer declarations can get hard to read, since the unary * is a prefix operator and has lower precedence than the [] and () operators. For example:
T *(*(*foo)())[N];
foo is a pointer to a function returning a pointer to an N-element array of pointers to T.
With your code, we're dealing with the first case - we want the readstudent function to modify the contents of an existing instance of struct student. And readstudent does that by calling scanf to read values into each separate member:
scanf("%s", pstu->name);
scanf("%f", &pstu->grade1);
scanf("%f", &pstu->grade2);
Remember that scanf expects its arguments to be pointers - again, we're trying to modify the contents of an object, so we have to pass a pointer to that object as the parameter.
&pstu->grade1 evaluates to the address of the grade1 member of the object that pstu points to. &pstu->grade2 evaluates to the address of the grade2 member of the object that pstu points to.
So what the heck is going on with pstu->name?
Arrays are special in C. Unless it is the operand of the sizeof or unary & operators, or is a string literal used to initialize an array in a character declaration like
char foo[] = "test";
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.
We won't go into the weeds on this, but this was a deliberate design decision by Ritchie when he was first creating the C language, and it does serve a purpose. It also means that arrays lose their "array-ness" under most circumstances, and what you wind up dealing with is actually a pointer to the first element, not the whole array itself. In the case of the scanf call, we're passing the equivalent of &pstu->name[0].
I'll answer a slightly different question first; but related.
"what does void printstudent( TStudent stu ); do?"
The answer is it takes a copy of the of the argument, and then does something with it.
By taking a copy of the data; it's unable to edit what was originally passed in.
Now we get to "what does void readstudent( TStudent *pstu );" do:
which is that it takes a copy of the pointer to some data. This will allow it to edit the data that is being pointed to.
As Jesper states; there are many other uses of *; but these are the basics that you need to know to understand THIS usage
* means different things in different contexts. Remember that C (and C++) is a context sensitive language.
When you declare a variable, like; int* foo; the * means that foo is a "pointer to int".
When you write a statement like printf("%d", *foo); the * means dereference the pointer stored in foo and give me the int value it points to.
When used in a function declaration like void f(int* bar) it means that the function accepts a pointer to an integer as its argument.
It can also mean multiplication, like in int something = baz * 42;
Or it can just be a plain character in a character literal, with no special meaning. Like const char[] foo = "bar*baz*";.
I'm new in programming and learning about pointers in array. I'm a bit confused right now. Have a look at the program below:
#include <stdio.h>
int fun();
int main()
{
int num[3][3]={23,32,478,55,0,56,25,13, 80};
printf("%d\n",*(*(num+0)+1));
fun(num);
printf("%d\n", *(*(num+0)+1));
*(*(num+0)+0)=23;
printf("%d\n",*(*(num+0)));
return 0;
}
int fun(*p) // Compilation error
{
*(p+0)=0;
return 0;
}
This was the program written in my teacher's notes. Here in the main() function, in the printf() function dereference operator is being used two times because num is pointer to array so first time dereference operator will give pointer to int and then second one will give the value at which the pointer is pointing to.
My question is that when I'm passing the array name as argument to the function fun() then why *p is used; why not **p as num is a pointer to array?
Second thing why *(p+0) is used to change the value of zeroth element of the array; why not *(*(p+0)+0)=0 as in the main() function *(*(num+0)+0) is used to change the value of zeroth element?
The whole thing is very confusing for me but I have to understand it anyway. I have searched about this and found that there is a difference between pointer to array and pointer to pointer but I couldn't understand much.
The trick is the array-pointer-decay: When you mention the name of an array, it will decay into a pointer to its first element in almost all contexts. That is num is simply an array of three arrays of three integers (type = int [3][3]).
Lets analyse the expression *(*(num + 1) + 2).
When you mention num in the expression *(num + 1), it decays into a pointer to its first element which is an array of three integers (type = int (*)[3]). On this pointer pointer arithmetic is performed, and the size of whatever the pointer points to is added to the value of the pointer. In this case it is the size of an array of three integers (that's 12 bytes on many machines). After dereferencing the pointer, you are left with a type of int [3].
However, this dereferencing only concerns the type, because right after the dereferencing operation, we see expression *(/*expression of type int[3]*/ + 2), so the inner expression decays back into a pointer to the first array element. This pointer contains the same address as the pointer that results from num + 1, but it has a different type: int*. Consequently, the pointer arithmetic on this pointer advances the pointer by two integers (8 bytes). So the expression *(*(num + 1) + 2) yields the integer element at an offset of 12 + 8 = 20 bytes, which is the sixth integer in the array.
Regarding your question about the call of fun(), that call is actually broken, and only works because your teacher did not include the arguments in the forward declaration of fun(). The code
int fun(int* arg);
int main() {
int num[3][3] = ...;
...
fun(num);
}
would have generated a compile time error due to the wrong pointer type. The code of your teacher "works", because the pointer to the first array in num is the same as the pointer to the first element of the first array in num, i. e. his code is equivalent to
int fun(int* arg);
int main() {
int num[3][3] = ...;
...
//both calls are equivalent
fun(num[0]);
fun(&num[0][0]);
}
which would compile without error.
This example shows a matrix, pointers to the first integers of arrays, and pointer to pointer
#include<stdio.h>
int fun(int (*p)[3]); /* p is pointer to array of 3 ints */
int main()
{
/* matrix */
int num[3][3]={{23,32,478},{55,0,56},{25,13, 80}};
/* three pointers to first integer of array */
int *pnum[3] = {num[0], num[1], num[2]};
/* pointer to pointer */
int **ppnum = pnum;
printf("%d\n", *(*(num+1)+2));
fun(num);
printf("%d\n", *(*(num+1)+2));
pnum[1][2] = 2;
printf("%d\n", *(*(num+1)+2));
ppnum[1][2] = 3;
printf("%d\n", *(*(num+1)+2));
return 0;
}
int fun(int (*p)[3])
{
p[1][2]=1;
return 0;
}
You do not actually need any pointers to print anything here.
Your int num[3][3] is actually an array of three elements, each of which is an array of three integers. Thus num[0][0] = 23, num[1][1] = 0, and so on. Thus you can say printf("%d", num[0][0]) to print the first element of the array.
Pointer to variable:
Pointer is variable which stores the address( of a variable). Every one know that.
Pointer to Array:
An array is a variable which has the starting point(address) of group of same objects.
And the pointer is a variable which stores the starting point(address) of an Array.
For example:
int iArray[3];
iArray is a variable which has an address value of three integers and the memory is allocated statically. And the below syntax is provided in a typical programming languages.
// iArray[0] = *(iArray+0);
// iArray[1] = *(iArray+1);
// iArray[2] = *(iArray+2);
In the above the iArray is a variable through which we can access the three integer variables, using any of the syntax mentioned above.
*(iArray+0); // Here iArray+0 is the address of the first object. and * is to dereference
*(iArray+1); // Here iArray+1 is the address of the second object. and * is to dereference
So simple, what is there to confuse.
The below lines are for your understanding
int iArray1[3];
int iArray2[3][3];
int *ipArray = 0;
ipArray = iArray1; // correct
ipArray = iArray2[0]; // correct
ipArray = iArray2[2]; // correct
int **ippArray = iArray2; // wrong
As per the above last line, compiler will not take it as a valid assignment. So **p is not used.
Pointer arthmatic cannot be applied on double arrays because of the way memory is allocated.
Pointer1 points to 5.
Pointer2 points to 3.
I want to multiply 5*3, but I only have the pointers. How would I do this in C?
Also, what does uint32_t *pointer mean when:
pointer[2] = {1, 2};
I do not know what is so hard for the answerers to understand about this question. It is obviously about dereferencing pointers.
This is how you display the contents of the pointer that it is pointing to:
#include <stdio.h>
int main(void)
{
int num1 = 5;
int num2 = 3;
int* num1_ptr = &num1;
int* num2_ptr - &num2;
int sum = *num1_ptr * *num2_ptr;
printf("%d\n", sum);
return 0;
}
*num1_ptr and *num2_ptr takes your pointers and references what the contents of that memory address.
I can't answer the first half of your question without more information, but uint32_t* pointer is simply a pointer to an unsigned 32-bit integer value (unsigned int and uint32_t are usually equivalent types, depending on your compiler).
If I see a declaration that simply reads uint32_t* pointer without more information I'm going to assume it's a pointer to a single value, and that using the indexing operator [n] on such a pointer is basically overflowing the single-element-sized buffer. However if the pointer is assigned the result from an array or buffer function (e.g. malloc, calloc, etc) then using the indexing operator is fine, however I would prefer to see uint32_t pointer[] used as the declaration as it makes it much easier to determine the developer's intent.
uint32_t *pointer is just a pointer with garbage value unless you point it to something.
pointer[0] = 1;
pointer[1] = 2;
is only valid if you have earlier pointed it to some array of type uint32_t with atleast size two or to a block containing uint32_ts defined using malloc as follows:
uint32_t *pointer;
pointer = (uint32_t*)malloc(sizeof(int*SIZE); //SIZE > 2 here
or
uint32_t array[10];
pointer = & array[0]; // also, pointer = array; would also work.
int main(void)
{
int variableA = 5;
int variableB = 3;
int* ptr1 = &variableA; // Pointer1 points to 5.
int* ptr2 = &variableB; // Pointer2 points to 3.
int answer;
answer = (*ptr1) * (*ptr2); // I want to multiply 5*3, but I only have the pointers.
// Answer gets set to [value stored at ptr1(5)] MultipliedBy [value stored at ptr2(3)]
}
Your misconception is that pointers do not refer to values, such as 5 and 3.
pointers refer to variables, such as variableA and variableB; those variables have values which can be accessed and changed via the pointer.But the pointer only refers to the variable, not directly to the value behind it.
?? fun()
{
int a[3]={3,3,4};
return &a;
}
what could be the compatible return type. Here the pointer is pointing to the array of 3 integers not just the pointer which points to integer array.
Aim is to return a pointer to array of 3 integers.
First, you really should not return the address of a local variable. When the function exits, the array a will get destroyed.
As for your question, the type of &a is int (*)[].
Don't do this.
You are returning a pointer to a local variable. When the function returns, that pointer points to a location that's no longer valid, so this exercise is pointless.
The return type would have been int (*)[3] though, but when you use that as a return type of a function, the prototype would be int (*fun(void))[3] (ugh, eew)
However
If a was static, you could do
int (*fun(void))[3]
{
static int a[3]={3,3,4};
return &a;
}
It's more common to return a pointer to the first element in an array - though you'll have to "know" in the caller that you can access 3 and only 3 elements of that pointer.
int *fun(void)
{
static int a[3]={3,3,4};
return &a[0]; // or just return a;
}
Since a is static in these cases, you'll have to worry about reentrancy
2 more common ways of achieving the same:
Pass in the array through the parameters and allocate it in the caller:
void fun(int *a)
{
a[0] = 3;
a[1] = 3;
a[2] = 4;
}
Call it like:
int a[3];
fun(a);
Dynamically allocate the memory:
int *fun(void)
{
int *a = malloc(3*sizeof *a);
if(a) {
a[0] = 3;
a[1] = 3;
a[2] = 4;
}
return a;
}
Call it like:
int *a;
a = fun();
if(a) {
///use a
free(a); // remember to free it when done
} else {
//out of memory
}
The return type would not be an int* or int** as others have suggested. The return type would be a pointer to an array. For example:
// we'll use a typedef so we can keep our sanity:
typedef int(*int3arrayptr)[3];
int3arrayptr fun()
{
int a[3]={3,3,4};
return &a;
}
While you can return a pointer to a local variable, you cannot use such a pointer after the function returns, so you cannot use the return value of fun().
The type would be int**
But your code is wrong because your table is on the stack.
Returning the pointer of an element in the stack make the reference pointing in nowhere when returning from the function.
Don't make the mistake. As soon as fun() loses scope, so does all it's local variables.
The address of a local variable cannot be returned from a function. Local variables are placed in the stack
a is a local variable. Don't return a pointer to it.
Back to the point. This is how you define a pointer-to-array-of-size-3 type in C:
int a[3] = { 1, 2, 3 };
typedef int (*p_arr_3)[3];
p_arr_3 fun() { return &a; }
Everyone else has already told you why you shouldn't do this as it is written, but here are the types you are interested in.
Given a declaration int a[3], the type of the expression &a is int (*)[3] (not int **), or "pointer to 3-element array of int", such as
void f()
{
int a[3] = {1,2,3};
int (*aptr)[3] = &a;
...
}
and the signature for a function returning that type would be int (*fun())[3] {...}.
One other option nos didn't show is this:
int (*fun())[3]
{
int (*aptr)[3] = malloc(sizeof *aptr);
if (aptr)
{
(*aptr)[0] = 1; // array pointer must be deferenced before applying
(*aptr)[1] = 2; // the subscript.
(*aptr)[2] = 3;
}
return aptr;
}
although this isn't terribly useful; you don't normally see allocations of single, fixed-size arrays like this. Somewhat more useful is allocating an array of those arrays:
int (*fun(size_t count))[3]
{
int (*aptr)[3] = malloc(sizeof *aptr * count);
if (aptr)
{
size_t i;
for (i = 0; i < count; i++)
{
aptr[i][0] = 1; // aptr[i] implicitly dereferences aptr, so
aptr[i][1] = 2; // there's no need for an explicit dereference
aptr[i][2] = 3; // here.
}
}
return aptr;
}
Even so, if somebody needs to allocate a fixed-size array type, they usually hide it behind a typedef:
typedef int fixedSizeRecord[SOME_SIZE];
...
fixedSizeRecord *fun(size_t count)
{
fixedSizeRecord *aptr = malloc(sizeof *aptr * count);
if (aptr)
{
// initialize contents as necessary
for (size_t i = 0; i < count; i++)
for (j = 0; j < sizeof *aptr / sizeof *aptr[0]; j++)
aptr[i][j] = ...;
}
return aptr;
}
Abstraction is a good thing.
I've put up several iterations of this table before; you might find it handy.
Declaration: T a[N];
Expression Type Decays To Value
---------- ---- --------- -----
a T [N] T * Address of first element in a
&a T (*)[N] n/a Address of a (same value as above,
but different type)
*a T n/a Same as a[0]
a[i] T n/a Value at index i
&a[i] T * n/a Address of value at index i
sizeof a size_t Total number of bytes in a
(N * sizeof T)
sizeof a /
sizeof *a size_t n/a Number of elements in a (N)
Declaration: T a[N][M];
Expression Type Decays To Value
---------- ---- --------- -----
a T [N][M] T (*)[M] Address of first element in a[0]
&a T (*)[N][M] n/a Address of a (same value as above,
but different type)
*a T [M] T * Same as a[0]
a[i] T [M] T * Address of first element in array
at index i
&a[i] T (*)[M] n/a Address of array at index i (same
value as above, but different
type)
*a[i] T n/a Same as a[i][0]
a[i][j] T n/a Value at a[i][j]
&a[i][j] T * n/a Address of value at index i,j
sizeof a size_t n/a Total number of bytes in a
(N * M * sizeof T)
sizeof a /
sizeof *a size_t n/a Number of subarrays in a (N)
sizeof a[i] size_t n/a Total number of bytes in a[i]
(M * sizeof T)
sizeof a[i] /
sizeof *a[i] size_t n/a Number of elements in a[i] (M)
If you want to return a pointer to an array, don't return the address of local variables. What you are returning here would be int**. What you want to do is allocate a new array of int, and return int*. What you want is probably something like:
int* fun()
{
int* a = malloc(sizeof(int) * 3);
a[0] = 3;
a[1] = 3;
a[2] = 4;
return a;
}
You then need to make sure to free the allocated array later.
Your function would have a return type of int * and you would call it like this:
int *array=fun();
printf("%d\n",array[0]); //print the first value in the array
Although! Keep in mind that this function is returning a reference to a locally created variable. There is no guarantee that the value in memory will be the same between inside and after the function call. You probably want to do something more like this:
int *more_fun(){
int *a=malloc(sizeof(int)*3);
a[0]=3;
a[1]=3;
a[2]=4;
return a;
}
Call it like:
int *array=more_fun();
printf("%d\n",array[0]); //print the first value in the array
But when you're done, make sure to free(array) so you don't leak any memory.
If you were to return a, the return type would be int *. I'm not entirely sure what &a means in this case, and my handy reference tells me that the only operation that can be applied to an array is sizeof, and I don't have the Standard handy. It may be flagged as illegal, or it may just return the value of a. The only thing a denotes is the array, and the only thing like a pointer to an array is a pointer to its first element. There is no address of the address.
In C, it's hard to pass around an array, since arrays decay to pointers on the slightest provocation. If you need to pass around an actual array, it's easiest to embed it in a struct. A struct containing int a[3]; can be passed around as a regular value.
I assume that you were just giving an example, because you're returning a reference to a local variable leads to all sorts of bad things. In most implementations, that memory will be used for other things with the next function call, which means that changing a value will stomp on who-knows-what, and referencing one will get who-knows-what.
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;
}