James Liu James Liu - 1 month ago 11
C Question

How are my arrays modified when C passes by value?

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;
}

Answer Source

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.