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.
Related
Please read the comments in the program below :
#include<stdio.h>
void test(char c[])
{
c=c+2; //why does this work ?
c--;
printf("%c",*c);
}
int main()
{
char ch[5]={'p','o','u','r'};
//ch = ch+2; //this is definitely not allowed on array names as they are not pointers
test(ch);
return 0;
}
OUTPUT
o
You should keep in mind that the name of the array "decays" to a pointer to its first element. This means that test(ch); is equivalent to test(&ch[0]);.
Also, void test(char c[]) is nothing but void test(char* c), a pointer to a character. Pointers can be incremented or decremented which is why c = c + 2 and c-- compiles just fine.
Array designators are immutable lvalues. That is you may not change an array designator such a way that ir would define another array.
Consider array designators as named memory extents.
As for your example then this function declaration
void test(char c[]);
is adjusted by the compiler the following way
void test(char *c);
that is a parameter having an array type is adjusted by the compiler to pointer. Thus for example these function declarations
void test(char c[100]);
void test(char c[10]);
void test(char c[1]);
void test(char c[]);
are equivalent and declare this one function
void test(char *c);
You nay include all these declarations in your program though they will be redundant.
For example
#include <stdio.h>
void test(char c[100]);
void test(char c[10]);
void test(char c[1]);
void test(char c[]);
void test( char *c)
{
c=c+2;
c--;
printf("%c",*c);
}
int main( void )
{
char ch[5]={'p','o','u','r'};
test(ch);
}
To make it evident consider the following program
#include <stdio.h>
void test( char c[] )
{
printf( "sizeof( c ) = %zu\n", sizeof( c ) );
}
int main( void )
{
char ch[5]={'p','o','u','r'};
test( ch );
printf( "sizeof( ch ) = %zu\n", sizeof( ch ) );
}
Its output is
sizeof( c ) = 8
sizeof( ch ) = 5
That is within the function sizeof( c ) is equal to the size of a pointer (in used system it is equal to 8). While in main sizeof( ch ) is the size of the array.
When you pass an array to such a function then the array designator is implicitly converted to pointer to its first element. So these calls
test( ch );
test( &ch[0] );
are equivalent.
This means that within the function you deal with a pointer and you can change the value of the pointer using the pointer arithmetic.
When an array is passed as function argument (among other cases), it decays to a pointer to the first element, and the function parameter which receives it is local to the function scope.
Quoting C11, chapter §6.3.2.1
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. [...]
So, in your case, inside void test(char c[]) function call, c is just another pointer, which points to the first element of the array. Normal pointer arithmetic can be performed on that pointer.
In other words,
void test(char c[]) { //....
is same as
void test(char *c) { //....
So, you case is something similar to
int main(void) //correcting the definition
{
char ch[5]={'p','o','u','r'};
//ch = ch+2; //this is definitely not allowed on array names as they are not pointers
char *c = &ch[0]; // this is what happens when you pass the array as function argument.
c = c + 2; // see, this is possible.
test(ch);
return 0;
}
In declarations of function parameters, an array declaration is automatically adjusted to be a pointer declaration, per C 2018 6.7.6.3 7:
A declaration of a parameter as “array of type” shall be adjusted to “qualified pointer to type”,…
Thus void test(char c[]) is effectively void test(char *c).
In main, ch is an array, because it was declared with char ch[5]…, which is a normal declaration that is not adjusted. In test, c is a pointer.
When main calls test with test(ch), the argument ch is an expression. In an expression, an array is automatically converted to a pointer in most cases because C 2018 6.3.2 3 says:
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…
Thus, when an array is passed to a function with a parameter declared as an array, the array is converted to a pointer and is passed for a parameter that was adjusted to be a pointer.
Note that only an outer array is adjusted. If the function parameter declaration is int x[3][4], it is adjusted to be int (*x)[4], a pointer to an array of 4 int. Only the array that is the parameter (the array of 3 arrays of 4 int above) is adjusted; other types within its composition are not adjusted.
Aside
The C standard is not entirely clear about the effects of the adjustment. Using Apple LLVM 10.0.1 with clang-1001.0.46.4, the following program prints “Hello, world.”:
#include <stdio.h>
static void foo(int a[printf("Hello, world.\n")]) {}
int main(void) { foo(0); }
This shows the array declaration was not completely adjusted to be a pointer declaration, as the expression specifying the array size was retained but would not be present in a pointer declaration.
I am having trouble passing a pointer array to a function. I will post a simple example that still doesn't work for me. Could you please tell me what I am doing wrong?
#include <stdio.h>
#include <stdlib.h>
int transformare(int *v[1])
{
*v[1] = 10;
return 0;
}
int main()
{
int v[1];
printf("n = ");
scanf("%d", &v[1]);
transformare(&v);
printf("%d", v[1]);
return 0;
}
You have two problems:
Array indexes are zero-based. That is, an array of N elements have indexes from 0 to N - 1 (inclusive)
The declaration int *v[1] declares v as an array of one pointer to int, not as a pointer to an array of one int. That would be int (*v)[1]. Which is also the type of &v from the main function.
The solution to the second problem (using the correct type) then leads to a third problem, as it means that *v[0] is incorrect due to operator precedence. You need to use parentheses here too, as in (*v)[0].
However the second (and the following third) problem is moot, since you don't need to pass arrays "by reference".
Arrays naturally decays to pointers to their first element. When using plain v when a pointer to int is expected, the compiler will automatically translate it as &v[0].
That means you could declare the function to simply take an int * as argument, and simply pass plain v as the argument.
First, please note that indizes are 0-based in C, i.e. the first (and - in your case only) element is v[0].
Concerning passing it, just define the parameter as pointer to int, i.e. int*. A variable of type int[1] will decay to a pointer to int when passed to a function (so there is no need to write transformare(&v), its transformare(v).
int transformare(int *v)
{
v[0] = 10;
return 0;
}
int main()
{
int v[1];
printf("n = ");
scanf("%d", &v[0]);
transformare(v);
printf("%d", v[0]);
return 0;
}
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,...
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.
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;
}