NireBryce

reality is the battlefield

the first line goes in Cohost embeds

๐Ÿฅ I am not embroiled in any legal battle
๐Ÿฆ other than battles that are legal ๐ŸŽฎ

I speak to the universe and it speaks back, in it's own way.

mastodon

email: contact at breadthcharge dot net

I live on the northeast coast of the US.

'non-functional programmer'. 'far left'.

conceptual midwife.

https://cohost.org/NireBryce/post/4929459-here-s-my-five-minut

If you can see the "show contact info" dropdown below, I follow you. If you want me to, ask and I'll think about it.


trainsfemme
@trainsfemme

how the fuck do i do this. it is literally. impossible. like not 'oh its possible but really hard' its impossible to fucking do this. I've looked through like 50k stack overflow posts and they all say you cant do this except with some weird combination of pointers and malloc. how do i do this. i can't just use void cuz according to my class im not meant to.


trainsfemme
@trainsfemme

hey did you guys know it's also impossible to find the length of an array that you passed in to a function? even using the sizeof(arr)/sizeof(arr[0]) method? this is because even the simplest things don't work. this is because dennis ritchie personally hates me


trainsfemme
@trainsfemme

c is like if you took a normal programming language and took it behind the shed and broke its kneecaps and left it unable to walk


You must log in to comment.

in reply to @trainsfemme's post:

the two ways to do this is by either creating an array on the heap (using malloc()), or (imo the better method (in most circumstances)) giving the find_divisor function a pointer to an output array, which it will fill in the values for

something like this:

void find_divisor(int* inputArray, int** outputArray)
{
     // (do stuff with inputArray[i] to solve for divisor and dividend)
     *outputArray[0] = divisor;
     *outputArray[1] = dividend;
}

int main(int argc, char** argv)
{
     int data[] = {1, 2, 3, 4, 5, 5, 6};
     int result[2];
     find_divisor(data, &result);
     // (returned array is stored in result[])
     // ...
}

a lot of the reasons for the weird quirks in C are due to how CPUs actually work x_x i've managed to internalize all the reasonings

