Need to learn C, best books?
Andy Wardley
abw at wardley.org
Wed Oct 24 20:31:22 BST 2007
Andy Armstrong wrote:
> size_t sl = strlen(somestring); /* get length of string */
>
> would be bad :)
Indeed. A good rule of thumb is to explain why you're doing something,
not what you're doing.
For example:
size_t sl = strlen(somestring) + 1; /* don't forget the terminating '\0' */
char *ptr = (char *) malloc(s1);
Another good rule is to make the purpose of the code blindingly obvious so
you don't need to explain it. But that's easier said than done...
As for learning C/XS you might like to take a look at the Perl and XS
implementations of Template::Stash in the Template Toolkit
(lib/Template/Stash.pm and xs/Stash.xs). I can't vouch for the quality
of the code and because it's a very time critical part of TT there are
trade-offs between clarity and speed. But you get to look at Perl and XS
implementations side-by-side so you can see how much nicer it is to write
Perl code than XS.
For example, in Perl:
if (ref $item eq 'ARRAY') {
# array slice
return [@$root[@$item]];
}
And in XS:
/* try array slice */
if (SvROK(key_sv) && SvTYPE(SvRV(key_sv)) == SVt_PVAV) {
AV *a_av = newAV();
AV *k_av = (AV *) SvRV(key_sv);
AV *r_av = (AV *) SvRV(root);
I32 i;
SV **svp;
for (i = 0; i <= av_len(k_av); i++) {
if ((svp = av_fetch(k_av, i, FALSE))) {
SvGETMAGIC(*svp);
if (looks_like_number(*svp) &&
(svp = av_fetch(r_av, SvIV(*svp), FALSE))) {
SvGETMAGIC(*svp);
av_push(a_av, SvREFCNT_inc(*svp));
}
}
}
return sv_2mortal(newRV_noinc((SV *) a_av));
}
I rather dread receiving patches for the Stash because the patcher inevitably
patches the Perl version and leaves the XS patch as an exercise for the
reader (i.e. me). Although I must admit, I do quite like hacking C code in a
sick and twisted maze of passages all alike kinda way. But it's the reference
counting that always gets me in XS. I used the "random monkeys until it no
longer leaks memory pr dumps core" approach :-)
A
More information about the london.pm
mailing list