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

Pages: 1-4041-8081-

Generic programming in C

Name: Anonymous 2012-01-12 3:49

I love C so much, and I really want to hate sepples, but I can't help but think that generic programming in C is shit! Macros are no good for generic data structures, as they are clunky and blow out code size, nor are void pointers, as you need to allocate separate memory just to store an integer (don't stuff ints into pointers; zeros won't work on architectures where the null pointer constant is non-zero). I really want to write my data structure library in sepples, where templates allow type genericism without issue. What should I do, /prague/; what should I do?!

Name: Anonymous 2012-01-12 3:54

Macros are no good for generic data structures, as they are clunky and blow out code size
No, no, no. A fully generic type checked linked list can be written in 15 lines C macros. You must be a fucking retard, in which case I recommend you proceed with using sepples and fuck right off.

Name: Anonymous 2012-01-12 4:00

>>2
While that is true, I do not enjoy the idea of having no function call stack, nor do I enjoy the idea of having the entire code for each action on the structure copied again and again each time it is used. Now you can fuck right off.

Name: Anonymous 2012-01-12 4:20

Write a preprocessor for a C with generics.
Oh, wait!

Name: Anonymous 2012-01-12 4:24

>>4
Oh, wait, what?

Name: Anonymous 2012-01-12 4:29

>>5
C++ was born as a preprocessor for C with classes, Cfront.

Name: Anonymous 2012-01-12 4:49

>>6
So in other words, using sepples isn't such a sin after all, at least not the evil that /prague/ makes it out to be?

Name: Anonymous 2012-01-12 4:51

>>7
It's mostly the bloated standard library that people love to overuse, and of course the tendency to want to create dozens of classes just because it "feels good" (really?)

Name: Anonymous 2012-01-12 6:12

>>7
C with classes evolved in the C++ monster we know and love today.

Not that C was good to begin with.

Name: Anonymous 2012-01-12 6:36

using sepples isn't such a sin after all
Oh it still is... and you'll spend eternity seeking memory leaks and mismanaged pointers in the nine threads of hell.

Name: Anonymous 2012-01-12 6:52

>>10
Well that sucks. How will I make data structures in C without macro hell or void pointers?

Name: Anonymous 2012-01-12 7:08

>How will I make data structures in C
Struct
Union
Typedef struct

Name: Anonymous 2012-01-12 7:57

>>1
Use void pointers. It's what sepples does.

Generics don't actually exists, they are just a layer that the programmer see and that the compiler strips away and does the casts and other things for you automatically

Name: Anonymous 2012-01-12 8:21

I wrote this up today, it's not very well tested but it has worked in the cases that I tested it.

Part 1 of 2:

#ifndef VECTOR_H__
#define VECTOR_H__

/*
 * Please avoid side effects in the arguments
 * to these macros.
 *
 * Note that these macros attempt to do the right
 * thing when it comes to handling errors, generally
 * they will return VECTOR_ERROR (default: NULL)
 * casted to the type the vector carries upon error
 * but more often than not the vector will be invalidated
 * upon error.
 *
 * So if the vector is of type vector(int) then the error
 * return will be (int) NULL, which might be a valid value
 * for successful return depending on the input, therefore
 * it is recommended that you define the VECTOR_ERROR macro
 * to be some value that makes sense for your application.
 */

#include <stddef.h>
#include <stdlib.h>

#define VECTOR_RESIZE_FACTOR 0.70

#ifndef VECTOR_ERROR
# define VECTOR_ERROR NULL
#endif

/**
 * VECTOR_EMPTY_INITIALIZER
 * Provides a valid constant sized empty
 * vector of any type.
 */
#define VECTOR_EMPTY_INITIALIZER                \
  {NULL, NULL, NULL}

/**
 * vector(type)
 * Generic vector that provides
 * - O(1)
 *   - append (amortized)
 *   - capacity
 *   - clear
 *   - is_empty
 *   - get
 *   - get_safe
 *   - pop
 *   - set
 *   - size
 * - O(n)
 *   - insert
 *   - pop_first
 *   - prepend
 *   - remove
 *   - trim
 * operations.
 */
#define vector(type)                            \
  struct {                                      \
    type * base;                                \
    type * head;                                \
    type * end;                                 \
  }

/* returns the new size based
   on VECTOR_SIZE_REFACTOR and
   the old size*/
#define vector_newsize__(oldsize)               \
  ((size_t) ((VECTOR_RESIZE_FACTOR + 1.0) *     \
             (oldsize)) + 1)

