473,382 Members | 1,692 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

What is considered macro abuse?

Hi all,

I was wondering what was considered macro abuse. Specifically I
implemented a key-value array (or dictionary), as per below. Notice
the use of macros - would that be considered alright?

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

#define START_ITERATE_KVA(kva) \
string_kva_node *node = kva->bol; \
while (node != kva->eol) {

#define END_ITERATE_KVA() \
node = node->next; \
}

typedef struct string_kva_node_struct {
char* key;
char* value;
struct string_kva_node_struct *next;
} string_kva_node;

typedef struct string_kva {
string_kva_node* bol;
string_kva_node* eol;
} string_kva;

string_kva* string_kva_init() {
string_kva *kva = (string_kva*)malloc(sizeof(string_kva));
kva->bol = (string_kva_node*)malloc(sizeof(string_kva_node));
kva->eol = kva->bol;
return kva;
}

void string_kva_add(string_kva *kva, char *key, char* value) {
// It just assigns the key & value reference, so don't go changing it
// afterwards - it's designed for speed here.
// And it will also allow you to add duplicate keys so be careful.

// If you need to set a key value that may or may not exist, use
// string_kva_set. This will guarantee uniqueness of keys.

kva->eol->key = key;
kva->eol->value = value;

kva->eol->next = (string_kva_node*)malloc(sizeof(string_kva_node));
kva->eol = kva->eol->next;
}

void string_kva_set(string_kva *kva, char *key, char* value) {
// find key and replace it
START_ITERATE_KVA(kva)
if (strcmp(node->key, key) == 0) {
node->value = value;
return;
}
END_ITERATE_KVA()

// if cannot find, then add as per usual
string_kva_add(kva, key, value);
}

char* string_kva_get(string_kva *kva, char* key) {
START_ITERATE_KVA(kva)
if (strcmp(node->key, key) == 0) {
return node->value;
}
END_ITERATE_KVA()
return NULL;
}

int string_kva_length(string_kva *kva) {
int length = 0;
START_ITERATE_KVA(kva)
length++;
END_ITERATE_KVA()
return length;
}

void string_kva_free(string_kva *kva) {
string_kva_node *node = kva->bol;
while (node != kva->eol) {
string_kva_node *next_node = node->next;
free(node);
node = next_node;
}
free(kva);
}

int main() {
string_kva* kva = string_kva_init();
printf("* Test first element\n");
string_kva_add(kva, "Ross", "Stevenson");
string_kva_add(kva, "Matthew", "Carrington");
string_kva_add(kva, "Lisa", "McQueen");
string_kva_add(kva, "Jerry", "Seinhauser");
string_kva_add(kva, "Wong", "Fei Hong");

printf("* Test first element\n");
assert(string_kva_get(kva, "Ross") == "Stevenson");

printf("* Test middle element\n");
assert(string_kva_get(kva, "Lisa") == "McQueen");

printf("* Test last element\n");
assert(string_kva_get(kva, "Wong") == "Fei Hong");

printf("* Test non-existent element\n");
assert(string_kva_get(kva, "Tara") == NULL);

printf("* Set duplicate key and test equality\n");
string_kva_set(kva, "Jerry", "Lee");
assert(string_kva_get(kva, "Jerry") == "Lee");

printf("* Test length\n");
assert(string_kva_length(kva) == 5);

printf("* Add another element after all that\n");
string_kva_add(kva, "Mini", "Me");

printf("* Test length again\n");
assert(string_kva_length(kva) == 6);

string_kva_free(kva);
}
Dec 12 '07 #1
9 2720
On Wed, 12 Dec 2007 02:57:12 -0800, Khookie wrote:
Hi all,

I was wondering what was considered macro abuse. Specifically I
implemented a key-value array (or dictionary), as per below. Notice
the use of macros - would that be considered alright?

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

#define START_ITERATE_KVA(kva) \
string_kva_node *node = kva->bol; \
while (node != kva->eol) {

#define END_ITERATE_KVA() \
node = node->next; \
}
<snip>
Can't say I like it.
In C90 at least, the caller would need to enclose START_ITERATE_KVA(),
END_ITERATE_KVA() pairs in {} or they are going to have syntax errors
(mixing declarations with code).
With nested loops you are going to have the inner node variable shadowing
the outer one and so there's no way to refer to the outer node in the
inner loop.
START_ITERATE_KVA(kva)
if ( !cond(kva, node))
{ continue;
}
/* code */
END_ITERATE_KVA()
would take a long time if cond were ever false.
These would be fixed by
#define START_ITERATE_KVA(kva,node) \
for((node)=(kva)->bol; (node)!=(kva)->eol; (node)=(node)->next)
and not bothering with END_ITERATE_KVA
but personally I'd prefer just to type the for.

