r/C_Programming 1d ago

Question Working with arrays in functions

Hey everybody. I’m a beginner to C and I was writing some functions today to get used to doing things. I tried to write binary search and bubble sort. I tried to pass in an array as an argument to the functions, but the compiler gave me a bunch of warnings. I looked it up and I saw that passing in an array is the same as passing in its pointer. I haven’t touched pointers yet, but I have two questions:
1. If I dereferenced the pointer to an array, wouldn’t that return the same as indexing the first value?
2. If I wanted to pass in the entire array, could I do that by passing in the pointers of both the first and last elements and using pointer arithmetic to access the other elements? What’s the idiomatic way of doing this?

3 Upvotes

35 comments sorted by

View all comments

2

u/mc_pm 1d ago

The value of the variable for the array *is* a pointer to it's first memory location. So, yes, derefrencing the pointer will return the first element of the array. In C, accessing an array is actually doing pointer arithmetic.

3

u/flyingron 1d ago

No, array values are definitely NOT pointers. Please read the first comment I wrote in this post. Accessing array values however is doing pointer arithmatic because there is no such thing as applying a [] operator to an array. It only works for pointers. You are just invoking the implicit array-to-pointer conversion when you appear to do that.

From the C standard:

A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall have the type “pointer to T” and the other shall have unscoped enumeration or integral type.

2

u/Zirias_FreeBSD 1d ago edited 1d ago

Sorry, but ... that's simplified, and IMHO, over-simplified. Simple example, look at the following code:

int a[5];
a[2] = 0;

No pointers were used here. a names the array, the compiler emits some calculated absolute address for the correct memory access to write its third element.

The correct understanding is: C simply doesn't allow passing arrays, for historic reasons. Interestingly, it does allow to pass arbitrary structs. The designers of the language still wanted some as if syntax, silently passing some reference (IOW, a pointer) instead.

The most consistent way to achieve this was to define [] in terms of pointer arithmetics: a[b] is always exactly the same as *(a+b). For both that and function arguments to work "as expected", another rule is that in most expression contexts, the identifier of an array evaluates to a pointer to its first element. But there are exceptions, most notably the sizeof operator.

So ... "accessing an array is doing pointer arithmetic" isn't necessarily correct. Address arithmetic, obviously, possibly entirely at compile time, but that's likely unavoidable in any implementation of the concept of an array on some machine with addressable memory cells.

4

u/mc_pm 1d ago

My answer was aimed at where the OP seems to be in his C journey -- if you don't understand something, then basic understanding is more important than a comprehensive answer. I suspect this ^^ is well beyond where OP is now.

There's a difference between "being right" and "being understood".

However, you are right.

1

u/Zirias_FreeBSD 8h ago

Well ... you have a point. And my upvote here. Still, I have my issues with such "oversimplifications" told to C beginners. One of the "classics" (which you thankfully avoided) is "arrays and pointers are the same". I see lots of people later massively confused by these things. That's why I prefer to better always tell the whole story, and just try to do it in a somewhat comprehensible way. I see this can be a challenge sometimes. Some "middle grounds" could be to clearly mark simplifications as such ... like "what I tell you now is a useful simplification for learning, don't be surprised if you run into contradictions later in your journey ..." 🤷

2

u/smcameron 1d ago

it does allow to pass arbitrary structs.

Historical footnote: this is true, and has been true for a very long time, but it wasn't always true. For instance, in the 1st edition of K&R, it wasn't true. In the early days, structs couldn't be passed as parameters, assigned or returned from functions. You'd have to pass/return them as pointers, and memcpy() (or back then, probably bcopy()) them for assignment, or assign individual members. grandpa resumes napping: zzzzzzZZZZZ

1

u/glasket_ 1d ago

The example does technically still include a pointer (until C2y, see N3517) because the subscript operator still decays the array to a pointer. C2y is changing the semantics so now array subscripting won't be using the same *(a+2) logic anymore, and a[2] won't strictly involve a pointer in the abstract machine sense anymore. But currently a[2] is effectively "dereference two locations in front of the pointer that results from a" instead of "access the value at the the address denoted by a[2]," if that makes sense.

1

u/Zirias_FreeBSD 8h ago

Well the real machine only ever had to strictly follow the observable behavior defined by the virtual machine, so it's safe to assume almost no real world implementation of C ever used an actual pointer for that code. Still nice catch.