[Swan-dev] const version of str_*()
Andrew Cagney
andrew.cagney at gmail.com
Sat Sep 14 14:55:40 UTC 2019
Lets assume:
id_t id1, id2 = ...
dn_t dn = ... // I don't think that exists
In the beginning we had the convention:
char b1[DN_LEN], b2[ID_LEN], b3[ID_LEN];
idtoa(&id1, b1, sizeof(b1));
idtoa(&id2, b2, ID_LEN);
dntoa(&dn, b3, DN_LEN);
printf("id1=%s dn=%s\ id2=%sn", b1, b2, b1);
But then we found that, over time, errors were creeping in, for instance:
- the wrong size was used when declaring the string buffer
- the wrong buffer and/or len was passed to *toa()
- the parameters on the print line didn't line up with the string
So things evolved:
- buf's type became strong
- the conversion routine returned a pointer to buf
and the code would now be written as:
id_t id1, id2 = ...
dn_t dn = ... // I don't think that exists
id_buf bid;
dn_buf bdn;
printf("id1=%s dn=%s\ id2=%sn", str_id(&id1,&bid), str_dn(&dn,
&bdn), str_id(id2, &bid))
which is a definite improvement.
But here's a different problem. We've code micro-optimized as follows:
char buf[ID_LEN]
idtoa(&id1, buf);
if (dbg) printf("id1 = %s\n", buf);
...
if (dbg) printf("id 2 = %s\n", buf);
presumably to minimise the number of string conversions. Except, with
certain irony, when !dbg and things matter, it will make an
unnecessary call.
I'm changing the code to:
if (dbg) {
id_buf b;
printf("id1 = %s\n", str_id(&id1, &b));
|
...
if (dbg) {
id_buf b;
printf("id2 = %s", str_id(&id2, &b));
}
so its more readable (the calls are on the debug path anyway).
However, I wonder if we we can tweak this further and eliminate the
need to declare the buffers; and the desire to optimise, vis:
id_buf id_str(const id_t *id) __attribute__((const))
...
printf("id1 = %s\n", id_str(&id1).buf);
printf("id2 = %s\n", id_str(&id2).buf);
printf("id1 = %s\n", id_str(&id1).buf);
https://lwn.net/Articles/285332/
- the need to declare the buffer is gone
- the compiler can eliminate duplicate calls
- the odds of passing wrong buffers is reduced further
it should also be efficient. Small structures are returned in 1-2
registers; and larger structures are returned by reference, the above
is compiled as:
id_buf tmp;
str_id(&tmp, &id)
tmp.buf
making it equivalent to the old str_id() call.
have fun,
Andrew
More information about the Swan-dev
mailing list