Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #12850 > unrolled thread
| Started by | Andrey Vul <andrey.vul@gmail.com> |
|---|---|
| First post | 2011-11-07 10:53 -0800 |
| Last post | 2011-11-07 16:46 -0800 |
| Articles | 14 — 7 participants |
Back to article view | Back to comp.lang.c
A variation of # Andrey Vul <andrey.vul@gmail.com> - 2011-11-07 10:53 -0800
Re: A variation of # Ian Collins <ian-news@hotmail.com> - 2011-11-08 07:59 +1300
Re: A variation of # Andrey Vul <andrey.vul@gmail.com> - 2011-11-07 11:11 -0800
Re: A variation of # James Kuyper <jameskuyper@verizon.net> - 2011-11-07 15:07 -0500
Re: A variation of # lawrence.jones@siemens.com - 2011-11-07 17:53 -0500
Re: A variation of # James Kuyper <jameskuyper@verizon.net> - 2011-11-07 18:31 -0500
Re: A variation of # lawrence.jones@siemens.com - 2011-11-08 09:16 -0500
Re: A variation of # Thad Smith <ThadSmith@acm.org> - 2011-11-07 19:51 -0700
Re: A variation of # Harald van Dijk <truedfx@gmail.com> - 2011-11-08 09:01 -0800
Re: A variation of # James Kuyper <jameskuyper@verizon.net> - 2011-11-08 12:15 -0500
Re: A variation of # Andrey Vul <andrey.vul@gmail.com> - 2011-11-07 17:32 -0800
Re: A variation of # James Kuyper <jameskuyper@verizon.net> - 2011-11-07 21:17 -0500
Re: A variation of # Andrey Vul <andrey.vul@gmail.com> - 2011-11-07 11:08 -0800
Re: A variation of # Peter Nilsson <airia@acay.com.au> - 2011-11-07 16:46 -0800
| From | Andrey Vul <andrey.vul@gmail.com> |
|---|---|
| Date | 2011-11-07 10:53 -0800 |
| Subject | A variation of # |
| Message-ID | <8f2cadb2-614d-4754-8bc3-bb7c063524ae@c16g2000pre.googlegroups.com> |
To stringify pp-constants, we use #foo notation. Is there a method of charifying constants defined on the preprocessor level, assuming the precondition of length being 1 is true? That is, does there exist a pp-builtin CHARIFY such that CHARIFY(x) = 'x' ?
[toc] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-11-08 07:59 +1300 |
| Message-ID | <9hqo41F4bgU2@mid.individual.net> |
| In reply to | #12850 |
On 11/ 8/11 07:53 AM, Andrey Vul wrote: > To stringify pp-constants, we use #foo notation. > Is there a method of charifying constants defined on the preprocessor > level, assuming the precondition of length being 1 is true? > That is, does there exist a pp-builtin CHARIFY such that CHARIFY(x) = > 'x' ? Something like #define CHAR(x) #x [0] ? -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Andrey Vul <andrey.vul@gmail.com> |
|---|---|
| Date | 2011-11-07 11:11 -0800 |
| Message-ID | <73822171-7a92-4420-9eea-e74bbeda1ff8@x28g2000prb.googlegroups.com> |
| In reply to | #12851 |
On Nov 7, 1:59 pm, Ian Collins <ian-n...@hotmail.com> wrote: > On 11/ 8/11 07:53 AM, Andrey Vul wrote: > > > To stringify pp-constants, we use #foo notation. > > Is there a method of charifying constants defined on the preprocessor > > level, assuming the precondition of length being 1 is true? > > That is, does there exist a pp-builtin CHARIFY such that CHARIFY(x) = > > 'x' ? > > Something like > > #define CHAR(x) #x [0] > Can't be used inside switch.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2011-11-07 15:07 -0500 |
| Message-ID | <4EB83A82.1080100@verizon.net> |
| In reply to | #12852 |
On 11/07/2011 02:11 PM, Andrey Vul wrote:
> On Nov 7, 1:59 pm, Ian Collins <ian-n...@hotmail.com> wrote:
>> On 11/ 8/11 07:53 AM, Andrey Vul wrote:
>>
>>> To stringify pp-constants, we use #foo notation.
>>> Is there a method of charifying constants defined on the preprocessor
>>> level, assuming the precondition of length being 1 is true?
I presume there's some reason why the constants cannot, themselves, be
defined as character constants?
>>> That is, does there exist a pp-builtin CHARIFY such that CHARIFY(x) =
>>> 'x' ?
>>
>> Something like
>>
>> #define CHAR(x) #x [0]
>>
>
> Can't be used inside switch.
There's no simple way I can think of to define a macro that generates a
character constant whose value depends upon the expansion of another
macro. I did, however, manage to come up with this ugly monstrosity,
which cannot possibly qualify as "simple", which I've inserted into some
test code:
#include <stdlib.h>
#define TRICAT(a, b, c) a ## b ## c
#define CHAR(a, b, c) TRICAT(a, b, c)
#define CASE1 x
int main(int argc, char *argv[])
{
if(argc <= 1)
return EXIT_FAILURE;
switch (*argv[1])
{
case CHAR('
, CASE1, '
): break;
default:
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}
The key thing that makes this work is that ' immediately followed by a
newline is not recognized as any other type of pre-processing token, so
it counts as a preprocessing token of it's own, under the classification
"each non-white-space character that cannot be one of the above" (6.4p1).
The two-level expansion allows CASE1 to be expanded to x before being
concatenated with the ' tokens.
If you can convince the relevant person to define the relevant constants
as character constants, that would make things a lot easier.
[toc] | [prev] | [next] | [standalone]
| From | lawrence.jones@siemens.com |
|---|---|
| Date | 2011-11-07 17:53 -0500 |
| Message-ID | <v44mo8-lfm.ln1@jones.homeip.net> |
| In reply to | #12855 |
James Kuyper <jameskuyper@verizon.net> wrote:
>
> #include <stdlib.h>
> #define TRICAT(a, b, c) a ## b ## c
> #define CHAR(a, b, c) TRICAT(a, b, c)
>
> #define CASE1 x
>
...
> case CHAR('
> , CASE1, '
> ): break;
Nice try, but no cigar. The ## operator requires that the result be a
valid pp-token and, depending on the order in which the operators are
evaluated, you either end up with 'x or x', neither of which are valid
pp-tokens.
--
Larry Jones
You know how Einstein got bad grades as a kid? Well MINE are even WORSE!
-- Calvin
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2011-11-07 18:31 -0500 |
| Message-ID | <4EB86A45.7030305@verizon.net> |
| In reply to | #12859 |
On 11/07/2011 05:53 PM, lawrence.jones@siemens.com wrote:
> James Kuyper <jameskuyper@verizon.net> wrote:
>>
>> #include <stdlib.h>
>> #define TRICAT(a, b, c) a ## b ## c
>> #define CHAR(a, b, c) TRICAT(a, b, c)
>>
>> #define CASE1 x
>>
> ...
>> case CHAR('
>> , CASE1, '
>> ): break;
>
> Nice try, but no cigar. The ## operator requires that the result be a
> valid pp-token and, depending on the order in which the operators are
> evaluated, you either end up with 'x or x', neither of which are valid
> pp-tokens.
I hadn't considered that issue, but taking a look at 6.10.3.3p3, I found
that it says "each each instance of a ## preprocessing token
in the replacement list (not from an argument) is deleted and the
preceding preprocessing token is concatenated with the following
preprocessing token. ... If the result is not a valid preprocessing
token, the behavior is undefined." It seems to me ambiguous whether "the
result" it refers to is the result of each concatenation, or the
combined result of all of the concatenations.
I'm not going to argue strongly over this. I think this is a horribly
ugly solution to what should be a simple problem; if it actually fails
to be a solution by reason of having undefined behavior, I'm not going
to lose any sleep over it.
[toc] | [prev] | [next] | [standalone]
| From | lawrence.jones@siemens.com |
|---|---|
| Date | 2011-11-08 09:16 -0500 |
| Message-ID | <n6qno8-etn.ln1@jones.homeip.net> |
| In reply to | #12860 |
James Kuyper <jameskuyper@verizon.net> wrote: > > I hadn't considered that issue, but taking a look at 6.10.3.3p3, I found > that it says "each each instance of a ## preprocessing token > in the replacement list (not from an argument) is deleted and the > preceding preprocessing token is concatenated with the following > preprocessing token. ... If the result is not a valid preprocessing > token, the behavior is undefined." It seems to me ambiguous whether "the > result" it refers to is the result of each concatenation, or the > combined result of all of the concatenations. I think it's pretty clear from context that it's talking about each replacement individually. For a token-based preprocessor, you either need each result to be a token or you need the concept of executing a bunch of operators in parallel (which we don't have in C). -- Larry Jones Hey! What's the matter? Can't you take a joke?! It was a JOKE! -- Calvin
[toc] | [prev] | [next] | [standalone]
| From | Thad Smith <ThadSmith@acm.org> |
|---|---|
| Date | 2011-11-07 19:51 -0700 |
| Message-ID | <j9a5g0$5b0$1@speranza.aioe.org> |
| In reply to | #12859 |
On 11/7/2011 3:53 PM, lawrence.jones@siemens.com wrote:
> James Kuyper<jameskuyper@verizon.net> wrote:
>>
>> #include<stdlib.h>
>> #define TRICAT(a, b, c) a ## b ## c
>> #define CHAR(a, b, c) TRICAT(a, b, c)
>>
>> #define CASE1 x
>>
> ...
>> case CHAR('
>> , CASE1, '
>> ): break;
>
> Nice try, but no cigar. The ## operator requires that the result be a
> valid pp-token and, depending on the order in which the operators are
> evaluated, you either end up with 'x or x', neither of which are valid
> pp-tokens.
So if we are concatenating 3 pp-tokens, not only do the individual items (a,b,c)
and the final concatenation need to be valid pp-tokens, but also all potential
_intermediates_, as determined by the unspecified processor order. That seems a
needless and complicating restriction.
If I understand correctly, CHAR(<,<,=) will work because both << and <= are
valid pp-tokens, but CHAR(., ., .) will not because .. isn't.
Finally the result of CHAR(%:, %, :) is undefined/unspecified, since order of
concatenation determines whether the intermediate is %:% ## : or %: ## %: where
%:% is not a pp-token. I noticed that CHAR(C,3,_) is only required to work
because 3_ is a valid pp-number!
It seems that the rule could be replaced by a greedy algorithm that concatenates
all ##-connected pp-tokens before requiring a pp-token result. As far as I can
see such replacement would have no incompatibility with the current standard and
would add little additional wording and processing. It would simplify the
concept by not relying on happenstance intermediates as noted above.
Thad
[toc] | [prev] | [next] | [standalone]
| From | Harald van Dijk <truedfx@gmail.com> |
|---|---|
| Date | 2011-11-08 09:01 -0800 |
| Message-ID | <e5604f05-1376-4a92-9c17-51cc92b3ff0b@d17g2000yql.googlegroups.com> |
| In reply to | #12859 |
On Nov 7, 11:53 pm, lawrence.jo...@siemens.com wrote:
> James Kuyper <jameskuy...@verizon.net> wrote:
> > #include <stdlib.h>
> > #define TRICAT(a, b, c) a ## b ## c
> > #define CHAR(a, b, c) TRICAT(a, b, c)
>
> > #define CASE1 x
>
> ...
> > case CHAR('
> > , CASE1, '
> > ): break;
>
> Nice try, but no cigar. The ## operator requires that the result be a
> valid pp-token and, depending on the order in which the operators are
> evaluated, you either end up with 'x or x', neither of which are valid
> pp-tokens.
Even if ## were redefined so that intermediate results of a ## b ## c
are ignored, the behaviour is explicitly undefined.
6.4:
preprocessing-token:
[...]
each non-white-space character that cannot be one of the above
6.4p3:
If a ' or a " character matches the last category, the behavior is
undefined.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2011-11-08 12:15 -0500 |
| Message-ID | <4EB963BA.1020800@verizon.net> |
| In reply to | #12901 |
On 11/08/2011 12:01 PM, Harald van Dijk wrote:
> On Nov 7, 11:53 pm, lawrence.jo...@siemens.com wrote:
>> James Kuyper <jameskuy...@verizon.net> wrote:
>>> #include <stdlib.h>
>>> #define TRICAT(a, b, c) a ## b ## c
>>> #define CHAR(a, b, c) TRICAT(a, b, c)
>>
>>> #define CASE1 x
>>
>> ...
>>> case CHAR('
>>> , CASE1, '
>>> ): break;
>>
>> Nice try, but no cigar. The ## operator requires that the result be a
>> valid pp-token and, depending on the order in which the operators are
>> evaluated, you either end up with 'x or x', neither of which are valid
>> pp-tokens.
>
> Even if ## were redefined so that intermediate results of a ## b ## c
> are ignored, the behaviour is explicitly undefined.
>
> 6.4:
> preprocessing-token:
> [...]
> each non-white-space character that cannot be one of the above
>
> 6.4p3:
> If a ' or a " character matches the last category, the behavior is
> undefined.
Yes, I forgot about that item, too.
[toc] | [prev] | [next] | [standalone]
| From | Andrey Vul <andrey.vul@gmail.com> |
|---|---|
| Date | 2011-11-07 17:32 -0800 |
| Message-ID | <3a4820b7-ea0d-43bf-a158-807d4c0b2294@l19g2000yqc.googlegroups.com> |
| In reply to | #12855 |
On Nov 7, 3:07 pm, James Kuyper <jameskuy...@verizon.net> wrote:
> On 11/07/2011 02:11 PM, Andrey Vul wrote:
>
> > On Nov 7, 1:59 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> >> On 11/ 8/11 07:53 AM, Andrey Vul wrote:
>
> >>> To stringify pp-constants, we use #foo notation.
> >>> Is there a method of charifying constants defined on the preprocessor
> >>> level, assuming the precondition of length being 1 is true?
>
> I presume there's some reason why the constants cannot, themselves, be
> defined as character constants?
>
> >>> That is, does there exist a pp-builtin CHARIFY such that CHARIFY(x) =
> >>> 'x' ?
>
> >> Something like
>
> >> #define CHAR(x) #x [0]
>
> > Can't be used inside switch.
>
> There's no simple way I can think of to define a macro that generates a
> character constant whose value depends upon the expansion of another
> macro. I did, however, manage to come up with this ugly monstrosity,
> which cannot possibly qualify as "simple", which I've inserted into some
> test code:
>
> #include <stdlib.h>
> #define TRICAT(a, b, c) a ## b ## c
> #define CHAR(a, b, c) TRICAT(a, b, c)
>
> #define CASE1 x
>
> int main(int argc, char *argv[])
> {
> if(argc <= 1)
> return EXIT_FAILURE;
> switch (*argv[1])
> {
> case CHAR('
> , CASE1, '
> ): break;
> default:
> return EXIT_SUCCESS;
> }
> return EXIT_FAILURE;
>
> }
>
> The key thing that makes this work is that ' immediately followed by a
> newline is not recognized as any other type of pre-processing token, so
> it counts as a preprocessing token of it's own, under the classification
> "each non-white-space character that cannot be one of the above" (6.4p1).
>
> The two-level expansion allows CASE1 to be expanded to x before being
> concatenated with the ' tokens.
>
That looks like it shouldn't even compile!
In the end, I figured it's best to define as a char in the first place
and define the string as { 'f', 'o', 'o', 'b', 'a', 'r', ... } instead
of "foo" "bar" "...".
It's not like I'm making use of null-termination in the string
anyways.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2011-11-07 21:17 -0500 |
| Message-ID | <j9a3fv$ou0$1@dont-email.me> |
| In reply to | #12864 |
On 11/07/2011 08:32 PM, Andrey Vul wrote:
> On Nov 7, 3:07�pm, James Kuyper <jameskuy...@verizon.net> wrote:
...
>> There's no simple way I can think of to define a macro that generates a
>> character constant whose value depends upon the expansion of another
>> macro. I did, however, manage to come up with this ugly monstrosity,
>> which cannot possibly qualify as "simple", which I've inserted into some
>> test code:
>>
>> #include <stdlib.h>
>> #define TRICAT(a, b, c) a ## b ## c
>> #define CHAR(a, b, c) TRICAT(a, b, c)
>>
>> #define CASE1 x
>>
>> int main(int argc, char *argv[])
>> {
>> � � if(argc <= 1)
>> � � � � return EXIT_FAILURE;
>> � � switch (*argv[1])
>> � � {
>> � � case CHAR('
>> � � � � , CASE1, '
>> � � � � ): break;
>> � � default:
>> � � � � return EXIT_SUCCESS;
>> � � }
>> � � return EXIT_FAILURE;
>>
>> }
>>
>> The key thing that makes this work is that ' immediately followed by a
>> newline is not recognized as any other type of pre-processing token, so
>> it counts as a preprocessing token of it's own, under the classification
>> "each non-white-space character that cannot be one of the above" (6.4p1).
>>
>> The two-level expansion allows CASE1 to be expanded to x before being
>> concatenated with the ' tokens.
>>
>
> That looks like it shouldn't even compile!
It does compile, and works as intended - with gcc, with maximal
conformance and warning levels turned on. However, whether or not it's
required to compile is, at best, ambiguous. See Lawrence Jone's message
on this same thread - he's a fairly authoritative source, which doesn't
mean he's necessarily right - but I wouldn't recommend betting a lot of
money against him.
I'm curious - is there any specific feature that bothers you about that
code, other than the issue that Larry raised?
> In the end, I figured it's best to define as a char in the first place
> and define the string as { 'f', 'o', 'o', 'b', 'a', 'r', ... } instead
> of "foo" "bar" "...".
Yes, that's by far the better approach, even if there were no ambiguity
about my "solution".
--
James Kuyper
[toc] | [prev] | [next] | [standalone]
| From | Andrey Vul <andrey.vul@gmail.com> |
|---|---|
| Date | 2011-11-07 11:08 -0800 |
| Message-ID | <6a676bb7-78fe-426a-a5d5-0e7d2e0bd257@h30g2000pro.googlegroups.com> |
| In reply to | #12851 |
On Nov 7, 1:59 pm, Ian Collins <ian-n...@hotmail.com> wrote: > On 11/ 8/11 07:53 AM, Andrey Vul wrote: > > > To stringify pp-constants, we use #foo notation. > > Is there a method of charifying constants defined on the preprocessor > > level, assuming the precondition of length being 1 is true? > > That is, does there exist a pp-builtin CHARIFY such that CHARIFY(x) = > > 'x' ? > > Something like > > #define CHAR(x) #x [0] Can't be used inside switch or anything else requiring a const expression.
[toc] | [prev] | [next] | [standalone]
| From | Peter Nilsson <airia@acay.com.au> |
|---|---|
| Date | 2011-11-07 16:46 -0800 |
| Message-ID | <4c5d4452-89a7-400b-95e9-5b9e63f274f9@k38g2000pro.googlegroups.com> |
| In reply to | #12850 |
Andrey Vul <andrey....@gmail.com> wrote:
> To stringify pp-constants, we use #foo notation.
> Is there a method of charifying constants defined
> on the preprocessor level, assuming the precondition
> of length being 1 is true? That is, does there exist
> a pp-builtin CHARIFY such that CHARIFY(x) = 'x' ?
This is a good example of a question on a possible
solution to an unstated problem. As James Juyper asks,
what is the real problem that you're trying to solve?
In short, if you're already hardcoding x, why can't
you hardcode 'x'?
There are ways of synchronising elements using the
preprocessor. But different methods have different
advantages and disadvantages. The following will work
for some characters but not for others...
#define char_x 'x'
#define char_y 'y'
#define CHARIFY(x) char_ ## x
switch (blah)
{
case CHARIFY(x):
..
case CHARIFY(y):
..
}
--
Peter
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web