Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-4041-

You have 10 seconds to implement std::vector in plain C

Name: Anonymous 2016-07-20 3:56

Must support:

* Adding elements
* Regrowing

Name: Anonymous 2016-07-20 3:57

Fuck, my finger slipped.

Hard mode:

* Accessing elements directly with array indexing (somevector[0])
* No void * casting.

Name: Anonymous 2016-07-20 17:26

Name: Anonymous 2016-07-20 17:29

Then what is std::vector implemented in? Javascript?

Name: Anonymous 2016-07-20 17:44

>>4
C arrays/pointers are part of the language.

Name: Anonymous 2016-07-20 17:54

>>4
It's implemented in C++ (it pretty much has to be, because it depends on templates and operator overloading). You could get similar functionality in plain C, but you'd have to use a different syntax.

For example, there's really no way to use something like std::vector<int> vec; in plain C, since C doesn't support namespaces or templates. You could implement a struct and appropriate functions to create an automatically resizing array-like data structure, which is really what I think >>1 is asking for. Making it type-generic like std::vector without resorting to making a new version of the struct and associated functions for each data type would be tricky and probably require messing around with pointers and casting, though that would actually be more elegant than what C++ templates actually do (they basically are macros that create multiple type-specific versions of functions and classes at compile time).

Name: Anonymous 2016-07-20 17:59

What is printf implemented in?

Name: Anonymous 2016-07-20 17:59

Making it type-generic like std::vector without resorting to making a new version of the struct
_Generic macro since C11

Name: Anonymous 2016-07-20 18:03

Name: Anonymous 2016-07-20 19:53

>>8
The trouble with _Generic is that the generic macro is defined once with one set of type-to-function associations. You can't use this to define an implementation on some arbitrary type anywhere in your codebase, as C++ vectors are typically used.

Name: Anonymous 2016-07-20 19:59

>>8
C11 is just "C++ without classes"

Name: Anonymous 2016-07-20 20:34

You have 10 seconds to learn a better fucking language than C, where you need to cobble together your own shit from smaller blocks of shit only to end up with a pile of shit that's shitty.

Name: Anonymous 2016-07-20 21:07

not reimplementing the Linux kernel in brainfuck

Name: Anonymous 2016-07-20 21:24

>>2
* No void * casting.
It's a good thing then that C allows type conversion with void* without casting.

>>6
would be tricky and probably require messing around with pointers and casting
It's trivial actually.

Name: Anonymous 2016-07-20 21:27

>>14
It's trivial actually
Only if you're someone that likes working with pointers.

Name: Anonymous 2016-07-21 0:36

>>15
You should do like the scarecrow in Oz and go get yourself a brain.

Name: Anonymous 2016-07-21 0:45

>>6
I like how you explained that as if everyone here were newbies to the language.

Name: Anonymous 2016-07-21 2:09

>>17
he's used to posting on reddit where he'll get upgoats if he ``ELI5''

Name: Anonymous 2016-07-21 4:15

>>18
le georges-louis sage

Name: Anonymous 2016-07-21 6:05

>>12
You have 10 seconds to learn a better fucking language than Common Lisp, where you need to cobble together your own macros from smaller blocks of macros only to end up with a pile of parens that's undecipherable to non-autists.

Name: Anonymous 2016-07-21 6:18

Any C challenge should include:
* No undefined behavior

But that's not really fair, because no actual written C code is free from UB.

Name: Anonymous 2016-07-21 6:18

(this space left intentionally blank)

Name: Anonymous 2016-07-21 7:27

>>15
My wife and daughter are pointers, so I love working with them.

Name: Cudder !cXCudderUE 2016-07-21 11:17

OpenSSL has implemented something like this using macros.

It also has stacks and queues, if I remember correctly.

Name: Anonymous 2016-07-21 11:27

C-dder is all talk and no action!

Name: Anonymous 2016-07-21 11:31

kill yourself >>24 and >>25

Name: Anonymous 2016-07-21 12:39

>>25
Not everyone is a JavaScript ninja.

Name: Anonymous 2016-07-22 10:42

>>24
Your software would be much better if you used tabs instead of a single-space for indentation.

Name: Anonymous 2016-08-01 20:49

the sad thing is that i actually tried to implement this using macros, and I thought it worked but it had a memory related bug that i didn't understand and i realized i suck at C

Name: Anonymous 2016-08-02 7:42

>>29
C itself sucks. You still suck at C, but the language can at least take some of the blame.

Name: Anonymous 2016-08-02 11:51

>>1
struct Cell
{
struct Cell * car;
struct Cell * cdr;
};


Then, just write suitable definitions of std::vector::push_back et al in Lisp.

Done.

Name: Anonymous 2016-08-02 12:44

>>31
how do you store an element in it lol

Name: Anonymous 2016-08-02 16:36