/**
 * vector_append
 * Adds element to the end of vector.
 *
 * @param  (vector(type) *) vector in question
 * @param  (type) element to be added
 * @return (type) element that was added
 */
#define vector_append(v, e)                     \
  ({                                            \
    typeof(v)          v__ = (v);               \
    typeof(*v__->base) e__ = (e);               \
    typeof(v__->base)  b__ = v__->base;         \
                                                \
    if (v__->head == v__->end) {                \
      ptrdiff_t cap__;                          \
      cap__ = (v__->end - v__->base);           \
                                                \
      b__ = realloc(v__->base,                  \
                    vector_newsize__(cap__) *   \
                    sizeof(*v__->base));        \
                                                \
      if (b__ != NULL) {                        \
        v__->base = b__;                        \
        v__->head = b__ + cap__;                \
        v__->end  = b__ +                       \
          vector_newsize__(cap__);              \
      }                                         \
    }                                           \
                                                \
    b__ == NULL ?                               \
      (typeof(*v__->base)) VECTOR_ERROR :       \
      (*v__->head++ = e__);                     \
  })

/**
 * vector_capacity
 * Returns the number of elements the current
 * allocated underlying array may hold.
 *
 * @param  (const vector(type) *) vector in question
 * @return (ptrdiff_t) capacity of vector
 */
#define vector_capacity(v)                      \
  ({                                            \
    typeof(v) v__ = (v);                        \
                                                \
    v__->end - v__->base;                       \
  })

/**
 * vector_clear
 * Removes every element from vector
 * and frees the underlying array.
 *
 * @param  (vector(type) *) vector to clear
 * @return (vector(type) *) the cleared vector
 */
#define vector_clear(v)                         \
  ({                                            \
    typeof(v) v__ = (v);                        \
                                                \
    free(v__->base);                            \
    v__->base = NULL;                           \
    v__->head = NULL;                           \
    v__->end  = NULL;                           \
                                                \
    v__;                                        \
  })

/**
 * vector_is_empty
 * Returns whether the vector is empty.
 *
 * @param  (const vector(type) *) vector in question
 * @return (int) zero if the vector isn't empty and non-zero otherwise
 */
#define vector_is_empty(v)                      \
  ({                                            \
    typeof(v) v__ = (v);                        \
                                                \
    v__->base == v__->head;                     \
  })

/**
 * vector_get
 * Returns the element at a certain
 * position in the vector without
 * removing it.
 *
 * @param  (const vector(type) *) the vector in question
 * @param  (int) index of element in vector
 * @return (type) the element at index in vector
 */
#define vector_get(v, i)                        \
  ((v)->base[(i)])

/**
 * vector_get_safe
 * Returns the element at a certain
 * position in the vector without
 * removing it.
 *
 * This returns NULL casted to type
 * upon error.
 *
 * @param  (const vector(type) *) the vector in question
 * @param  (int) index of element in vector
 * @return (type) the element at index in vector
 */
#define vector_get_safe(v, i)                   \
  ({                                            \
    typeof(v) v__ = (v);                        \
    int i__ = (i);                              \
                                                \
    i__ < vector_size(v) ?                      \
      v__->base[i__] :                          \
      (typeof(*v__->base)) VECTOR_ERROR;        \
  })

/**
 * vector_insert
 * Inserts an element at a certain position
 * in vector without removing any elements.
 *
 * @param  (vector(type) *) the vector in question
 * @param  (int) the index of the new element
 * @param  (type) the element to be added
 * @return (type) the added elemenet
 */
#define vector_insert(v, i, e)                  \
  ({                                            \
    typeof(v) v__ = (v);                        \
    typeof(*v__->base) e__ = (e);               \
    typeof(*v__->base) l__;                     \
    int i__ = (i);                              \
    ptrdiff_t size__ = vector_size(v);          \
                                                \
    l__ = (typeof(*v__->base)) VECTOR_ERROR;    \
                                                \
    if (i__ < 0)                                \
      l__ = l__;                                \
    else if (i__ == size__)                     \
      l__ = vector_append(v, e);                \
    else if (i__ < size__) {                    \
      typeof(*v__->base) p__;                   \
      int j__;                                  \
                                                \
      p__ = v__->base[size__-1];                \
                                                \
      for (j__ = size__-1; j__ > i__; j__--)    \
        v__->base[j__] = v__->base[j__-1];      \
                                                \
      v__->base[i__] = e__;                     \
                                                \
      l__ = vector_append(v, p__) ==            \
        (typeof(*v__->base)) VECTOR_ERROR ?     \
        l__ :                                   \
        e__;                                    \
    } else                                      \
      l__ = l__;                                \
                                                \
    l__;                                        \
  })

