Dynamic Printf


D

dwgoldfarb

Hi,

I am writing an application which generates a Comma Separated Values
file with an unknown number of columns at compile time, but they will
be determined at the beginning of runtime prior to outputing the first
line. I could do something like:

int a, b, c, d, e, f;
char a_print, b_print, c_print, d_print, e_print, f_print; /* These
are set at the beginning of runtime. 1=print the value, 0 = no print
*/

main() {

/* These would be set in practice by CommandLine options -- this is
example */
a_print=c_print=e_print =1;
b_print=d_print=f_print=0;


while (1) {
/* get some data, process it, and set variables a,b.c,d,e,f as
needed */
if(a_print) printf("%d,"a);
if(b_print) printf("%d,"b);
if(c_print) printf("%d,"c);
if(d_print) printf("%d,"d);
if(e_print) printf("%d,"e);
if(f_print) printf("%d,"f);
printf("\n");
}
}

But this is slow as it will need to check a_print, b_print .... for
every line of output (potentially millions), and there will be one
call to printf for each column.

I have thought of constructing a printf format string "%d,%d,%d\n"
called "fmt" before the beginning of the while loop, and then call one
invocation of vprintf. The question I have is how to get a "va_list"



char fmt[2000]; /* probably be dynamically allocated, but this is
easier for example */

int a, b, c, d, e, f;
char a_print, b_print, c_print, d_print, e_print, f_print; /* These
are set at the beginning of runtime. 1=print the value, 0 = no print
*/

va_list ap; /* Or similar */

main() {

/* These would be set in practice by CommandLine options -- this is
example */
a_print=c_print=e_print =1;
b_print=d_print=f_print=0;

/* Setup format */
fmt[0]='\0';
if(a_print) strcat(fmt,"%d,");
if(b_print) strcat(fmt,"%d,");
if(c_print) strcat(fmt,"%d,");
if(d_print) strcat(fmt,"%d,");
if(e_print) strcat(fmt,"%d,");
if(f_print) strcat(fmt,"%d,");
strcat(fmt,"\n");

/* setup va_list ap ....here is where I am stumped */



while (1) {
/* get some data, process it, and set variables a,b.c,d,e,f as
needed */

vprintf(fmt,ap); /* ap points to the list of variables a,c,e
*/
}
}


Probably not possible, but any suggestions welcome....thanks
 
Ad

Advertisements

M

mark.bluemel

Hi,

I am writing an application which generates a Comma Separated Values
file with an unknown number of columns at compile time, but they will
be determined at the beginning of runtime prior to outputing the first
line.  I could do something like:

int a, b, c, d, e, f;
char a_print, b_print, c_print, d_print, e_print, f_print; /* These
are set at the beginning of runtime.  1=print the value, 0 = no print
*/

main() {

/* These would be set in practice by CommandLine options -- this is
example */
a_print=c_print=e_print =1;
b_print=d_print=f_print=0;

while (1) {
      /* get some data, process it, and set variables a,b.c,d,e,f as
needed */
     if(a_print) printf("%d,"a);
     if(b_print) printf("%d,"b);
     if(c_print) printf("%d,"c);
     if(d_print) printf("%d,"d);
     if(e_print) printf("%d,"e);
     if(f_print) printf("%d,"f);
    printf("\n");

}
}

I'm doubtful whether you can dynamically build a va_list.

I'd have thought arrays, or a more sophisticated data structure, would
be helpful here - an array or linked list of structures of the form :-
struct data_item {
int value;
int print_or_not;
}

might be a start. Then you print, or append into a string, on a per-
item basis.
 
G

Guest

On 22 Apr, 14:14, (e-mail address removed) wrote:

this is my third attempt to reply to this. I don't
think I understand your problem well enough.

I am writing an application which generates a Comma Separated Values
file with an unknown number of columns at compile time, but they will
be determined at the beginning of runtime prior to outputing the first
line. I could do something like:

int a, b, c, d, e, f;
char a_print, b_print, c_print, d_print, e_print, f_print; /* These
are set at the beginning of runtime. 1=print the value, 0 = no print
*/

to me this screams "use an array!"

#define MAX_COL 6
int columns [MAX_COL];
Bool column_present [MAX_COL];

