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;
}
Related
I made a simple program in C to check if two words are anagrams. My question is that if I'm passing word_one and word_two as parameters, doesn't that mean that I'm not modifying the original arrays? I would think that I'm effectively working on a copy of these which are not returned.
That means I shouldn't be able to compare them with my equal_array function.
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#define MAXLENGTH ((int) (sizeof(letters) / sizeof(letters[0])))
void read_word(int counts[26]);
bool equal_array(int counts[26], int counts2[26]);
int main(void){
int word_one[26] = { 0 };
int word_two[26] = { 0 };
printf("Enter first word: ");
read_word(word_one);
printf("Enter second word: ");
read_word(word_two);
if (equal_array(word_one, word_two))
printf("These words are anagrams!");
else
printf("These words not are anagrams!");
return 0;
}
void read_word(int counts[26]){
char ch;
while ((ch = getchar()) != '\n'){
ch = toupper(ch);
if (ch >= 'A' && ch <= 'Z'){
counts[(ch - 'A')]++;
}
}
}
bool equal_array(int counts1[26], int counts2[26]){
int i;
bool equal = true;
for (i = 0; i < 26; i++) {
if (counts1[i] != counts2[i]) {
equal = false;
break;
}
}
return equal;
}
C indeed always passes by value, but when arrays are passed to functions they always decay to pointers, even when you specify the length in the parameter declaration. What happens is that your declaration of
void read_word(int counts[26])
is equivalent to
void read_word(int * counts)
When you pass word_one and word_two to your functions, the value they recieve is the address of the first element of the array. These still point to the original arrays and therefore, when you modify them in the function, the result is also visible in the original array.
ADDIT
Interesting, but little-known side note: in C99 and beyond you can declare your functions with the length preceded by static, as follows:
void read_word(int counts[static 26])
This doesn't change the fact that the function receives a copy of the address and not the whole array, but it does allow the compiler to optimize and detect potential errors. In the case of the read_word above, the compiler can warn if you pass a NULL-pointer to the function, or an array with less than 26 elements. More can be read here.
Except when it is the operand of the sizeof or unary & operator, or is a string literal used to initialize a character 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
read_word(word_one);
The expression word_one is converted from type "26-element array of int" to "pointer to int", so what actually gets passed to read_word is the address of the first element of word_one.
In the context of a function parameter declaration, T a[N] and T a[] are both interpreted as T *a - a is declared as a pointer to T, not an array of T. Thus, the prototype
void read_word(int counts[26])
is interpreted as
void read_word(int *counts)
Thus, read_word does indeed modify the contents of word_one and word_two.
You'll want to pass the size of the array as a separate parameter:
read_word( word_one, sizeof word_one );
...
void read_word( int *counts, size_t size )
{
...
}
since you won't know how big the target array is from the pointer alone.
Arrays are reference types in C. If a function takes an array, it will be passed a pointer, and any changes you make to it will also affect the original array.
C passes only the pointer. Only structs and simple types are passed by the value.
I wrote a simple recursive function for binary search that takes three arguments: an array of integers, the length of the array and a value to find. The idea is that at every recursive call it either halves the length and keeps the array[0] in place or moves the starting index to the middle (third line from the bottom in my sample). That is until the value is found or length is 0.
Then I saw this disccussion: How do you shift the starting index of an array in C?
It is said here that an array name is a constant and cannot be reassigned in C. So my question is why this code works?
int rsearch( int needle, int haystack[], int size ) {
if (size == 0) {
printf("%i not found\n", needle);
return 0;
}
int mid = size / 2;
if (haystack[mid] == needle) {
printf( "found %i in the array\n", needle );
return 1;
} else if (haystack[mid] > needle) {
return rsearch( needle, haystack, size / 2 );
} else {
haystack = &haystack[mid + 1];
return rsearch( needle, haystack, (size - 1) / 2 );
}
I'm just studying, and my knowledge of pointers is very limited. And there's no practical application here. Just curious.
P.S.
The other question is what happens to the memory allocated to the original array when it's reduced this way? Is it made available again or is it a memory leak?
Arrays when used as function arguments actually mean a pointer to an array, but not the array as value. So the following function signatures are equivalent: void test(int xptr[10]), void test(int xptr[]), and void test(int *xptr).
At the point where an array is defined, however, you can only initialise it's value, but you cannot assign any other value later on.
When you pass an array, let's say int x[10] to a function by just using x as parameter, like in test(x), then array x automatically decays to a pointer to the first element of x.
See the following code showing the difference:
#include <stdio.h>
void test(int xptr[10]) {
printf("value of xptr[0]: %d\n", xptr[0]); // -> 0
xptr = &xptr[2]; // OK; xptr will point to element 2
printf("value of xptr[0]: %d\n", xptr[0]); // -> 2
}
int main(){
int x[10] = { 0,1,2,3,4,5,6,7,8,9 };
// x = &x[2]; // Error: Array type 'int [10]' is not assignable
// but:
test(x); // OK; and is eqivalent to...
test (&x[0]); // OK;
return 0;
}
As a function argument, this:
int haystack[]
Is equivalent to:
int *haystack
This is mainly because an array decays to a pointer to the first element when passed to a function.
So what you have is not an array but a pointer. Unlike an array, a pointer is a modifiable lvalue, so it is allowed to assign to it.
According to the C Standard (6.7.6.3 Function declarators (including prototypes))
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted
to ‘‘qualified pointer to type’’...
and (6.3.2.1 Lvalues, arrays, and function designators)
3 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 and is not an lvalue. If the array object
has register storage class, the behavior is undefined.
Thus in this function declaration
int rsearch( int needle, int haystack[], int size );
the parameter int haystack[] is adjusted to int *haystack. So these function declarations
int rsearch( int needle, int haystack[100], int size );
int rsearch( int needle, int haystack[10], int size );
int rsearch( int needle, int haystack[], int size );
int rsearch( int needle, int *haystack, int size );
declare the same one function. You may include all these declarations in your program because a function declaration may appear more than one time. However the function shall be defined only one time (if it is not an inline function).
Accordingly the array passed to the function as argument is implicitly converted to pointer to its first element.
Take into account that it would be better to declare the function like
int rsearch( int needle, const int *haystack, int size );
^^^^^
In this case the function can be used also with constant arrays.
It is said here that an array name is a constant and cannot be
reassigned in C.
It would be correctly to say that array is not a modifiable lvalue.
From the C Standard (6.5.16 Assignment operators)
2 An assignment operator shall have a modifiable lvalue as its left
operand.
and (6.3.2.1 Lvalues, arrays, and function designators)
...A modifiable lvalue is an lvalue that does not have array type,...
KEEP IN MIND I WROTE THIS CODE IN HERE TO SIMPLIFY MY QUESTION, PLEASE IGNORE MINOR MISTAKES IF THERE ARE ANY, MY PROBLEM FOCUSES ON MANIPULATING AN ARRAY OUTSIDE OF A FUNCTION BY USING IT'S POINTER.
I create a static array like this
char *array[size1][size2];
For the purposes of my example size1 = 3 and size2 = 6.
Then I use a function to pass the pointer of the array, and allocate strings to it.
int counter = 0;
void somefunction(char *a, char *b, int size1){
while(counter<size1){
//do some stuff to a
strcpy(b+counter, a);
counter++;
printf("Adding %s to pos %i RESULT: %s\n",a,counter,b+counter);
}
}
This works nicely and the output is correct (when outputting array b in the function), but it does not actually effect the array[] outside of the function. If I use
somefunction(a,array,size1);
The output will be correct, but the actual array outside of the function (array[]) will output gibberish random memory.
I output it like this:
for(int i=0;i<size1;i++){
printf("%s\n",array[i]);
}
So what am i doing wrong here? I thought the array when passed to a function decays into a pointer to the first element (and therefore that array), but that doesn't seem to be the case. What am I doing wrong? How do I manipulate the array outside of the function by passing it's pointer?
Thanks!
From the comments:
What Im trying to do is I calculate the length of the string (size2). So all of the strings contained will be of length 3 in this case, "ABC" for example. Size 1 is simply the amount of strings of size 3 that I need to store and iterate through. So size1=6 size2=3 means I want to have 6 strings accesable by ordered array, all of which are 3 chars in length. Once I compute size1 and size2 (I do this before creating the array) they do indeed stay constant.
In that case, you want to declare array as a 2D array of char:
char array[size1][size2]; // no *
Note that to store a string of length N, you need an N+1-element array to account for the 0 terminator. So if you're storing strings like "ABC" ({'A','B','C',0}), then size2 needs to be 4, not 3.
When you pass it to somefunction, the type of the expression array "decays" to "pointer to size2-element array of char" (char (*)[size2])1. Based on your description, it sounds like you declare array as a variable-length array (i.e., size1 and size2 are not known until runtime). If that's the case, then your function definition needs to look like
/**
* size2 must be declared in the argument list before char (*b)[size2]
* b may also be declared as char b[][size2]; it means the same thing
*/
void somefunction( char *a, size_t size2, char (*b)[size2], size_t size )
{
...
strcpy( b[counter], a );
...
}
and should be called as
somefunction( a, size2, array, size1 );
Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character 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. In your case, N is size1 and T is "size2-element array of char".
I believe you just need this:
char *array[SIZE];
Some function then looks like this:
int counter = 0;
void somefunction(char *a, char **b){
while(counter < SIZE){
//do some stuff to a
*(b+counter) = calloc(sizeof(char), strlen(a)+1);
strcpy(*(b+counter), a);
counter++;
printf("Adding %s to pos %i RESULT: %s\n",a,counter,b+counter);
}
}
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.
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;
}