Name: Anonymous 2012-01-12 8:22

>>14

Part 2 of 2:

/**
 * vector_pop
 * Removes and returns the element
 * at the end of the vector.
 *
 * @param  (vector(type) *) vector in question
 * @return (type) the removed element
 */
#define vector_pop(v)                           \
  ({                                            \
    typeof(v) v__ = (v);                        \
                                                \
    v__->head == v__->base ?                    \
      (typeof(*v__->base)) VECTOR_ERROR :       \
      *--v__->head;                             \
  })

/**
 * vector_pop_first
 * Removes and returns the first
 * element of the vector.
 *
 * @param  (vector(type) *) vector in question
 * @return (type) the removed element
 */
#define vector_pop_first(v)                     \
  ({                                            \
    typeof(v) v__ = (v);                        \
    typeof(*v__->base) l__;                     \
    ptrdiff_t size__;                           \
                                                \
    size__ = vector_size(v);                    \
                                                \
    if (size__ > 1) {                           \
      int i__;                                  \
                                                \
      l__ = v__->base[0];                       \
                                                \
      for (i__ = 0; i__ < size__-1; i__++)      \
        v__->base[i__] = v__->base[i__+1];      \
                                                \
      v__->head -= 1;                           \
    } else {                                    \
      l__ = vector_pop(v);                      \
    }                                           \
                                                \
    l__;                                        \
  })

/**
 * vector_prepend
 * Adds element to the front of vector.
 *
 * @param  (vector(type) *) vector in question
 * @param  (type) element to be added to vector
 * @return (type) element that was added
 */
#define vector_prepend(v, e)                    \
  ({                                            \
    typeof(v)          v__ = (v);               \
    typeof(*v__->base) e__ = (e);               \
    typeof(*v__->base) l__;                     \
    ptrdiff_t size__ = vector_size(v);          \
                                                \
    if (size__ > 0) {                           \
      int i__;                                  \
                                                \
      l__ = v__->base[size__-1];                \
                                                \
      for (i__ = size__ - 1; i__ > 0; i__--)    \
        v__->base[i__] = v__->base[i__-1];      \
                                                \
      v__->base[0] = e__;                       \
    } else {                                    \
      l__ = e__;                                \
    }                                           \
                                                \
    vector_append(v, l__) ==                    \
      (typeof(*v__->base)) VECTOR_ERROR ?       \
      (typeof(*v__->base)) VECTOR_ERROR :       \
      e__;                                      \
  })

/**
 * vector_remove
 * Removes and returns an element at a
 * certain position in vector.
 *
 * @param  (vector(type) *) vector in question
 * @param  (int) index of element
 * @param  (type) the removed element
 */
#define vector_remove(v, i)                     \
  ({                                            \
    typeof(v)          v__ = (v);               \
    typeof(*v__->base) l__;                     \
    int i__ = (i);                              \
    ptrdiff_t size__ = vector_size(v);          \
                                                \
    l__ = (typeof(*v__->base)) VECTOR_ERROR;    \
                                                \
    if (i__ < 0)                                \
      l__ = l__;                                \
    else if (i__ == size__-1)                   \
      l__ = vector_pop(v);                      \
    else if (i__ < size__) {                    \
      int j__;                                  \
                                                \
      l__ = v__->base[i__];                     \
                                                \
      for (j__ = i__; j__ < size__-1; j__++)    \
        v__->base[j__] = v__->base[j__+1];      \
                                                \
      v__->head -= 1;                           \
    } else                                      \
      l__ = l__;                                \
                                                \
    l__;                                        \
  })

/**
 * vector_set
 * Sets the element at a certain position
 * in the vector and removes the old element.
 *
 * @param  (vector(type) *) the vector in question
 * @param  (int) index of new element
 * @param  (type) element to be added
 * @return (type) element that was added
 */
#define vector_set(v, i, e)                     \
  ({                                            \
    typeof(v)          v__ = (v);               \
    typeof(*v__->base) e__ = (e);               \
    typeof(*v__->base) l__;                     \
    int i__ = (i);                              \
    ptrdiff_t size__;                           \
                                                \
    size__ = vector_size(v);                    \
    l__ = (typeof(*v__->base)) VECTOR_ERROR;    \
                                                \
    if (i__ < 0)                                \
      l__ = l__;                                \
    else if (i__ < size__)                      \
      l__ = (v__->base[i__] = e__);             \
    else if (i__ == size__)                     \
      l__ = vector_append(v, e);                \
    else                                        \
      l__ = l__;                                \
                                                \
    l__;                                        \
  })