("why can't you just return an array?" because it either has to be allocated on the stack or the heap, but the local stack is cleared when your function returns, so it must be stored on the caller's stack, or in the heap, but it has to be later free()-ed if allocated in the heap)

edit: if your class is Requiring the return type to be non-void then i'm guessing they Expect you to allocate it using malloc() but that's kinda dumb :( bleh

wait you might be able to have the function return a struct? i never looked into that because i always just did this indirect access method, for Object Ownership reasons, plus returning a struct seems weird to me,,,

Either way, it would need to be heap-allocated because the local stack gets cleaned up when the function returns. So you'd still have to malloc space for it.

It might seem to work if you allocate it on the stack, but that memory could be reused at any time.

usually but not always, for example if you have a struct on the stack of the main function (or whatever root function), you can always pass a struct pointer to functions and it won't get cleared away after they return, since the main function holds onto it

it Would clear if the main function returns, but that only happens when the program finishes running, so it's not much of a concern ๐Ÿ‘

many libraries already do this, by instructing the programmer to allocate a state struct and re-use it for all the function calls, which can sit on the main function's stack, or the heap (and keeping it on the stack (if you can) is simpler/safer)

i have no idea how Returning A Struct works in this model though so i don't really do it (i would Hope that the caller makes space on the stack for the return value to be stored into? below the return address so it stays in memory even after the callee returns)

i obsess over C too much as you can probably tell D:

Oh, well, yeah, you could pass a pointer to a stack-allocated struct, but at that point why not just pass the pointer to your array?

(I too obsess, but mostly over C++ ๐Ÿ˜)

(I'm talking about the System V x86_64 ABI, I don't know about other platforms) Returning big structs is done by the adding an implicit outparam, the caller will reserve and release the memory automatically (It will use the stack but nothing prohibits a compiler to use malloc/free implicitly AFAIK).

Returning structs used to be unsupported but enough compilers added it as an extension that I believe it's in the standard now. It's not heap allocated, it gets copied into the stack frame of the caller

Returning a struct works.

We can debate on if returning a dynamically sized array is valuable (it IS possible to do). But the fact that returning an int[3] does not work is just nonsense.

Since the array has a fixed size, you can wrap it in a struct... Dn't ask why it has to be wrapped in a struct..

struct find_devisor_result {
  int result[2];
};

struct find_devisor_result
find_devisor(...) {
  // return 1 & 2 always yes very algorithm
  return (struct find_devisor_result) { .result = { 1, 2 } };
}

(i also didn't test this code at all so it might just not work)

I would say skip the question and ask the teacher.

but https://stackoverflow.com/questions/11656532/returning-an-array-using-c might be helpful. And you can find the size of the array in the place you find the initial array, then pass the size as a parameter.

some teachers use initial quizzes to judge the knowledge of the class in general, and this might be it. Otherwise, they can at least point you to resources.

the struct answer probably is more correct, but may not be for your class if they haven't taught you structs exist yet.

Embrace the darkside. Let the madness take hold.

From what I can tell, this function takes an array of two numbers only. You allocate an array of 2 numbers on the stack, and pass a pointer to it to your function. And then you just write to that pointer within the function.

In general you never want to use malloc within a function. Ideally, you only want to allocate memory at the top scope, and pass a pointer to that memory to whatever function that needs it.

When I was doing C, I remember using structs a lot. For this assignment, probably a struct would be better.

struct two_numbers = {2, 4}
two_numbers = find_divisor(two_numbers)

The larger problem with this question is that since it is impossible to actually return a [local] array, it is unclear which of the things that are possible that it wants you to do. If I were given this question I would probably just use a static array, since that comes closest to the instructed 'return an array' without being undefined behavior.

in reply to @trainsfemme's post:

i must have a really messed up brain cause i actually understand exactly why that doesn't work

when passing an array to a function, the function CANNOT (or hasn't been told to) make any assumptions about the array- because Any code can call this function (especially if loaded like a library), the array size is no longer a known constant like it is with a local array variable- this is why every standard function that takes in an array Also asks for that array's size, since the size of an array is not inherently included with the array (except with zero-terminated strings ("C-strings"), the zero byte marks the end of the string)

i am Very Normal for knowing this by heart :) (help)

if you do end up needing a headstart, there's also searching "c for x programmers", and Learn X in Y Minutes, Where X == C for the whirlwind syntax tour.

and if you need code examples of those things in use, while you can find others, one of the more fun ones is mining Advent of Code solutions, because then you get multiple examples (but they might not be right / the right one to use, necessarily) https://github.com/Bogdanp/awesome-advent-of-code#c

because that lets you then look up those solutions in other languages and see the similarities of approach

In most programming languages, the length of the array is a property of the array. It's stored alongside the array elements.

This is because those programming languages learned from the mistakes of C. In C, an array is just a pointer for the first element of the array. arr[4] actually means "add 4 to the arr pointer then dereference the resulting pointer". C arrays have no concept of size, so you have to pass in the size of the array separately from the array itself.

And this right here is cause of, I want to say, 80%ish of all critical bugs in existence. Hell, this was the cause of the heartbleed bug.

in reply to @trainsfemme's post:

There is a simple and heartbreaking reason for this: arrays are not real.

They're an abstraction over "a sequence of values stored consecutively in the heap", and exist purely as a syntactical sugar to store or access a sequence of values consecutively in the heap. What you're actually saving to a variable when you think you're storing an array is the pointer to the location in memory where the array starts, and what you're doing when you access an item in an array (say x[y]) is accessing the memory at location x+y.

The problem here is that your professor hasn't told you any of this and your experience with higher-level languages where arrays are treated as if they're real is throwing you off. Learning how to work with pointers and memory is by far the biggest hurdle of learning the language. C offers as little abstraction over raw machine code as possible, and a lot of things suffer for it.

my -hope- is this is a Koboyashi Maru to figure out the average knowledge level of the class and not a sign of things to come, but if it ends up continuing to be like this, it might be time to see if you can transfer classes to a different professor.

(Assuming you did whatever assigned readings were assigned)

the most unfortunate truth is that C is probably the oldest programming language still in continuous widespread use. COBOL is older, but it's only used in ancient mainframes. Pascal is a few years older, but it's not used for much these days. C is everywhere and it's over 50 years old. it has not changed very much since the ANSI C revision in 1989 which standardized most of the language.

it's showing its age, definitely.

The thing is, many of C's contemporaries don't have these issues. It's not age that C is showing, it's fanatical dedication to implementation simplicity.

C is basically the third Unkillable Hell Language after Fortran (heavily used in scientific computing to this day and you probably have a BLAS and/or LAPACK implementation somewhere on your computer) and COBOL. One may add Lisp to that list but that's a big philosophical question.

The other three have seen much greater advances than C has which is the real hell of it.

As someone who knows C extremely well: it's a bad language with very few affordances and modernities. It basically expects you to know how things work at a lower level than any other programming language still used today, excluding assembly itself. Once you understand how all the pieces fit together, the limitations make sense from an implementation perspective, but they're still not "good". Don't use C if you can avoid it.