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

Pages: 1-

I am a C Programmer

Name: Anonymous 2012-01-27 23:08

Yes. I'm a C programmer. So? I don't see a problem. I embraced my UNIX soul long ago and I am happy together with my compiler (who is a cute layered front/backend design!). We have a fucking lot of functions in and outside of the kernel and I am pretty compact and resource conserving.

But thanks anyway asshole. Go and beat off to your stupid garbage collection shit while I #INCLUDE <stdio.h> with my preprocessor.

Name: Anonymous 2012-01-27 23:26

It's possible to write C programs with garbage collection (I've done it). Just because it's not built in the language means nothing. You must be new to C. How are you liking it so far?

Name: Anonymous 2012-01-27 23:28

>>1
congrats. now what?

Name: Anonymous 2012-01-27 23:32

>>1
I can do anything you can do in C in Lisp. Butthurt much?

Name: Anonymous 2012-01-27 23:32

>>2
How do you implement a destructor in C?

Name: Anonymous 2012-01-27 23:33

>>5
Trivially.

Name: Anonymous 2012-01-27 23:38

>>6
I know gnu89/gnu99 has __attribute__((constructor)), but can you implement a destructor in C?

Name: Anonymous 2012-01-27 23:45

>>5
If you want OOP in C (inheritance, constructors, deconstructors, etc.) do something like this:



typedef struct object object;

enum {
  T_NUM,
  T_STR
};

struct object {
  int type;
  union {
    double num;
    char *str;
  } val;
};

object *new_obj(int type) {
  object *obj;

  obj = malloc(sizeof(*obj));
  obj->type = type;
  return obj;
}

object *new_num(double num) {
  object *obj;

  obj = new_obj(T_NUM);
  obj->val.num = 0;
  return obj;
}

object *new_str(char *str) {
  object *obj;

  obj = new_obj(T_STR);
  obj->val.str = strdup(str);
  return obj;
}

void delete(object *obj) {
  if (obj->type == T_STR)
    free(obj->val.str);
  free(obj);
}

Name: Anonymous 2012-01-27 23:46

>>8
obj->val.num = 0; should be obj->val.num = num;

Whatever.

Name: Anonymous 2012-01-27 23:49

>>8

Well, yes, that's trivial, and single inheritance comes easily enough.
There's still no way of really making a destructor.

Name: Anonymous 2012-01-27 23:50

>>2
but I don't want to

Name: Anonymous 2012-01-27 23:55

>>10

you just have to explicitly call it. And if you want the inheritance with destructors to work, you just have to explicitly call the destructor of the parent class from the destructor of the child class. There is the issue of forgetting to call the destructors for scoped variables on the stack. You can't really get around that, so you have to be careful to remember, at it is error prone.

Name: Anonymous 2012-01-27 23:55

>>10
Sure there is. Keep in mind that both C++ and Objective C compilers used to be nothing more than preprocessors that generated regular C code.

Name: Anonymous 2012-01-27 23:59

>>12,13
I know it's possible if i write the code manually.
The C macro system isn't powerful enough to do the sort of static analysis required to know when variables go out of scope.
So, i'd have to use a custom preprocessor, at which point the language is no longer C.

Name: Anonymous 2012-01-28 0:10

I suppose it's possible if i have something like


#define { { scope_open();
#define } scope_close(); }
#define new(x,y) y=##x __new(); scope_reg(y, ##y __free());
#define SCOPE_MAX_DEPTH 256

static int scope_idx = 1;
static std::map<void*, void(*pFree)()>[SCOPE_MAX_DEPTH] scope_elems;

void scope_open() {
  scope_idx++;
}
void scope_reg(pObj, pFree) {
  scope_elems[scope_idx].insert(pObj, pFree);
}
void scope_close() {
  for(int i = 0, e = scope_elems[scope_idx].size(); i < e; i++) {
    scope_elems[scope_idx][i].second(); /* destructor */
  }
  scope_elems[scope_idx].clear();
}


Obviously i would need to use a C equivalent of the std::map, which is trivial, and should use a dynamically expanding array instead of a fixed-size one..
.. but maybe it's possible after all...
Someone familiar with THE STANDARD tell me if those #defines are remotely close to being valid?

Name: Anonymous 2012-01-28 0:15

>>15
some addendums;
#define's must be after declaration of scope_ functions, or in another translation unit, to avoid an infinite loop when they are first called
#define new should call scope_reg with a function ptr, not the value

Name: Anonymous 2012-01-28 0:20

>>15,16
further addendums;
>destructors.c:8:9: error: macro names must be identifiers

So, perhaps this approach isn't valid after all. I guess you would have to use some other character instead of { to denote the start of a block... at which point you're conceptually doing things like #define END } to turn C into BASIC or Pascal. Although, it would be very interesting to see how the result is, perhaps a sort of higher-level language that compiles with a C compiler.