/**
 * vector_size
 * Returns the current number of elements
 * in the vector.
 *
 * @param  (const vector(type) *) vector in question
 * @return (ptrdiff_t) number of elements in vector
 */
#define vector_size(v)                          \
  ({                                            \
    typeof(v) v__   = (v);                      \
                                                \
    v__->head - v__->base;                      \
  })

/**
 * vector_trim
 * Resizes the underlying array so only the
 * elements currently in vector fits.
 *
 * @param  (vector(type) *) the vector in question
 * @return (vector(type) *) the trimmed vector
 */
#define vector_trim(v)                          \
  ({                                            \
    typeof(v) v__ = (v);                        \
    typeof(v__->base) b__;                      \
    ptrdiff_t size__ = vector_size(v);          \
                                                \
    b__ = realloc(v__->base,                    \
                  size__ * sizeof(*v__->base)); \
                                                \
    if (b__ != VECTOR_ERROR) {                  \
      v__->base = b__;                          \
      v__->head = b__ + size__;                 \
      v__->end  = b__ + size__;                 \
    }                                           \
                                                \
    b__ == VECTOR_ERROR ?                       \
      VECTOR_ERROR :                            \
      v__;                                      \
  })

#endif /* VECTOR_H__ */

Name: Anonymous 2012-01-12 9:00

>>14
>>15

I was a little over-eager near the end so some of the NULLs were turned into VECTOR_ERRORs, the comparisons with b__ should be NULL and not VECTOR_ERROR.

Also this is not macro hell, this is macro heaven.

Name: Anonymous 2012-01-12 9:06

>>14-15
Why would you do that to my eyes. Why.

Name: Anonymous 2012-01-12 9:08

PIG DISGUSTING!

Name: Anonymous 2012-01-12 9:36

>>15
>>14

Perfect example of Preprocessor abuse.

Enjoy wondering why your 500 lines equates to 50000+ line C file won't compile when you try to use that in any type of project that makes heavy use of said data structure.

Name: Anonymous 2012-01-12 10:05

>>13

how does that work for char and int? They are different sizes.

Name: Anonymous 2012-01-12 10:13

>>1
You should try C++. It supports templates which would allow you to do what you want. It also has STL that has some nice standard containers. STL is easily better than Java or C# containers.

Name: Anonymous 2012-01-12 10:55

>>14
>>15

we deserve more than stumping to pre-processor abuse.

Name: Anonymous 2012-01-12 11:08

You think C++ is bad because you haven't properly given it a chance or are too incompetent to use it well.

p.s. god damn you can't even program in C.

Name: Anonymous 2012-01-12 11:09

>>14,15

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

#include "vector.h"

int main (int argc, char ** argv) {
  vector(int) numbers = VECTOR_EMPTY_INITIALIZER;

  while (--argc)
    vector_append(&numbers, atoi(*++argv));

  while (!vector_is_empty(&numbers))
    printf("%d\n", vector_pop(&numbers));

  vector_clear(&numbers);

  return 0;
}

Name: Anonymous 2012-01-12 11:16

You think Brainfuck is bad because you haven't properly given it a chance or are too incompetent to use it well.

p.s. god damn you can't even program in Python.

Name: Anonymous 2012-01-12 11:20

>>25
invalid analogy you moron

Name: Anonymous 2012-01-12 11:41

>>26
moron analogy you invalid

Name: kodak_gallery_programmer !!kCq+A64Losi56ze 2012-01-12 11:54

>>24
I bet your mom must be proud oc that piece of C code.

Name: Anonymous 2012-01-12 11:56

So use C++ then, and pick and choose your style of programming. C++ doesn't really remove anything of value from C, and it adds a ton of features, at least a handful of which you may find useful. Also, it's a hell of a lot safer than these posts:

>>14
>>15

There's no real benefit to using C over C++ except for a slight performance boost (which really is only slight), it's just that C programmers hate C++ programming practices, which you don't have to use (it's just that C++ programmers consider them safer than the C alternative, which is >>14-15)

Name: Anonymous 2012-01-12 11:57

>>28
I showed it to her and she said she didn't understand.

Name: kodak_gallery_programmer !!kCq+A64Losi56ze 2012-01-12 11:59