Dec 12 '07 #2
Khookie wrote:
Hi all,

I was wondering what was considered macro abuse. [...]
The most abusive example I ever saw was an IOCCC entry
from quite a few years ago. The program had a few minor
portability issues, but was astonishingly flexible and
powerful, especially considering its brevity:

#include "/dev/tty"

--
Eric Sosman
es*****@ieee-dot-org.invalid
Dec 12 '07 #3
Khookie wrote:
Hi all,

I was wondering what was considered macro abuse. Specifically I
implemented a key-value array (or dictionary), as per below. Notice
the use of macros - would that be considered alright?

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

#define START_ITERATE_KVA(kva) \
string_kva_node *node = kva->bol; \
while (node != kva->eol) {

#define END_ITERATE_KVA() \
node = node->next; \
}
I've worked on codebases with this sort of thing, though I remember it
being more like this :-

#define START_ITERATE_KVA(kva) \
string_kva_node *node; \
for (node = kva->bol; node != kva->eol; node = node->next;) {

#define END_ITERATE_KVA() \
}

Of course for C90 compatibility, you'd go for :-

#define START_ITERATE_KVA(kva) \
{ \
string_kva_node *node; \
for (node = kva->bol; node != kva->eol; node = node->next;) {

#define END_ITERATE_KVA() \
}\
}

In some cases we had macros which depended on being nested within this
sort of structure, in much the same way as your string_kva_set function
has code which refers to variables it didn't appear to define.

I don't like it, as I feel it makes code less readable and less
maintainable.

I would be inclined to look for less ugly solutions, perhaps using a
call-back approach.
Dec 12 '07 #4
Khookie wrote:
>
Hi all,

I was wondering what was considered macro abuse.
http://groups.google.com/group/comp....37543775aa8567

I think there are 66 different functions defined here.
This really compiles!

/* pete-4.c */

#define F(Q,R,P) Q(int x){int i=x;while(i--)x=R(x,x);return x;}\
P(int L,int x){int i=x;if(L--)while(i--)x=P(L,x);return Q(x);}

#define Y(A,z,B,C,D,E,G,H,I,J,K,M,N,O,S,T,U,V,W)\
F(A,z,B)F(C,B,D)F(E,D,G)F(H,G,I)F(J,I,K)F(M,K,N)F( O,N,S)F(T,S,U)F(V,U,W)

Z(int L,int x)
{
int i = x;

if(L--)
while(i--)
x = Z(L,x);
return x << x;
}

Y(a,Z,b,c,d,e,g,h,X,j,k,m,n,o,s,t,u,v,w)
Y(Aa,w,Ba,Ca,Da,Ea,Ga,Ha,Ia,Ja,Ka,Ma,Na,Oa,Sa,Ta,U a,Va,Wa)
Y(Ab,Wa,Bb,Cb,Db,Eb,Gb,Hb,Ib,Jb,Kb,V,U,W,T,S,O,N,M )
F(A,M,B)
F(C,B,D)
F(E,D,G)
F(H,G,I)
F(J,I,K)

int main()
{
return K(99999,9);
}
--
pete
Dec 12 '07 #5
Le 12-12-2007, Khookie <ch********@gmail.coma écritÂ*:
Hi all,

I was wondering what was considered macro abuse. Specifically I
implemented a key-value array (or dictionary), as per below. Notice
the use of macros - would that be considered alright?
Yes it is to me.
But, why don't you use the well-known iterator paradim ?

kva_it it= kva_first( ... );
while( has_next(kva_it) ){
value= get_next(kva_it);
do_thing_on(value);
}

Marc Boyer
Dec 12 '07 #6
Marc Boyer <Ma********@enseeiht.yahoo.fr.invalidwrote:
Le 12-12-2007, Khookie <ch********@gmail.coma écritÂ*:
Hi all,

I was wondering what was considered macro abuse. Specifically I
implemented a key-value array (or dictionary), as per below. Notice
the use of macros - would that be considered alright?

Yes it is to me.
But, why don't you use the well-known iterator paradim ?

kva_it it= kva_first( ... );
while( has_next(kva_it) ){
value= get_next(kva_it);
do_thing_on(value);
}
Because
- it's not grammatical - you're using kva_it as both type and object
- the first kva doesn't get things done on it, which may make it jealous
- the following is more idiomatic, and IMO clearer:

for (kva_it kva=kva_first(); kva; kva=kva_next(kva) {
do_thing_on(kva_value(kva));
}

Richard
Dec 12 '07 #7
Le 12-12-2007, Richard Bos <rl*@hoekstra-uitgeverij.nla écritÂ*:
Marc Boyer <Ma********@enseeiht.yahoo.fr.invalidwrote:
>Le 12-12-2007, Khookie <ch********@gmail.coma écritÂ*:
Hi all,

I was wondering what was considered macro abuse. Specifically I
implemented a key-value array (or dictionary), as per below. Notice
the use of macros - would that be considered alright?

Yes it is to me.
But, why don't you use the well-known iterator paradim ?

kva_it it= kva_first( ... );
while( has_next(kva_it) ){
value= get_next(kva_it);
do_thing_on(value);
}

Because
- it's not grammatical - you're using kva_it as both type and object
Yes:
2,3s/kva_it/it/
- the first kva doesn't get things done on it, which may make it jealous
It depend the semantics of 'first'. It can be 'one-before-start', or
the real first element.
- the following is more idiomatic, and IMO clearer:

for (kva_it kva=kva_first(); kva; kva=kva_next(kva) {
do_thing_on(kva_value(kva));
}
Yes, this is another variation. I was using a Java-like concept,
but I wont defend mine more than your.
The only point I want to says is that the iterator concept
is better than the OP stange macros.
Dec 12 '07 #8
In article <of******************************@comcast.com>,
Eric Sosman <es*****@ieee-dot-org.invalidwrote:
>Khookie wrote:
>Hi all,

I was wondering what was considered macro abuse. [...]

The most abusive example I ever saw was an IOCCC entry
from quite a few years ago. The program had a few minor
portability issues, but was astonishingly flexible and
powerful, especially considering its brevity:

#include "/dev/tty"
Is that macro abuse, or more generic preprocessor abuse?
dave

Dec 12 '07 #9
On Dec 13, 1:57 am, r...@hoekstra-uitgeverij.nl (Richard Bos) wrote:
Marc Boyer <Marc.Bo...@enseeiht.yahoo.fr.invalidwrote:
Le 12-12-2007, Khookie <chris.k...@gmail.coma écrit :
Hi all,
I was wondering what was considered macro abuse. Specifically I
implemented a key-value array (or dictionary), as per below. Notice
the use of macros - would that be considered alright?
Yes it is to me.
But, why don't you use the well-known iterator paradim ?
kva_it it= kva_first( ... );
while( has_next(kva_it) ){
value= get_next(kva_it);
do_thing_on(value);
}

Because
- it's not grammatical - you're using kva_it as both type and object
- the first kva doesn't get things done on it, which may make it jealous
- the following is more idiomatic, and IMO clearer:

for (kva_it kva=kva_first(); kva; kva=kva_next(kva) {
do_thing_on(kva_value(kva));
}

Richard
Hi Richard

Yeah I like that - thanks man.

Chris
Dec 13 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

220
by: Brandon J. Van Every | last post by:
What's better about Ruby than Python? I'm sure there's something. What is it? This is not a troll. I'm language shopping and I want people's answers. I don't know beans about Ruby or have...
25
by: mike420 | last post by:
Ladies and Gentlemen, I present to you the final and ultimate proof of Python's brain-damage: As you may remember, flist = for i in range(3)
5
by: Steven T. Hatton | last post by:
I'm trying to figure out if this code (which I'm sure was written for a C compiler, could be considered legal C++. My confusion is from the last bit of code at the end. Could someone explain to me...
7
by: Newbie_sw2003 | last post by:
Where should I use them? I am giving you my understandings. Please correct me if I am wrong: MACRO: e.g.:#define ref-name 99 The code is substituted by the MACRO ref-name. So no overhead....
3
by: Charlie Zender | last post by:
Hi, I want to have a CPP macro that tests the value of a token and returns the string "No" if the token is undefined (or 0) and returns "Yes" if the token is defined (non-zero). Then I can...
3
by: Vish | last post by:
Please let me know how this macro works and please provide an example for, how to call it in my main() function. #include <stdio.h> #define MY_ENUM_BEGIN(etype) typedef enum etype##e { #define...
32
by: Stephen Horne | last post by:
I've been using Visual C++ 2003 for some time, and recently started working on making my code compile in GCC and MinGW. I hit on lots of unexpected problems which boil down to the same template...
5
by: =?GB2312?B?17/HvyBaaHVvLCBRaWFuZw==?= | last post by:
Hi, I would like to have someone comments on what's the best practice defining error codes in C. Here's what I think: solution A: using enum pros: type safe. better for debug (some debugger...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.