>>32
It's C, so you can cast whatever the fuck you want as a Cell *.

Name: Anonymous 2016-08-02 18:35

>>30
I agree this is true, but still

oh... i just realized it was because my add function uses realloc, so i was reusing an invalid pointer

Name: Anonymous 2016-08-03 8:01

>>33
you can cast anything but it won't be useful. your structure holds pointers to two structures of the smae kind but at no point does it hold anything other than pointers. you made a doubly linked list of nothings

Name: Anonymous 2016-08-03 9:29

>>35
If the semantics of car and cdr are maintained then it's actually a list of lists of lists of lists of lists, ad infinitum.

Name: Anonymous 2016-08-03 9:49

>>36
the problem is the lack of atoms

Name: Anonymous 2016-08-03 16:48

>>35

You can also use it as a singly linked list, with each cell containing a pointer to its data and a pointer to the next cell.

https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/Cons-cells.svg/350px-Cons-cells.svg.png

You can also use it to implement a limited form of binary tree, where only the leaves store values. For example you could have Cell A containing pointers to Cell B and C, and cells B and C each containing pointers to two data objects.

A "true" binary tree however would require at least three pointers per cell, one to store data and two to point to other cells.

Name: Anonymous 2016-08-03 18:32

I know it's been more than 10 seconds but I think emacs has almost finished starting up.

Name: Anonymous 2016-08-03 18:41

>>38
You could do this

[ node-val . [ left-branch . right-branch ] ]

Name: Anonymous 2016-08-03 20:01

>>39
It only takes 5 seconds to start up for me. And my computer's like 5 years old with only 4 GB of RAM.

Name: Anonymous 2016-08-03 20:51

All y'all niggas need some tag bits in yo life.

Name: Anonymous 2016-08-04 2:39

I have never used emacs.

Name: Anonymous 2016-08-04 11:14

I've thought about using Emacs and read a manual..
For example, the shortcut C-M-% is executed by pressing simultaneously four keys on my keyboard, each on a different side of the keyboard. Here is how to remap the associated command to C-c %.

Name: Anonymous 2016-08-04 19:59

Emacs' """shortcuts""" are an object lesson as to why verbose commands or more self-descriptive nested menus are actually sensible.

Name: Anonymous 2016-08-05 3:15

Black """dicks""" are an object lesson as to why my wife needing a real man or a larger penis is actually sensible.

Name: Anonymous 2016-08-06 7:44

>>23
Bestiality detected!

Name: Anonymous 2016-08-06 18:07

>>46
Blacks don't have bigger dicks. You have been fooled by the porn industry.

Name: Anonymous 2016-08-06 18:14

>>6
though that would actually be more elegant than what C++ templates actually do
No, it wouldn't. C++ templates at least work correctly and efficiently. Ad hoc C shit knocked together by a hacker won't.

Name: Anonymous 2016-08-06 18:16

>>49
Elegant in the sense of actually creating true type-generic functions using casting, as opposed to what templates do (create a new copy of the function for each type).

Name: Anonymous 2016-08-06 18:26

>>50
Elegance is subjective here. Elegant casts behind the scenes where I didn't ask for them? At least C++ doesn't lie to you. Performance-wise, it's a trade-off with no clear winner. C++ templates are more performant but cause code-bloat, true generics a la C# (which you are talking about) escape code duplication but contain unnecesary and inelegant casts behind the s

Name: Anonymous 2016-08-07 20:56

>>49
C++ is ad hoc C shit knocked together by a hacker.

Name: Anonymous 2016-08-09 22:30

prime GET

Name: Anonymous 2016-08-10 1:57

>>53
53 is not a prime, dumbass.

Name: Anonymous 2016-08-10 3:30

>>54
53 is a prime, dumbass.

Name: Anonymous 2016-08-10 7:42

>>54
i bet you feel pretty bad now :D

Name: Anonymous 2017-01-05 21:51

>>1
Here's my submission. I didn't bother making it type-generic, however it does meet both primary requirements. As for the secondary requirements, I did not make any use of void pointers, and while it does not support direct array addressing, it does allow array addressing of the data element, as it is stored as a contiguous block of memory. This is demonstrated in the printarray() function. It is written in portable ANSI C, and to the best of my knowledge is free of undefined behavior. If any call to malloc() fails, it is reported to the user and the program quits. I however did not bother to check for failure of any other of the standard library functions included in the program.

#include <stdio.h>
#include <stdlib.h>

typedef struct {
int *data;
unsigned long size;
} vector;

void vector_init(vector *v) {
v->data = NULL;
v->size = 0;
}

void vector_addelement(vector *v, int element) {
int *ptr = realloc(v->data, v->size + 1);
if(ptr == NULL) {
fputs("fatal runtime error: heap allocation failed", stderr);
exit(EXIT_FAILURE);
} else {
v->data = ptr;
v->data[v->size] = element;
v->size++;
}
}