>>24
By the way, I think you meant __typeof__ and not typeof.

Name: Anonymous 2012-01-12 12:00

>>31
Not the guy who made it but it's clearly not for use in ISO C programs.

Name: Anonymous 2012-01-12 12:02

>>31
This is your daily reminder that the statement every subset of a countable set is also countable is absolutely true and never fails under any conditions.

Keep denying the truth you mental midget, I'm sure it'll change one day. Oh wait...

Name: Anonymous 2012-01-12 12:04

>>27
that's another way to reply to what >>25 said, yes.

>>29
c isn't faster. c++ wasn't designed in such a way that you could never write code that was fast as c code. it's all down to the implementation.

Name: Anonymous 2012-01-12 12:05

>>34
C++ is a lot faster than C, actually.

Name: Anonymous 2012-01-12 12:06

and before someone says the implementation will end up being c code... no. i was also talking about the compiler anyway.

Name: Anonymous 2012-01-12 12:06

>>35
in what way?...

Name: Anonymous 2012-01-12 12:07

Name: Anonymous 2012-01-12 12:33

>>3
There is no ``function call stack'' in C so you are wrong right from the start, and in any case, if you are worried about a little bit of macro replacement you shouldn't be using C in the first place. (You do know how #include works, right?)

Also, you forgot to sage your worthless post.

(p.s. >>14,15 is an idiot.)

Name: Anonymous 2012-01-12 12:52

>>39
errr yes there is? he's not talking about stack traces in case you misunderstood

Name: /prog/ police !1fOeGamQwA!PrM413+Y2UUOlKE 2012-01-12 12:52

>>40
Go back to /g/.

Name: Anonymous 2012-01-12 13:40

#ifndef GENERIC_VECTOR_H__
#define GENERIC_VECTOR_H__

#define _LStruct(TYPE)                                                    \
struct {                                                                \
    int cap, num;                                                        \
    TYPE *table;                                                        \
}
#define DEF_LIST(NAME, TYPE)                                            \
typedef _LStruct(TYPE) NAME;                                            \
NAME NAME##Create() {                                                    \
    return (NAME){128, 0, malloc(128 * sizeof(TYPE))};                    \
}                                                                        \
void NAME##Push(NAME *v, TYPE t) {                                        \
    if(v->cap == v->num)                                                \
        v->table = realloc(v->table, (v->cap *= 2) * sizeof(TYPE));        \
    v->table[v->num++ % v->cap] = t;                                    \
}                                                                        \
TYPE NAME##Pop(NAME *v) {                                                \
    TYPE t = v->table[0];                                                \
    for(int i = 0; i < v->num - 1; i++) v->table[i] = v->table[i+1];    \
    return t;                                                            \
}

#endif


#include <stdio.h>
#include <stdlib.h>
#include "glist.h"
DEF_LIST(IntVec, int);

int main() {
    IntVec x = IntVecCreate();
    for(int i = 0; i < 3; i++) IntVecPush(&x, i);
    for(int i = 0; i < 3; i++) printf("%d ", IntVecPop(&x));
    printf("\n");
}


> 0 1 2

Name: Anonymous 2012-01-12 13:42

>>42
Fucking shitchan.

#ifndef GENERIC_VECTOR_H__
#define GENERIC_VECTOR_H__

#define _LStruct(TYPE)                                                  \
struct {                                                                \
    int cap, num;                                                       \
    TYPE *table;                                                        \
}
#define DEF_LIST(NAME, TYPE)                                            \
typedef _LStruct(TYPE) NAME;                                            \
NAME NAME##Create() {                                                   \
    return (NAME){128, 0, malloc(128 * sizeof(TYPE))};                  \
}                                                                       \
void NAME##Push(NAME *v, TYPE t) {                                      \
    if(v->cap == v->num)                                                \
        v->table = realloc(v->table, (v->cap *= 2) * sizeof(TYPE));     \
    v->table[v->num++ % v->cap] = t;                                    \
}                                                                       \
TYPE NAME##Pop(NAME *v) {                                               \
    TYPE t = v->table[0];                                               \
    for(int i = 0; i < v->num - 1; i++) v->table[i] = v->table[i+1];    \
    return t;                                                           \
}

#endif

Name: Anonymous 2012-01-12 13:51

>>42,43
Er, remove the % v->cap, was for a different circular buffer impl.

Name: Anonymous 2012-01-12 14:00

>>40
There is no function call stack in C you dumb Jew, there is no stack at all in C. Now fuck off you back to /g/ you piece of shit retard.

