threads / discuss / 6879

Numeric constants as strings

Subject: Numeric constants as strings

## tl;dr

11 messages between Feb 19, 2007 and Feb 20, 2007.

replies: 10people: 6as markdown or json

Andy Parkins· Feb 19, 2007, 09:16 UTC · lore
Hello,

I'm working on bringing my hash width literals patch up to date now that 1.5.0 has passed. It's all been trivial apart from one line:

#define HASH_WIDTH_ASCII 40
-               printf("%-40s %s%s (%d subtrees)\n",
+               printf("%-" HASH_WIDTH_ASCII "s %s%s (%d subtrees)\n",

This compiles, but I suspect that it's not going to do what I want it to do. It's something I've never been able to do in C - how does one get quotes around a defined value? I don't really want to resort to

+               printf("%-*s %s%s (%d subtrees)\n", HASH_WIDTH_ASCII,
As that's a runtime change.
Andy
-- 
Dr Andy Parkins, M Eng (hons), MIEE
andyparkins@gmail.com
Junio C Hamano· Feb 19, 2007, 09:38 UTC · re: Andy Parkins · lore

Re: Numeric constants as strings

Andy Parkins <andyparkins@gmail.com> writes:
Show 10 quoted lines
> I'm working on bringing my hash width literals patch up to
> date now that 1.5.0 has passed.  It's all been trivial apart
> from one line:
>
> #define HASH_WIDTH_ASCII 40
> -               printf("%-40s %s%s (%d subtrees)\n",
> +               printf("%-" HASH_WIDTH_ASCII "s %s%s (%d subtrees)\n",
>
> This compiles, but I suspect that it's not going to do what I
> want it to do.

Doesn't writing "foo" "bar" (two string literals next to each other) tell the compiler to concatenate them?

Shawn O. Pearce· Feb 19, 2007, 09:49 UTC · re: Junio C Hamano · lore

Re: Numeric constants as strings

Junio C Hamano <junkio@cox.net> wrote:
Show 15 quoted lines
> Andy Parkins <andyparkins@gmail.com> writes:
> 
> > I'm working on bringing my hash width literals patch up to
> > date now that 1.5.0 has passed.  It's all been trivial apart
> > from one line:
> >
> > #define HASH_WIDTH_ASCII 40
> > -               printf("%-40s %s%s (%d subtrees)\n",
> > +               printf("%-" HASH_WIDTH_ASCII "s %s%s (%d subtrees)\n",
> >
> > This compiles, but I suspect that it's not going to do what I
> > want it to do.
> 
> Doesn't writing "foo" "bar" (two string literals next to each other)
> tell the compiler to concatenate them?

Yes, but here HASH_WIDTH_ASCII is a number... wtf is the compiler generating for the following?

  printf("%-" 40 "s %s%s (%d subtrees)\n",

I did not even realize that was legal C... Now if the 40 was in quotes (e.g. "40") then the concatenate rule would apply and we would get a nice argument to printf.

-- 
Shawn.
Matthieu Moy· Feb 19, 2007, 10:01 UTC · re: Shawn O. Pearce · lore

Re: Numeric constants as strings

"Shawn O. Pearce" <spearce@spearce.org> writes:
> I did not even realize that was legal C...  Now if the 40 was in
> quotes (e.g. "40") then the concatenate rule would apply and we
> would get a nice argument to printf.

I suppose the solution is to use #HASH_WIDTH_ASCII to tell the preprocessor to put the quotes around HASH_WIDTH_ASCII.

-- 
Matthieu
Andy Parkins· Feb 19, 2007, 10:54 UTC · re: Matthieu Moy · lore

Re: Numeric constants as strings

On Monday 2007 February 19 10:01, Matthieu Moy wrote:
Show 7 quoted lines
> "Shawn O. Pearce" <spearce@spearce.org> writes:
> > I did not even realize that was legal C...  Now if the 40 was in
> > quotes (e.g. "40") then the concatenate rule would apply and we
> > would get a nice argument to printf.
>
> I suppose the solution is to use #HASH_WIDTH_ASCII to tell the
> preprocessor to put the quotes around HASH_WIDTH_ASCII.

I'm afraid that only works when you're token pasting parameters in a #define macro.

For example:
 #define macro(x) "foo" #x "baz"

Then, macro(bar) expands to "foo" "bar" "baz". However, the following does not work:

 #define BAR bar
 #define macro "foo" #BAR "baz"
 
This is because BAR is not a macro parameter.  I've also tried it indirectly:
 #define BAR bar
 #define MAKESTRING(x) #x
 #define macro "foo" MAKESTRING(BAR) "baz"

But this expands to "foo" "BAR" "baz". Also wrong. Equally, using # anywhere but during a #define doesn't work, so I can't simply write

 printf( "%-" #HASH_WIDTH_ASCII "s", string );
Woe is me. :-(
Andy
-- 
Dr Andy Parkins, M Eng (hons), MIEE
andyparkins@gmail.com
Andy Parkins· Feb 19, 2007, 10:14 UTC · re: Junio C Hamano · lore

Re: Numeric constants as strings

On Monday 2007 February 19 09:38, Junio C Hamano wrote:
Show 9 quoted lines
> > #define HASH_WIDTH_ASCII 40
> > -               printf("%-40s %s%s (%d subtrees)\n",
> > +               printf("%-" HASH_WIDTH_ASCII "s %s%s (%d subtrees)\n",
> >
> > This compiles, but I suspect that it's not going to do what I
> > want it to do.
>
> Doesn't writing "foo" "bar" (two string literals next to each other)
> tell the compiler to concatenate them?
It's not a string literal though.
It's
 #define HASH_WIDTH_ASCII 40
rather than
 #define HASH_WIDTH_ASCII "40"
I'm wondering how to turn the first into the second using the preprocessor.
Andy
-- 
Dr Andy Parkins, M Eng (hons), MIEE
andyparkins@gmail.com
Junio C Hamano· Feb 19, 2007, 09:49 UTC · re: Andy Parkins · lore

Re: Numeric constants as strings

Andy Parkins <andyparkins@gmail.com> writes:
> I'm working on bringing my hash width literals patch up to
> date now that 1.5.0 has passed.

I do not want to risk discouraging public discussion on this topic, but I am not sure if this is really worth it.

It is not like if/when we find SHA-1 is inadequate we would just switch to SHA-256 and redefine HASH_BYTES from 20 to 32 and be done with it. With the need for backward compatibility, we would probably end up changing "unsigned char sha1[20]" to something that allows us to tell which hash function's result we are talking about, like:

	struct {
	       	enum { SHA_1, SHA_256 } type;
               	union {
                        unsigned char sha1[20];
                        unsigned char sha256[32];
		} u;
	};
Andy Parkins· Feb 19, 2007, 11:00 UTC · re: Junio C Hamano · lore

Re: Numeric constants as strings

On Monday 2007 February 19 09:49, Junio C Hamano wrote:
> I do not want to risk discouraging public discussion on this
> topic, but I am not sure if this is really worth it.
It's not primarily for that purpose, but rather to improve readability.
For example, this little bit of patch:
-       if (get_sha1_hex(buffer+5, tree_sha1) || buffer[45] != '\n')
+       if (get_sha1_hex(buffer+5, tree_sha1) || buffer[HASH_WIDTH_ASCII+5] != '\n')
                return objerror(&commit->object, "invalid 'tree' line format - bad sha1");
-       buffer += 46;
+       buffer += HASH_WIDTH_ASCII+6;
        while (!memcmp(buffer, "parent ", 7)) {
-               if (get_sha1_hex(buffer+7, sha1) || buffer[47] != '\n')
+               if (get_sha1_hex(buffer+7, sha1) || buffer[HASH_WIDTH_ASCII+7] != '\n')
                        return objerror(&commit->object, "invalid 'parent' line format - bad sha1");
-               buffer += 48;
+               buffer += HASH_WIDTH_ASCII+8;

Using HASH_WIDTH_ASCII+8 is much clearer for a reader to be able to understand intent than 48. Especially when the variables in question are called "buffer" it's harder to track what is being stored in the buffer without a named constant.

There are also a few other places where 20 is used and HASH_WIDTH_ASCII is not intended.

Andy
-- 
Dr Andy Parkins, M Eng (hons), MIEE
andyparkins@gmail.com
Mark Wooding· Feb 19, 2007, 10:04 UTC · re: Andy Parkins · lore

Re: Numeric constants as strings

Andy Parkins <andyparkins@gmail.com> wrote:
Show 6 quoted lines
> I'm working on bringing my hash width literals patch up to date now
> that 1.5.0 has passed.  It's all been trivial apart from one line:
>
> #define HASH_WIDTH_ASCII 40
> -               printf("%-40s %s%s (%d subtrees)\n",
> +               printf("%-" HASH_WIDTH_ASCII "s %s%s (%d subtrees)\n",
The standard two-step goes

#define STRINGIFY(foo) STRINGIFY_REALLY(foo) #define STRINGIFY_REALLY(foo) #foo

The purpose of STRINGIFY_REALLY is to macro-expand the argument foo. If you just invoked STRINGIFY_REALLY

  printf("%-" STRINGIFY_REALLY(HASH_WIDTH_ASCII) "s %s%s (%d subtrees)\n", 
you'd get
  printf("%-HASH_WIDTH_ASCIIs %s%s (%d subtrees)\n", ...
which is not what you wanted.  However,
  printf("%-" STRINGIFY(HASH_WIDTH_ASCII) "s %s%s (%d subtrees)\n", 
will do the right thing.
-- [mdw]
Andy Parkins· Feb 19, 2007, 11:02 UTC · re: Mark Wooding · lore

Re: Numeric constants as strings

On Monday 2007 February 19 10:04, Mark Wooding wrote:
> #define STRINGIFY(foo) STRINGIFY_REALLY(foo)
> #define STRINGIFY_REALLY(foo) #foo
>   printf("%-" STRINGIFY(HASH_WIDTH_ASCII) "s %s%s (%d subtrees)\n",
Ah ha!  Magical.  You've taught me something there.  Thanks.
Andy
-- 
Dr Andy Parkins, M Eng (hons), MIEE
andyparkins@gmail.com
Jakub Narebski· Feb 20, 2007, 13:06 UTC · re: Andy Parkins · lore

Re: Numeric constants as strings

Andy Parkins wrote:
Show 7 quoted lines
> On Monday 2007 February 19 10:04, Mark Wooding wrote:
> 
>> #define STRINGIFY(foo) STRINGIFY_REALLY(foo)
>> #define STRINGIFY_REALLY(foo) #foo
>>   printf("%-" STRINGIFY(HASH_WIDTH_ASCII) "s %s%s (%d subtrees)\n",
> 
> Ah ha!  Magical.  You've taught me something there.  Thanks.

This trick is in the cpp documentation. (cpp.info.gz)Stringification

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

← back to recent threads