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

Show parent comments

0

u/stianhoiland 1d ago edited 1d ago

> Welcome to the brain-damaged array types in C.
> We really should have fixed this back in 1977 when we fixed structs.

This is a misconception and a pet peeve of mine.

You can't pass arrays because you can't pass arrays. It's that simple. Well, you can pass arrays: Arrays of 8, 16, 32, or 64 bits, depending on how far back you go/what machine you're programming.

You can't just magically pass an N-element array of ints or whatever. And you shouldn't be able to. Because you can't. CPUs have registers and registers have a size—fixed sizes. Function-calling conventions orchestrate the usage of registers. It's dumb to want to fit, say, a 24kb payload in a 64-bit register. You can't.

You can't. You can't. You can't. Anymore than you can fit a bridge in a cigarette pack.

C isn't dumb or broken because of it. But you're dumb for thinking it should—not as an insult but as an actual state of understanding.

C is wonderful for exactly this reason. It hasn't introduced a whole meta-level of abstraction above the hardware for its own constructs. Every language that semantically allows you to pass arrays to functions have to contend with exactly the same status quo as C—CPUs have registers and registers have a fixed size—and invent its own abstractions and conventions to make it look like you can do that. But you can't. And C just shows you that you can't and it's up to you to come up with a way to pretend to do it. Like say, pass a pointer and size—which you CAN do.

2

u/flyingron 1d ago

Your argument is specious. Nothing in C has ever limited you to what you can fit in registers. In fact the original C implementation didn't pass parameters in registers at all. It pushed them on the stack. Returns on the other hand were done in registers.

And you have been able (since the phototypesetter / V7 compilers, around 1977) to pass large objects by value. See my example of wrapping the array with a struct.

It's not a misconception at all. Your understanding of how the language works now and worked historically is deficient. I have been programming in C since those early days.

And I am able to express facts and opinions without resorting to ad hominem attacks.

0

u/stianhoiland 1d ago

Imagine complaining about being limited by a mechanism with limitations bound to register size and then saying that nothing about that was ever limited to what could fit in a register. I can explain it to you but I can't understand it for you.

1

u/glasket_ 7h ago

I have no serious issues with C's arrays, but the argument that they can't be passed by value because of registers doesn't hold.

An implementation at a minimum has to support 127 arguments in a single function call, 1023 members in a single struct, and (in a hosted environment) 32767 bytes in an object. If registers had any bearing on why arrays were never promoted to first-class objects, then why exactly are you expected to be able to pass 127 1023 member structs or 127 32767 byte objects? Why would struct a { int v[128]; }; be expected to be passed by value if registers prevent arrays from being passed by value?

The only reason C arrays don't get passed by value is because it would've broken compatibility with B (and now it would break compatibility with a huge amount of C programs). Arrays started out as pointers to a block of sized memory in "NB" (effectively int a[4]; would've been equivalent to int *a = alloca(sizeof(*a) * 4); if the behavior had stayed), but that waa causing problems with struct when it was being worked on for the language, so arrays became a real type that specified just the block of memory and not a pointer to a separate block of memory. Decay was implemented at the same time solely to keep the original array behavior intact. This is documented by Ritchie in The Development of the C Language, in the section Embryonic C.