Name: Anonymous 2012-01-12 14:15

>>45
>2011
>being anal about stacks even though you very well know what he means
Confirmed for Asperger

Name: Anonymous 2012-01-12 14:18

>>46
back to /g/, please

Name: Anonymous 2012-01-12 14:18

The oroginal source for CFront:


/* CFront.h: The revolutional object system */

#ifndef orgasm_h_
#define orgasm_h_

#define class struct

#endif

Name: Anonymous 2012-01-12 14:18

>>47
back to /b/, please

Name: Anonymous 2012-01-12 14:21

>>46
I really don't know what he means, please explain it to me.

Name: Anonymous 2012-01-12 14:22

>>50
Go back to /g/

Name: Anonymous 2012-01-12 14:28

using C instead of cobol

Name: Anonymous 2012-01-12 14:31

>>51
No, please explain to me what he means when he's talking about a stack in C, please do, because I can't find it mentioned anywhere in C89, C99 or C11.

Name: Anonymous 2012-01-12 14:35

>>3,40,46
The C standard does not describe or mention a "stack." In many implementations, the activation record, arguments, and local variables are stored in different regions of memory or registers. The System/360 (S/370, S/390, and System z) uses a linked list of activation records allocated using GETMAIN and separate memory regions for the argument list and local variables, also allocated using GETMAIN. Similarly, the ARM allows "chunked stacks" where each activation record is part of a linked list. The VAX uses a contiguous stack for return addresses, but also has CALLG which is a standard call where the argument list can be anywhere in memory. Many RISCs pass arguments in registers and store the return address in a register, so they are able to complete a function call without even touching a stack. Other machines may use separate stacks for return addresses, arguments, and local variables, and may further break them down depending on whether these items are integers, floating-point, or pointers. Some small architectures like PICs may use static variables for all functions that are determined at compile time not to be recursive, allowing the fixed-size stack to be conserved for storing return addresses without violating the standard.

Name: Anonymous 2012-01-12 15:04

>>40
C is a high level language, it has no notion or knowledge of a call stack.

Name: Anonymous 2012-01-12 15:23

>>54
Many RISCs pass arguments in registers and store the return address in a register, so they are able to complete a function call without even touching a stack.
Don't forget Itanium, it does (did?) all that and more.

Some small architectures like PICs may use static variables for all functions that are determined at compile time not to be recursive, allowing the fixed-size stack to be conserved for storing return addresses without violating the standard.
That's not really about an architecture, only about compiler. Keil Microvision did that for 8051, but seamlessly switched to compiling functions as reentrant (all locals on stack) if necessary. I sometimes wonder why none of the major x86 compilers do that, if you don't count inlining as the logical conclusion of this approach.

Name: Anonymous 2012-01-12 22:31

>>48

But a class isn't a struct. It's a struct that defaults members to be private. And C++ structs are better than C structs. They have an implicit typedef and can have methods as well as member variables.

Why shouldn't one just use C++ instead of tossing around shitty C hacks?

Name: Anonymous 2012-01-12 22:35

>>53
I'm sorry I can't hear you over my awesome C implementation

Name: Anonymous 2012-01-12 22:43

If you are still here OP I'd be interested in your thoughts on the technique in >>42 considering it does not duplicate code for every use of the data structure.

Name: Anonymous 2012-01-12 22:55

>>58
3/10

Name: Anonymous 2012-01-12 22:57

>>60
You're just mad because you have an inferior implementation on a toy architecture. ;)

Name: Anonymous 2012-01-13 0:12

>>57
Did you read this thread at all? C++ started out as a c pre- OH, you're a troll. Good one, I almost got mad

Name: Anonymous 2012-01-13 1:36

Simple solution to all of this bumfuckery:




































































USE LISP!

Name: Anonymous 2012-01-13 2:04

(Post truncated.) is an inherently sinful message.

End the delusions. Open your chakras.

Name: Anonymous 2012-01-13 3:20

>>59
Still a disgusting abuse of preprocessor macros. It's hardly elegant.

Name: Anonymous 2012-01-13 5:57

>>59
Well I'm not OP but _LStruct is a reserved identifier, you managed to make it O(n) even though you're only defining two operations on it which you named push and pop and are commonly used for stacks, you never check malloc or realloc for failing so it will probably just segfault after a while considering you're just allocating double the amount of memory every time and  you never give any option to create it a capacity of less than 128 elements.

Name: Anonymous 2012-01-13 14:21

