Help with Functions and Arrays in C

Help with Functions and Arrays in C
0.0 0

#1

Hi, I’m taking the CS50 course and am having some trouble understanding how arrays and functions work in C. I’m on pset 3 where I have to create a game called “The Game of Fifteen.”

Something that I’ve stumbled upon is that if you call a function that changes the array, you don’t have to return that array to make changes to the outer scope. Why is that?

For example, if I have the

void change (int x[]);

int main (void){
    int a[4]={1,2,3,4};
    for (int i=0; i<4;i++){
        printf("%i\n",a[i]); //prints 1 2 3 4 
    }
    change(a);
    for (int i=0; i<4;i++){
        printf("%i\n",a[i]); //prints 1 2 10 4
    }
}

void change (int x[])
{
    x[2]= 10;
}

The second print statement in main prints 1 2 10 4, even though I did not return the array in the change function. How does C know that x[2] is the same as a[2]?

If I were to look at a similar situation but instead of an array, we look at a single integer, I would have to return and reassign the integer to print what the change function has done from main.

int change (int x);

int main (void){
    int a=2;
    printf("%i\n", a);
    a=change(a);
    printf("%i\n", a);
}

int change (int x)
{
    return x=7;
}

Is it inherent in data structures that we do not have to return them? It looks like C keeps track of where these structures are being changed, even if they have a different name.

Thanks!


#2

@_sleepyowl

Something that I’ve stumbled upon is that if you call a function that changes the array, you don’t have to return that array to make changes to the outer scope. Why is that?

An array in C is just a particular patch of memory. (Which is why C is considered dangerous. It’s easy to go over the edge and stomp on some unrelated piece of memory with potentially bad consequences.)

void change (int x[]);

So when you pass an array into a function like this you are essentially passing a pointer to the address of that memory. Thus all the changes you make in the function directly affect that memory.

How does C know that x[2] is the same as a[2]?

Because a represents the contents of a memory address. Let’s say 10000. a[2] is that base memory address plus an offset of 2 times the size of the datatype. For an int on a modern computer that’s probably 8 bytes so a[2] is the contents of memory location 10000 + (2 * 8) or 10016. You’ve told C x = a. so x also = the contents of 10000 and therefore x[2] also = the contents of 10016. (This is a very simplified explanation. In real life there are other factors to consider such as alignment etc.)

int change (int x);

Now here the c compiler makes a copy of the contents of x and passes it into the function. This copy has a different memory address than the original. So changes made to it in the function will not be reflected in the original. If you had written…

    int change (int& x);

…Then you would get the same effect as with the array.

To learn about this, what you want to read about is “pass by value versus pass by reference.”

Btw, modern languages like JavaScript or Python abstract away all this nonsense because it is so easy to get wrong. But when you need it, it is very powerful and efficient.


#3

Basically, in C, function parameters that are arrays are passed by reference, by default.

Passing by reference means that any changes made to a variable within a function are reflected in the variable that was passed in—i.e., the argument variable (in this case your array) is modified directly within that function. Unlike in a language like JavaScript, the variable within the function is NOT some sort of copy and is passed in directly.

I’m not familiar with the CS50 course as I haven’t taken it, but hopefully it’s covered pointers already, in which case you can consider the parameter a pointer (to an array). If the course hasn’t covered pointers, you can think of a pointer to be a reference to a location in system memory - as in, to put it in as plain English as possible, a location in your computer’s memory (i.e., the RAM to be specific) that stores a value. On a modern 64-bit system, individual memory locations can be up to 64-bit, but are more commonly 32-bit (which in C are designated by the ‘int’ type).

Basically, if there’s one thing you should take away from C, it’s that every variable not only takes up a certain amount of space in memory, but you can also refer to it in memory by its memory location (the proper term is its “memory address”). Referring to a variable by its memory location is done through pointers, which can be considered another form of variables, except instead of holding a value, they hold a memory address.


#4

Just wanted to point out for clarification that the only things JS passes in by value are strings and numbers. Objects, Arrays, Functions, etc. are all by reference.


#5

Thank you! I remember reading the “pass by value versus pass by reference” somewhere. It may have been in the part of the YDKJS series, which I never really got far on, or elsewhere. But this is making a lot more sense now.


#6

Thanks for the clarification on pointers! I don’t believe that the CS50 course has gone in depth about it, or if it has it was definitely something that I missed. I do tend to see references to pointers in several other resources but never paid much attention. This helps a lot!


#7

Haaaa just got to the next lecture, now they’re talking about pointers and memory allocation :slight_smile:


#8

Hi!

I would refer you to https://study.cs50.net/ . Helped me out a lot with the class.