void printvector(vector *v) {
unsigned long i;
for(i = 0; i < v->size; i++) {
printf("%d ", v->data[i]);
}
printf("\n");
}

int main(void) {
vector *vec = malloc(sizeof(vector));
if(vec == NULL) {
fputs("fatal runtime error: heap allocation failed", stderr);
exit(EXIT_FAILURE);
}
vector_init(vec);
vector_addelement(vec, 5);
vector_addelement(vec, 6);
vector_addelement(vec, 10);
printvector(vec); /* 5 6 10 */
vector_addelement(vec, 2);
vector_addelement(vec, 3);
printvector(vec); /* 5 6 10 2 3 */
printf("third element of vec is %d\n", vec->data[2]); /* should be 10 */
printf("there are %d elements in vec\n", vec->size); /* should be 5 */
return(EXIT_SUCCESS);
}

Name: Anonymous 2017-01-05 23:08

The whole concept of vector is unnecessary overhead, use arrays and realloc to needed size or for temporaries: stack arrays which are much faster.

Name: Anonymous 2017-01-05 23:35

>>58
An auto-resizing dynamic array is basically a vector already, it's just useful to have the resizing process streamlined rather than have to manually call realloc every time you do something. And a vector is already easily capable of functioning as a stack, its size (number of elements) multiplied by the size in bytes of each element, gives you an offset from the base of the vector's data block that can be easily used similarly to a stack pointer.

Name: suigin 2017-01-06 11:33

>>58
This. The old adage ``when in /prague/, do as the progriders do'' comes to mind. When in C, do as the old UNIX hackers would. A general purpose vector abstraction has dubious footing in C.

Name: Cudder !cXCudderUE 2017-01-06 11:33

>>59
The main problem with abstractions like vectors is that it makes programmers forget (or ever learn) about resizing, and doing so can be slow since it involves copying all the elements. Thus you end up with code that despite knowing the final length, appends elements to a vector individually, possibly causing resizes, instead of sizing and allocating once and then reading all the elements in. Having to think about realloc() means you're more likely to write your code such that you can avoid it, rather than just doing v.push_back(e); all the time.

I see the latter (anti-)pattern in code a lot. It's disgusting.

Name: Anonymous 2017-01-06 12:54

>>61
yeah, it's horrible because if such a program was designed from the ground up with static arrays in mind it would run its array operations in 0.000000001 seconds and with vector it takes 0.000000005 seconds.

Name: Anonymous 2017-01-06 13:20

>>62
what is big O

Name: Anonymous 2017-01-06 13:50

>>61
Technically, it's not an anti-pattern, it is standard practice. It is idiomatic C++.

The man himself in the "The C++ Programming Language" book says that std::vector is optimized for sequential push_back()s and that you should always prefer vectors (and others) over arrays, and you should always use push_back() on a vector over using realloc() on an array.

Name: Anonymous 2017-01-06 17:04

>>62
That's a 5x slowdown, fucktard. Go round corners somewhere else.

Name: Anonymous 2017-01-06 18:08

>>63
yeah, what is big O? or rather how relevant is it here? you know good vector implementations don't call realloc() on every push_back()/append(), right?

Name: Anonymous 2017-01-07 3:00

>>63
Stay on g we dontwant you here

Name: Anonymous 2017-01-07 4:40

Op: Fuccq u

Name: Anonymous 2017-01-07 7:59

>>67
What does big-O have to do with /g/?

Name: Cudder !cXCudderUE 2017-01-07 15:48

>>64
More proof that C++ is based around dogmatic cargo-cult bullshit. At least std::vector has reserve(), but actually seeing that used correctly --- or at all --- is rare.

std::vector's real use-case is for huge arrays of unknown length, that you would otherwise have to implement with malloc() and realloc() anyway. Large fixed allocations go in static arrays, small static allocations go on the stack, and small dynamic allocations can either be treated as small static ones (if the upper limit is not too high) or a fixed heap allocation. They all have different characteristics and assuming std::vector is the best for all of those use-cases is just plain stupid.

Small inefficiencies add up.

Name: Anonymous 2017-01-07 21:26

Name: Alyssa P. Hacker 2017-01-08 1:32

Name: Anonymous 2017-01-08 5:42

>>70
They add up in insignificant ways until you get hard data by running a profiler.

Name: Cudder !cXCudderUE 2017-01-08 15:53

>>73
Profilers don't always tell the truth because the act of inspection changes the state of the system. They also are useless for looking at memory waste.

Name: Anonymous 2017-01-08 22:54

>>74
So do some basic arithmetic to find memory usage at different points in operation. You have profiler data to say which paths happen and that is all the information one needs to derive the memory usage.

Don't change these.
Name: Email:
Entire Thread Thread List