>>66
You are an idiot. It's a proof of concept, and you didn't bring a single conceptual issue to bare. Why don't you go and argue about the color of some bike sheds?

Name: Anonymous 2012-01-13 17:00

>>45,50,53,54
call stack semantics you nerds

Name: Anonymous 2012-01-13 17:13

The real solution to all the world's problems lies somewhere between void* and C++.

Name: Anonymous 2012-01-13 17:23

>>67
It's a pretty bad proof of concept.

Name: Anonymous 2012-01-13 19:18

>>67
Well I'm sorry that you're a fucking retard, and if you really want to know, the concept is fucking retarded as well.

Name: Anonymous 2012-01-13 19:25

>>71
/polecat kebabs/

Name: Anonymous 2012-01-13 21:15

C11 has improved generic support for the preprocessor.

Check out GCC 4.7 or Clang 3.1 nightly snapshots.

Name: Anonymous 2012-01-13 21:44

>>73
What is your point? You have to know all the types you want to generate functions for before you create the generic selection macro so it does nothing to aid us in this situation.

Name: Anonymous 2012-01-13 22:16

>>40
Actually, I guess what >>39-san is saying is that nowhere in the standard that defines C there is any mention of a "function call stack". It is usually implemented that way but that is not mandatory. Officially, C does not have a stack.

In fact, in some architectures, it is not even an advantage for it to be implemented with them.

Name: Anonymous 2012-01-14 3:18

>>1
architectures where the null pointer constant is non-zero

are retarded and don't deserve support.

Name: Anonymous 2012-01-14 3:21

>>76
Support my anus

Name: Anonymous 2012-01-14 3:22

>>77
gladly

Name: Anonymous 2012-01-14 5:16

>>76
I don't want to write a program in C that makes assumptions about the target hardware that aren't necessarily true.

Name: Anonymous 2012-01-14 5:29

>>79
If you compare the logical value of pointers to a constant integer zero, you should be fine. But if you use memcmp or do union or casting tricks to compare the bit pattern of the pointer to the bit pattern of an integer with a value of zero, it is not guaranteed to be zero.
#include <assert.h>
int main(void) {
     union {
          void *p;
          int i;
     } u;
     u.p = 0;
     void *p = 0;
     int i = 0;
     assert(p == u.p); /* true */
     assert(p == 0); /* true */
     assert(u.p == 0); /* true */
     //assert((int)p == i); /* not guaranteed */
     //assert((int)u.p == u.i); /* not guaranteed */
     //assert(p == (void *)i); /* not guaranteed */
     //assert(u.p == (void *)u.i); /* not guaranteed */
     //assert(memcmp(&u.i, &i, sizeof(int)); /* not guaranteed */
}

Name: Anonymous 2012-01-14 5:36

Generic programming in C
Back in my time, when men were men, we simply used void pointers and an enum that indicated the real type of the pointer if needed.

Name: Anonymous 2012-01-14 6:07

>>81
Back in my time, we used two unused lower bits of pointer to hold type.

Name: Anonymous 2012-01-14 6:27

>>81
sounds like an ugly hack

Name: Anonymous 2012-01-14 6:56

A generic linked list that will contain anything you could think of. No macros! It assumes struct node has the strictest alignment.

#include <stdlib.h>
#include <stddef.h>
#include <string.h>

// API
struct list;

struct list *make_list(size_t elem_size);
void *prepend(struct list *l);
void *append(struct list *l);
void *insert_after(struct list *l, void *node);
void *insert_before(struct list *l, void *node);
void *head(struct list *l);
void *tail(struct list *l);
void *next(void *node);
void *previous(void *node);

// implementation

struct list
{
    size_t elem_size;
    struct node head, tail;
};

struct node
{
    struct node *prev, *next;
};

struct list *make_list(size_t elem_size)
{
    struct list *l;

    l = malloc(sizeof *l);
    l->elem_size = elem_size;
    l->head.next = &l->tail;
    l->tail.prev = &l->head;
    return l;
}

static struct node *make_node(size_t elem_size)
{
    struct node *n;
    size_t size;

    size = sizeof *n + (elem_size + sizeof *n - 1) / sizeof *n;
    n = malloc(size);
    return n;
}

static void insert(struct node *i, struct node *p, struct node *n)
{
    p->next = i;
    i->prev = p;
    i->next = n;
    n->prev = i;
}


void *prepend(struct list *l)
{
    struct node *n;

    n = make_node(l->elem_size);
    insert(n, &l->head, l->head.next);
    return n + 1;
}