Name: Anonymous 2012-01-28 1:07

>>17

that's some pretty cool stuff bro. It reminds me of the c implementations of stack based language/virtua machine. You could implement dynamic scoping with something like that if you wanted to.

It might be possible with macros though, which would be ideal since the destructor calls could be determined at compile time. It would be trivial to do in lisp, and lisp weenies do it all the time with stuff like with-open-file. Here's an attempt with the C preprocessor:


#include <stdio.h>
#include <malloc.h>

#define SCOPE(type, variable_name, constructor_expression, destructor_expression, body) \
{ \
  type variable_name = constructor_expression; \
  body \
  destructor_expression; \
}


int main(int argc, char** argv) {
  SCOPE(int*, x, malloc(sizeof(int)), free(x),
    *x = 5;
    printf("[%p] = %d\n", x, *x);
  )
  return 0;
}

$ a.out
[0x8dfc008] = 5
$ valgrind --leak-check=full a.out
==2702== Memcheck, a memory error detector
==2702== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2702== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for copyright info
==2702== Command: a.out
==2702==
[0x4181028] = 5
==2702==
==2702== HEAP SUMMARY:
==2702==     in use at exit: 0 bytes in 0 blocks
==2702==   total heap usage: 1 allocs, 1 frees, 4 bytes allocated
==2702==
==2702== All heap blocks were freed -- no leaks are possible
==2702==
==2702== For counts of detected and suppressed errors, rerun with: -v
==2702== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 8)
$

Name: Anonymous 2012-01-28 1:46

If private: in a struct definition is considered a label, you might be able to build classes using something like

#define class struct
#define private private ## __LINE__


to avoid duplicate labels. However i expect this code won't work either.


>>18
I see, you can express the body in terms of the macro, which is possibly the cleanest way of doing things. However that still inevitably requires special syntax. Combining your approach with >>15 allows for not specifying the variable name, its constructor and destructor every time you create a block, and hence the trivial ability to create a block without a variable and a variable without a block

Name: Anonymous 2012-01-28 1:54

>>19

yeah, if one wanted to they could use consistent names for the destructor functions, such that

type_t could be mapped to

void destroy##type_t(type_t* target) {

}

and then the name of the destructor could be inferred from the type. But the new syntax will look confusing to people, there is no getting around that. Also, a SCOPE macro is required for every variable that will use a destructor, which is annoying, and totally avoidable if the macro system was lispy.

Name: Anonymous 2012-01-28 15:21

>>20
A SCOPE macro would be required for every block, but it wouldn't be required for every variable, using the caching technique shown in >>15 .

Name: Anonymous 2012-01-28 15:35

>>21
yeah, but seeing how the number of variables allocated within a block is known at compile time, it would be ideal if the destructor calls could be put in at compile time. The system in >>15 is actually more powerful than seeples destructors, and you could use it for more things if you wanted to.

Name: Anonymous 2012-01-28 16:16

http://rosettacode.org/wiki/Category:Order
Order is a high-level, functional programming language implemented entirely using the C preprocessor. It provides a full programming language for metaprogramming in C (or any other environment where the C preprocessor can be used). A debugging environment and line-by-line evaluator are also included. Rather than building a library of macros to solve specific metaprogramming problems individually, Order-PP implements a continuation-based virtual machine which then interprets the high-level Order language.
Order is based primarily on lambda calculus, and is vaguely similar in semantics to languages such as ML or Scheme, offering first-class functions with partial application, lexical scope, first-class continuations, arbitrary-precision arithmetic, and built-in operators for compound types.
http://chaos-pp.cvs.sourceforge.net/viewvc/chaos-pp/order-pp/example/bottles.c?view=markup
ORDER_PP
(8let((8B, 8fn(8N,
        8cond((8greater(8N, 1),
            8separate(8N, 8quote(bottles)))
            (8equal(8N, 1),
            8quote(1 bottle))
            (8else,
            8quote(no more bottles))))),
    8for_each_in_range
    (8fn(8N,
        8print(8ap(8B, 8N) (of beer on the wall,) 8space
            8ap(8B, 8N) (of beer,) 8space
            (take one down, pass it around,) 8space
            8ap(8B, 8dec(8N)) (of beer on the wall.))),
    100, 1)))

Name: Anonymous 2012-01-28 16:17

YOU JEALOUS OF MY ABSTRACTFACTORYFACTORIES, FAGGOT? XD

Name: Anonymous 2012-01-28 16:32

>>23

it's like trying to look for traffic in the fog. I leik it!

Name: Anonymous 2012-01-28 16:56

>>1
Put that back in your pants you freak!

Name: Anonymous 2012-01-28 17:14

This is a copypasta, Morans.

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