main() {

/* These would be set in practice by CommandLine options -- this is
example */
a_print=c_print=e_print =1;
b_print=d_print=f_print=0;

while (1) {
/* get some data, process it, and set variables a,b.c,d,e,f as
needed */
if(a_print) printf("%d,"a);
if(b_print) printf("%d,"b);
if(c_print) printf("%d,"c);
if(d_print) printf("%d,"d);
if(e_print) printf("%d,"e);
if(f_print) printf("%d,"f);
printf("\n");

}

are they all present?

while (1) /* eek! infinite loop */
{
for (i = 0; i < MAX_COL; i++)
{
if (column_present)
printf ("%d,", column);
printf ("\n");
}
}

But this is slow as it will need to check a_print, b_print .... for
every line of output (potentially millions), and there will be one
call to printf for each column.

I thought of an array of function pointers but that doesn't quite seem
to
fit.

How about a list of columns to print?

int columns_to_print[MAX_COL];
int print_count = 0;

void add_column (int columns_to_print[], int *print_count, int
col_num)
{
assert (*print_count < MAX_COL);
columns_to_print [*print_count++] = col_num;
}

Build your table from the command line (real code more complicated)

add_column (columns_to_print, &print_count, 0);
add_column (columns_to_print, &print_count, 2);
add_column (columns_to_print, &print_count, 4);


Then printing consists of:-

for (i = 0; i < print_count; i++)
printf ("%d,", column [columns_to_print]);

This isn't real code. I haven't even compiled it.


I have thought of constructing a printf format string "%d,%d,%d\n"
called "fmt" before the beginning of the while loop, and then call one
invocation of vprintf. The question I have is how to get a "va_list"

char fmt[2000]; /* probably be dynamically allocated, but this is
easier for example */

int a, b, c, d, e, f;
char a_print, b_print, c_print, d_print, e_print, f_print; /* These
are set at the beginning of runtime. 1=print the value, 0 = no print
*/

va_list ap; /* Or similar */

main() {

/* These would be set in practice by CommandLine options -- this is
example */
a_print=c_print=e_print =1;
b_print=d_print=f_print=0;

/* Setup format */
fmt[0]='\0';
if(a_print) strcat(fmt,"%d,");
if(b_print) strcat(fmt,"%d,");
if(c_print) strcat(fmt,"%d,");
if(d_print) strcat(fmt,"%d,");
if(e_print) strcat(fmt,"%d,");
if(f_print) strcat(fmt,"%d,");
strcat(fmt,"\n");

/* setup va_list ap ....here is where I am stumped */

while (1) {
/* get some data, process it, and set variables a,b.c,d,e,f as
needed */

vprintf(fmt,ap); /* ap points to the list of variables a,c,e
*/

}
}

Probably not possible, but any suggestions welcome....thanks

I've got about the same number of calls but maybe a few tests
less. Depends how many columns you have and how clever
the compiler is with for loops.

I've assumed all your columns are integers. If not you
might well need the array of function pointers.


General Rule: if you see the same code being repeated
over and over again try and come up with a generalisation


--
Nick Keighley

Programming should never be boring, because anything
mundane and repetitive should be done by the computer.
~Alan Turing
 
J

James Kuyper

Hi,

I am writing an application which generates a Comma Separated Values
file with an unknown number of columns at compile time, but they will
be determined at the beginning of runtime prior to outputing the first
line. I could do something like:

int a, b, c, d, e, f;
char a_print, b_print, c_print, d_print, e_print, f_print; /* These
are set at the beginning of runtime. 1=print the value, 0 = no print
*/

main() {

/* These would be set in practice by CommandLine options -- this is
example */
a_print=c_print=e_print =1;
b_print=d_print=f_print=0;


while (1) {
/* get some data, process it, and set variables a,b.c,d,e,f as
needed */
if(a_print) printf("%d,"a);
if(b_print) printf("%d,"b);
if(c_print) printf("%d,"c);
if(d_print) printf("%d,"d);
if(e_print) printf("%d,"e);
if(f_print) printf("%d,"f);
printf("\n");
}
}

But this is slow as it will need to check a_print, b_print .... for
every line of output (potentially millions), and there will be one
call to printf for each column.

I have thought of constructing a printf format string "%d,%d,%d\n"
called "fmt" before the beginning of the while loop, and then call one
invocation of vprintf. The question I have is how to get a "va_list"



char fmt[2000]; /* probably be dynamically allocated, but this is
easier for example */

int a, b, c, d, e, f;
char a_print, b_print, c_print, d_print, e_print, f_print; /* These
are set at the beginning of runtime. 1=print the value, 0 = no print
*/

va_list ap; /* Or similar */

main() {

/* These would be set in practice by CommandLine options -- this is
example */
a_print=c_print=e_print =1;
b_print=d_print=f_print=0;

Rather than a va_list, what you should use is one additional level of
indirection:

int *argptr[6];
int argcnt = 0;
int dummy = INT_MIN;
/* A value likely to catch your attention,
* if accidentally printed */
/* Setup format */
fmt[0]='\0';

if(a_print) strcat(fmt,"%d,");
if(b_print) strcat(fmt,"%d,");
if(c_print) strcat(fmt,"%d,");
if(d_print) strcat(fmt,"%d,");
if(e_print) strcat(fmt,"%d,");
if(f_print) strcat(fmt,"%d,");

Replace with:
if(a_print) {
strcat(fmt, "%d,");
argptr[argcnt++] = &dummy;
}

Repeat for each of the other variables. Then:

while(argcnt < 6)
argptr[argcnt++] = &f;

Note: it doesn't matter what those extra pointers point at, as long as
it contains a valid int value.

strcat(fmt,"\n"); ....
while (1) {
/* get some data, process it, and set variables a,b.c,d,e,f as
needed */

printf(fmt, *argptr[0], *argptr[1] /* etc */);


Note, this extra level of indirection has it's own associated costs.
Check to make sure whether it's actually faster than the using multiple
printf()s.
 
P

Paul Hsieh

I am writing an application which generates a Comma Separated Values
file with an unknown number of columns at compile time, but they will
be determined at the beginning of run-time prior to outputting the
first line.  I could do something like:

int a, b, c, d, e, f;
char a_print, b_print, c_print, d_print, e_print, f_print; /* These
are set at the beginning of runtime.  1=print the value, 0 = no print
*/

main() {

/* These would be set in practice by CommandLine options -- this is
example */
a_print=c_print=e_print =1;
b_print=d_print=f_print=0;

while (1) {
      /* get some data, process it, and set variables a,b.c,d,e,f as
needed */
     if(a_print) printf("%d,"a);
     if(b_print) printf("%d,"b);
     if(c_print) printf("%d,"c);
     if(d_print) printf("%d,"d);
     if(e_print) printf("%d,"e);
     if(f_print) printf("%d,"f);
    printf("\n");

}
}

But this is slow as it will need to check a_print, b_print .... for
every line of output (potentially millions), and there will be one
call to printf for each column.

You have a very disproportionate idea of what is slow or not. The
real cost is the overhead of calling printf, having it re-parse the
format string then call the number to string converter and pump it out
to the output device. An if-statement, by comparison costs nothing.

There are many approaches to this, but let me just give you one.

#define glue2_aux(x,y) x ## y
#define glue2(x,y) glue2_aux(x,y)
#define FMT_d(X) glue2(FMT_d_AUX_,X)
#define FMT_d_AUX_0 ""
#define FMT_d_AUX_1 "%d,"
#define ARG(X,y) glue2(ARG_AUX_,X)(y)
#define ARG_AUX_0(x)
#define ARG_AUX_1(x) ,x

#define OUTLINE6(idx,A,a,B,b,C,c,D,d,E,e,F,f) PFX(idx) printf \
(FMT_d(A) FMT_d(B) FMT_d(C) FMT_d(D) FMT_d(E) FMT_d(F) \
ARG(A,a) ARG(B,b) ARG(C,c) ARG(D,d) ARG(E,e) ARG(F,f)); AFX(idx)

#define XOUTLINE5(idx,A,a,B,b,C,c,D,d,E,e,f)\
OUTLINE6(idx, A,a,B,b,C,c,D,d,E,e,0,f) \
OUTLINE6(idx+1,A,a,B,b,C,c,D,d,E,e,0,f)

#define XOUTLINE4(idx,A,a,B,b,C,c,D,d,e,f) \
XOUTLINE5(idx, A,a,B,b,C,c,D,d,0,e,f) \
XOUTLINE5(idx+2,A,a,B,b,C,c,D,d,1,e,f)

#define XOUTLINE3(idx,A,a,B,b,C,c,d,e,f) \
XOUTLINE4(idx, A,a,B,b,C,c,0,d,e,f) \
XOUTLINE4(idx+4,A,a,B,b,C,c,1,d,e,f)

#define XOUTLINE2(idx,A,a,B,b,c,d,e,f) \
XOUTLINE3(idx, A,a,B,b,0,c,d,e,f) \
XOUTLINE3(idx+8,A,a,B,b,1,c,d,e,f)

#define XOUTLINE1(idx,A,a,b,c,d,e,f) \
XOUTLINE2(idx, A,a,0,b,c,d,e,f) \
XOUTLINE2(idx+16,A,a,1,b,c,d,e,f)

#define OUTLINE(a,b,c,d,e,f) \
XOUTLINE1(0, 0,a,b,c,d,e,f) \
XOUTLINE1(32,1,a,b,c,d,e,f)

#define PFX(idx) case (idx):
#define AFX(idx) break;

void outputLine6 (int mode, int a, int b, int c, int d, int e, int f)
{
switch (mode) {
OUTLINE(a,b,c,d,e,f)
}
}

I just spit this out, so there are likely compile errors out the
wazzoo, but you get the idea. "mode" is a 6-bit selector where each
bit corresponds to the output or not output of the ordered parameter.

I find that pushing the pre-processor is highly under utilized in C.
You can do surprisingly powerful things like this if you put your mind
to it.

If performance is really your beef then you really have to try to
improve on the performance of printf() itself. In this case, rather
than simply calling printf () with its set of parameters, you would
want to write your own kind of integer to ASCII routine that you would
emit selectively similarly to the above. The main benefit of that
being that you avoid the redundant printf format string parsing, and
you have the opportunity to inline and possibly blasting the result
from a single accumulated buffer in a single IO call.
 
B

BartC

There are many approaches to this, but let me just give you one.

#define glue2_aux(x,y) x ## y
#define glue2(x,y) glue2_aux(x,y)
#define FMT_d(X) glue2(FMT_d_AUX_,X)
#define FMT_d_AUX_0 ""
#define FMT_d_AUX_1 "%d,"
#define ARG(X,y) glue2(ARG_AUX_,X)(y)
#define ARG_AUX_0(x)
#define ARG_AUX_1(x) ,x

#define OUTLINE6(idx,A,a,B,b,C,c,D,d,E,e,F,f) PFX(idx) printf \
(FMT_d(A) FMT_d(B) FMT_d(C) FMT_d(D) FMT_d(E) FMT_d(F) \
ARG(A,a) ARG(B,b) ARG(C,c) ARG(D,d) ARG(E,e) ARG(F,f)); AFX(idx) .....
#define PFX(idx) case (idx):
#define AFX(idx) break;
I find that pushing the pre-processor is highly under utilized in C.

For good reasons. You're trading straightforward C code for a different
language and using that to write difficult-to-follow and far too clever
code.
You can do surprisingly powerful things like this if you put your mind
to it.

I don't dispute that.
 
Ad

Advertisements

P

Paul Hsieh

For good reasons. You're trading straightforward C code for a
different language and using that to write difficult-to-follow and
far too clever code.

This counts as a good reason? Have you looked at how va_arg() is
defined in your compiler? I don't consider "skill level" for the code
a good reason to omit C code. C is not a complicated enough language
for anything written it to be undecipherable with sufficient effort.
If you can simplify it then do so, but if you can't then do what it
takes.

The pre-processor is part of the C language and the OP's question is
not marginal and it can be solved by the pre-processor. I find your
objection to be specious.
 
B

BartC

Paul said:
This counts as a good reason? Have you looked at how va_arg() is
defined in your compiler? I don't consider "skill level" for the code
a good reason to omit C code. C is not a complicated enough language
for anything written it to be undecipherable with sufficient effort.
If you can simplify it then do so, but if you can't then do what it
takes.

The pre-processor is part of the C language and the OP's question is
not marginal and it can be solved by the pre-processor. I find your
objection to be specious.

I thought the original problem just needed an array or two and a loop.

But even the OP's code was simpler (because a lot of it repeats) than the
macro solution.

With the macro (which I've tried and it sort of works), it does actually
generate 64 lots of calls to printf().

If it was a necessity to make only a single printf call per dataset, then I
think it can be coded without macros and with only 6 actual printf calls in
the source.

(And we don't know if there is in fact only a maximum of 6 columns, or if
that was an example. If the maximum number of columns was much higher, then
the macro solution would run into trouble.)
 
L

Leo

Hi,

I am writing an application which generates a Comma Separated Values
file with an unknown number of columns at compile time, but they will
be determined at the beginning of runtime prior to outputing the first
line. I could do something like:
main() {

/* These would be set in practice by CommandLine options -- this is
example */
a_print=c_print=e_print =1;
b_print=d_print=f_print=0;

/* Setup format */
fmt[0]='\0';
if(a_print) strcat(fmt,"%d,");
if(b_print) strcat(fmt,"%d,");
if(c_print) strcat(fmt,"%d,");
if(d_print) strcat(fmt,"%d,");
if(e_print) strcat(fmt,"%d,");
if(f_print) strcat(fmt,"%d,");
strcat(fmt,"\n");

/* setup va_list ap ....here is where I am stumped */
It is possible to setup a va_list manually.
The parameter pass mechanism is nothing special for a variable-length
parameter function. So the va_list variable is just a pointer points
to the end of last known parameter.

The following code should work for you.
--------------
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

int main() {
int a,b,c,d,e,f;
int a_print, b_print, c_print, d_print, e_print, f_print;
char fmt[100];
int v_arg[100];
int* tmp = v_arg;
void* ap = v_arg;

a_print = c_print = e_print = 1;
b_print = d_print = f_print = 0;
a = b = c = d = e = f = 1;
/* Setup format */
fmt[0]='\0';
if(a_print) {strcat(fmt,"%d,"); *tmp++ = a;}
if(b_print) {strcat(fmt,"%d,"); *tmp++ = b;}
if(c_print) {strcat(fmt,"%d,"); *tmp++ = c;}
if(d_print) {strcat(fmt,"%d,"); *tmp++ = d;}
if(e_print) {strcat(fmt,"%d,"); *tmp++ = e;}
if(f_print) {strcat(fmt,"%d,"); *tmp++ = f;}
strcat(fmt,"\n");

vprintf(fmt, ap);
return 0;
}


Leo
 
N

Nate Eldredge

Leo said:
Hi,

I am writing an application which generates a Comma Separated Values
file with an unknown number of columns at compile time, but they will
be determined at the beginning of runtime prior to outputing the first
line. I could do something like:
main() {

/* These would be set in practice by CommandLine options -- this is
example */
a_print=c_print=e_print =1;
b_print=d_print=f_print=0;

/* Setup format */
fmt[0]='\0';
if(a_print) strcat(fmt,"%d,");
if(b_print) strcat(fmt,"%d,");
if(c_print) strcat(fmt,"%d,");
if(d_print) strcat(fmt,"%d,");
if(e_print) strcat(fmt,"%d,");
if(f_print) strcat(fmt,"%d,");
strcat(fmt,"\n");

/* setup va_list ap ....here is where I am stumped */
It is possible to setup a va_list manually.
The parameter pass mechanism is nothing special for a variable-length
parameter function. So the va_list variable is just a pointer points
to the end of last known parameter.

The following code should work for you.
--------------
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

int main() {
int a,b,c,d,e,f;
int a_print, b_print, c_print, d_print, e_print, f_print;
char fmt[100];
int v_arg[100];
int* tmp = v_arg;
void* ap = v_arg;

a_print = c_print = e_print = 1;
b_print = d_print = f_print = 0;
a = b = c = d = e = f = 1;
/* Setup format */
fmt[0]='\0';
if(a_print) {strcat(fmt,"%d,"); *tmp++ = a;}
if(b_print) {strcat(fmt,"%d,"); *tmp++ = b;}
if(c_print) {strcat(fmt,"%d,"); *tmp++ = c;}
if(d_print) {strcat(fmt,"%d,"); *tmp++ = d;}
if(e_print) {strcat(fmt,"%d,"); *tmp++ = e;}
if(f_print) {strcat(fmt,"%d,"); *tmp++ = f;}
strcat(fmt,"\n");

vprintf(fmt, ap);
return 0;
}

Not so much. On my machine this code outputs

490024,16387,16387,

The format of va_list varies between systems, depending on the parameter
passing conventions. You're not likely to be able to construct one by
hand in a portable manner.

If the data you want to output don't come as arguments to a varargs
function, then vprintf is not the right tool to output them. The
standard C library doesn't provide a function that works well for this
situation, so you have to come up with your own. I would either printf
the variables one at a time, or get a free implementation of printf and
adapt it to handle variables passed in an array or something similar.
 
D

dwgoldfarb

Thanks to all the replies!

In fact the OP was just an example. My program will most likely
output a maximum of 120 columns over 30 million lines of output which
would amount to 3.6 billion calls to printf.

I did take Eric's suggestion and coded an example in three different
ways. Using 83 columns and 1.2 millions lines of output, my tests
show about
-- 34 seconds for a version of the program coded as one big printf
(all 83 columns at once)
-- 40 seconds for a version with 15 if(printflag) printf combinations
(each printf outputs 3-12 fields)
-- 56 secs for a version where there are 83 if(printflag) printf
combinations (each printf outputs one field).


My favorite solution above was James K. solution to use an array of
pointers as arguments to printf:

printf(fmt, *argptr[0], *argptr[1] /* etc */);

I have coded this up and currently call printf with 150 arguments, but
the last 50 are not used (yet). The "fmt" argument determines how
many of the subsequent arguments are used. One limitation of this is
that the "pointer to char string" needs to be the same number of bytes
as a "unsigned long" in the machine architecture compiled. Also, the
only formats that can be in the "fmt" string are %s, %ld, %lx (or
other "long" formats).

After coding it and comparing the runtime to the other examples above,
I found that the time was around 38 seconds.

Regarding the suggestion to use MACROs, I find that while the solution
is very clever, it will be almost impossible to debug and maintain. I
have worked on a system in the past where developers of one subsystem
designed their own MACRO language to make the code pretty. However
coredumps and hex datablock dumps and register dumps made it next to
impossible to figure out which byte was with this datablock. I
suggest MACROs should be used for simply making constants clear. If
you wish to optimize code with "inline" functions let the compiler do
that for you.

Thanks for the suggestions!
 
Ad

Advertisements

P

Paul Hsieh

In fact the OP was just an example.  My program will most likely
output a maximum of 120 columns over 30 million lines of output which
would amount to 3.6 billion calls to printf.

120 columns!?!? Wow! Well, that changes things. In that case,
internal storage, and inter-column accumulation overhead is a second-
order consideration after you deal with the printf() cost.

If you were to use my technique you would, first of all, want to go in
powers of 4 or 8, not 2, and you would probably want to write a
program, just to output the code.
I did take Eric's suggestion and coded an example in three different
ways.  Using 83 columns and 1.2 millions lines of output, my tests
show about
-- 34 seconds for a version of the program coded as one big printf
(all 83 columns at once)
-- 40 seconds for a version with 15 if(printflag) printf combinations
(each printf outputs 3-12 fields)
-- 56 secs for a version where there are 83 if(printflag) printf
combinations (each printf outputs one field).

Right. In all these cases you are paying the cost of calling printf()
format parsing proportional to the length of the string. What you
should really do, is accumulate into a string and use the [f]puts()
function, so that you are primarily only paying the cost of IO and not
format parsing.
My favorite solution above was James K. solution to use an array of
pointers as arguments to printf:

         printf(fmt, *argptr[0], *argptr[1] /* etc */);

I have coded this up and currently call printf with 150 arguments, but
the last 50 are not used (yet).  The "fmt" argument determines how
many of the subsequent arguments are used. One limitation of this is
that the "pointer to char string" needs to be the same number of bytes
as a "unsigned long" in the machine architecture compiled.

Which is pretty ridiculous if you are on a 64-bit machine.
[...] Also, the
only formats that can be in the "fmt" string are %s, %ld, %lx (or
other "long" formats).

If you are limiting your types, you might as well write your own
format parser; you can easily do better than the performance of printf
().
After coding it and comparing the runtime to the other examples above,
I found that the time was around 38 seconds.

Regarding the suggestion to use MACROs, I find that while the solution
is very clever, it will be almost impossible to debug and maintain.

By itself, that's true. I have written a *LOT* of code using this
technique, and of course, you are right in that it presents very
significant *INITIAL* debugging challenges. The approach I found for
dealing with it is to create, along side it, a function version of the
macro as well, while I am developing and debugging the code. Once I
and done debugging it, I then insert the macro version, and verify
that it behaves the same, and then make it selectable between the two,
so I can go back and forth as necessary.
[...] I
have worked on a system in the past where developers of one subsystem
designed their own MACRO language to make the code pretty.  However
coredumps and hex datablock dumps and register dumps made it next to
impossible to figure out which byte was with this datablock.  I
suggest MACROs should be used for simply making constants clear.  If
you wish to optimize code with "inline" functions let the compiler do
that for you.

Yes, I know. The "function based alternative" was enough for me to
convince my coworkers that my code was not undebuggable and they
bought into it as a result.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top