void *append(struct list *l)
{
    struct node *n;

    n = make_node(l->elem_size);
    insert(n, l->tail.prev, &l->tail);
    return n + 1;
}

void *insert_after(struct list *l, void *node)
{
    struct node *m, *n;

    m = (struct node *)node - 1;
    n = make_node(l->elem_size);
    insert(n, m, m->next);
    return n + 1;
}

void *insert_before(struct list *l, void *node)
{
    struct node *m, *n;

    m = (struct node *)node - 1;
    n = make_node(l->elem_size);
    insert(n, m->prev, m);
    return n + 1;
}

void *head(struct list *l)
{
    return &l->head + 1;
}

void *tail(struct list *l)
{
    return &l->tail + 1;
}

void *next(void *node)
{
    struct node *n;

    n = (struct node *)node - 1;
    return n->next + 1;
}

void *previous(void *node)
{
    struct node *n;

    n = (struct node *)node - 1;
    return n->prev + 1;
}

// example

struct person
{
    char name[60];
    int age;
};

void init_person(struct person *p, const char *name, int age)
{
    strcpy(p->name, name);
    p->age = age;
}

int main()
{
    struct list *l;
    struct person *p;

    l = make_list(sizeof *p);
    init_person(append(l), "Charlie", 8);
    init_person(append(l), "Bob", 42);
    init_person(append(l), "Niels", 9);
    init_person(append(l), "Jon", 11);
    init_person(append(l), "Becky", 10);
    init_person(append(l), "Ashley",9);

    for (p = next(head(l)); p != tail(l); p = next(p)) {
        printf("%s %d\n", p->name, p->age);
    }

    exit(EXIT_SUCCESS);
}

I wrote this on my phone, so I probably made some mistakes. I didn't bother to add remove() or error handling, but that should be straight-forward.

Name: Anonymous 2012-01-14 7:06

>>84
linked is shit

Name: Anonymous 2012-01-14 14:18

>>85
If it ain't linked, it's crap.

Name: Anonymous 2012-01-14 14:58

>>86
If it is linked, it's shit, unless it's a lock-free concurrent structure then it's acceptable.

Name: Anonymous 2012-01-14 15:01

>>85-87
Lists are shit.

Name: Anonymous 2012-01-14 15:01

>>14,15
This is how GNU does it afaik.

Name: Anonymous 2012-01-14 15:16

>>84
It assumes undefined behaviour
Enjoy your segfaults.

Name: Anonymous 2012-01-14 18:53

>>88
1) If it ain't Lisp, it's crap.
2) Lisp is shit.

Name: Anonymous 2012-01-14 19:00

http://chaos-pp.cvs.sourceforge.net/viewvc/chaos-pp/order-pp/example/array_ops.c?view=markup
You can do generic programming using macro libraries like Chaos, Order, and Boost Preprocessor.

Name: Anonymous 2012-01-14 20:59

#define GENERIC_TYPE Jew
#include <work_camp.h>
#define GENERIC_TYPE Nigger
#include <work_camp.h>
#define GENERIC_TYPE Faggot
#include <work_camp.h>
#define GENERIC_TYPE Communist
#include <work_camp.h>
enum WorkCamp { Auschwitz, Dachau };
int Goldberg(void) {
#define Mr_Goldberg_TYPE Jew
  Jew Mr_Goldberg = get_vitals(Jew, "Itzhak Goldberg");
  send_to_camp(Mr_Goldberg, Dachau);
  return Mr_Goldberg->serialNumber;
}

Name: Anonymous 2012-01-14 21:38

>>93
2/10

Name: Anonymous 2012-01-14 21:51

>>93
lol, nice

Name: Anonymous 2012-01-14 22:11

>>93
9.5/10

Name: Anonymous 2012-01-15 0:59

>>93
http://en.wikipedia.org/wiki/Whoopi_Goldberg
She adopted the traditionally German/Jewish surname Goldberg as a stage name because her mother felt the original surname of Johnson was not "Jewish enough" to make her a star.

She had a smart mother.

Name: Anonymous 2012-01-15 1:18

>>97
Goldberg made a sexual joke about President George W. Bush, by waving a bottle of wine, pointing toward her pubic area and saying: "We should keep Bush where he belongs, and not in the White House."

Name: Anonymous 2012-01-16 0:15

>>98
Awesome.

She is still annoying.

Name: DUBS LIBERATION FRONT 2012-03-24 18:30

NON-DUBS SHALL BE CLEANSED FROM THE EARTH!

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