468,733 Members | 1,483 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,733 developers. It's quick & easy.

Index a #define string

s
Can I do this:

#define MYSTRING "ABC"
..
..
..
char mychar = MYSTRING[0];
..
..
..

-Thanks,
s
Jul 22 '05 #1
97 27158
s wrote:
Can I do this:

#define MYSTRING "ABC"
.
.
.
char mychar = MYSTRING[0];
.
.
.

-Thanks,
s


I would suggest using:
const char* const MYSTRING = "ABC";

AFAIK, your #define string thing should work, though.

- Pete
Jul 22 '05 #2
"s" <yo*********@home.with.yourself> wrote in message
news:40**************@home.with.yourself...
Can I do this:

#define MYSTRING "ABC"
.
char mychar = MYSTRING[0];

-Thanks,
s

Hello

Tried it with VC and it works fine.
Also: char mychar = *MYSTRING works fine.

--
Elias
Jul 22 '05 #3
On Fri, 16 Apr 2004 13:51:01 GMT in comp.lang.c++, "Petec" <x@x.x>
wrote,
I would suggest using:
const char* const MYSTRING = "ABC";


Why the gratuitous pointer?
const char mystring[] = "ABC";

Jul 22 '05 #4
David Harmon <so****@netcom.com> spoke thus:
const char* const MYSTRING = "ABC";
const char mystring[] = "ABC";


Are there any situations where the behavior of these two constructs
differs?

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #5
"s" <yo*********@home.with.yourself> wrote in message
news:40**************@home.with.yourself...
Can I do this:

#define MYSTRING "ABC"
.
.
.
char mychar = MYSTRING[0];


Yes, but why do this anyway. Avoid macros completely.

In this case you can do:

char mychar="ABC"[0];
or
const char * const MYSTRING="ABC";

char mychar=MYSTRING[0];


Ioannis Vranos

Jul 22 '05 #6
s wrote:
Can I do this:

#define MYSTRING "ABC"
.
.
.
char mychar = MYSTRING[0];
.
.
.

-Thanks,
s


This is a FAQ, but listed in the C language FAQ.
Reading the FAQs before posting is always a good
idea.
http://www.eskimo.com/~scs/c-faq/q6.11.html
--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book

Jul 22 '05 #7
Ioannis Vranos <iv*@guesswh.at.emails.ru> spoke thus:
Avoid macros completely.


Not all macros are evil.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #8
"s" <yo*********@home.with.yourself> wrote in message
news:40**************@home.with.yourself
Can I do this:

#define MYSTRING "ABC"
.
.
.
char mychar = MYSTRING[0];
.


The preprocessor simply does a text substitution so you end up with:

char mychar = "ABC"[0];

This is perfectly valid; it assigns 'A' to mychar. As far as the surrounding
code is concerned, a string literal is just a pointer.
--
John Carson
1. To reply to email address, remove donald
2. Don't reply to email address (post here instead)

Jul 22 '05 #9
"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in message
news:c5**********@chessie.cirr.com...
David Harmon <so****@netcom.com> spoke thus:
const char* const MYSTRING = "ABC";

const char mystring[] = "ABC";


Are there any situations where the behavior of these two constructs
differs?

Behaviour no, but implementation yes. "ABC" is stored in a separate space
reserved from the implementation, while the pointer MYSTRING and the array
mystring with all its members are stored in the stack.


Ioannis Vranos

Jul 22 '05 #10
David Harmon wrote:
On Fri, 16 Apr 2004 13:51:01 GMT in comp.lang.c++, "Petec" <x@x.x>
wrote,
I would suggest using:
const char* const MYSTRING = "ABC";


Why the gratuitous pointer?
const char mystring[] = "ABC";


It's just my style, and there's not much of a difference.
Besides, if I want to avoid pointers, I use a std::string.

- Pete
Jul 22 '05 #11
"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in message
news:c5**********@chessie.cirr.com...

Not all macros are evil.

We must try to avoid using macros completely (mainly by using templates),
with very few exceptions that this can't be done (mainly the #ifndef stuff).


Ioannis Vranos

Jul 22 '05 #12
On Fri, 16 Apr 2004 19:07:38 +0300 in comp.lang.c++, "Ioannis Vranos"
<iv*@guesswh.at.emails.ru> wrote,
"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in message
news:c5**********@chessie.cirr.com...
David Harmon <so****@netcom.com> spoke thus:
>>const char* const MYSTRING = "ABC";

> const char mystring[] = "ABC";


Are there any situations where the behavior of these two constructs
differs?

Behaviour no, but implementation yes. "ABC" is stored in a separate space
reserved from the implementation, while the pointer MYSTRING and the array
mystring with all its members are stored in the stack.


Sorry, but no. There is no "stack" at the point in namespace or file
scope where those declarations are presumably found. It could only be
on the stack if it were written local to a function, in which case I
would have written it
static const char mystring[] = "ABC";

Unfortunately, "static" means different things at function scope and at
file scope. Either way it should be merely a name referring to the same
constant area that the literal does occupy in the various other idioms.
Putting it on the stack would be very bad, calling for a copy to be made
from constant area every time you use it.

The possible extra level of indirection, and possible wasted space for
a pointer variable that was not called for in the original #define
example, is a mistake and a red herring and should never have been
introduced into the discussion. But, if it was at function scope, Pete
would presumably have declared it "static" also, and still have nothing
extra on the stack, I hope.

Jul 22 '05 #13
On Fri, 16 Apr 2004 16:05:00 +0000 (UTC) in comp.lang.c++, Christopher
Benson-Manica <at***@nospam.cyberspace.org> wrote,
Ioannis Vranos <iv*@guesswh.at.emails.ru> spoke thus:
Avoid macros completely.


Not all macros are evil.


Example?

Jul 22 '05 #14
"David Harmon" <so****@netcom.com> wrote in message
news:40***************@news.west.earthlink.net...
On Fri, 16 Apr 2004 19:07:38 +0300 in comp.lang.c++, "Ioannis Vranos"
<iv*@guesswh.at.emails.ru> wrote,
"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in messagenews:c5**********@chessie.cirr.com...
David Harmon <so****@netcom.com> spoke thus:

>>const char* const MYSTRING = "ABC";

> const char mystring[] = "ABC";

Are there any situations where the behavior of these two constructs
differs?

Behaviour no, but implementation yes. "ABC" is stored in a separate space
reserved from the implementation, while the pointer MYSTRING and the arraymystring with all its members are stored in the stack.


Sorry, but no. There is no "stack" at the point in namespace or file
scope where those declarations are presumably found.

At first, i assumed the definition takes place in a local scope and not in
the global or a namespace scope.

But except of that, where do you think global "non-static" variables are
created?

It could only be
on the stack if it were written local to a function, in which case I
would have written it
static const char mystring[] = "ABC";

There would be no point for this. The time cost for creating this thing is a
joke. :-) (Even the compiler may optimise it entirely out).
Unfortunately, "static" means different things at function scope and at
file scope.
Yes, and instead of using static keyword in the global scope it is better to
use an anonymous namespace.

Either way it should be merely a name referring to the same
constant area that the literal does occupy in the various other idioms.
Putting it on the stack would be very bad, calling for a copy to be made
from constant area every time you use it.

I do not understand what you mean, after all copies will be created inside
the array in all case scenarios.
The possible extra level of indirection, and possible wasted space for
a pointer variable that was not called for in the original #define
example, is a mistake and a red herring and should never have been
introduced into the discussion. But, if it was at function scope, Pete
would presumably have declared it "static" also, and still have nothing
extra on the stack, I hope.


You are wrong. static variables inside a function scope are still created in
the stack.


Ioannis Vranos

Jul 22 '05 #15
Ioannis Vranos <iv*@guesswh.at.emails.ru> spoke thus:
You are wrong. static variables inside a function scope are still created in
the stack.


Assuming the implementation uses a stack.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #16
On Fri, 16 Apr 2004 20:46:22 +0300 in comp.lang.c++, "Ioannis Vranos"
<iv*@guesswh.at.emails.ru> wrote,
At first, i assumed the definition takes place in a local scope and not in
the global or a namespace scope.
I assumed otherwise, since I have seen some huge number of such #define
constants in C code, and a somewhat lesser number of const strings in
C++ code, and the vast majority of them were near the top of the file
before any functions, if not in headers included near the top of the
file before any functions.
But except of that, where do you think global "non-static" variables are
created?
I don't understand that. All globals have static lifetime, or they
wouldn't be global. Show me the declaration of what you are talking
about and I'll tell you where I think it's created.
It could only be
on the stack if it were written local to a function, in which case I
would have written it
static const char mystring[] = "ABC";


There would be no point for this. The time cost for creating this thing is a
joke. :-) (Even the compiler may optimise it entirely out).


No point for what? There is certainly a point for putting "static" on
the declaration of that, at function scope, however small the cost of
omitting it on a string that happens to be very short.
Unfortunately, "static" means different things at function scope and at
file scope.


Yes, and instead of using static keyword in the global scope it is better to
use an anonymous namespace.


That's irrelevant. I was not suggesting "static" at global scope, I was
explaining why I did _not_ use "static" at global scope in the previous
example. Besides, consts at file scope are "static" in that sense by
default anyway. For purposes of this thread it matters not whether the
globals are declared "static" or in a namespace, or neither. It only
matters regarding the locals.
You are wrong. static variables inside a function scope are still created in
the stack.


No, not this time. Static variables wouldn't be static if they were on
the stack. If they were on the stack, where do you think their values
would be preserved from one call of the function to the next?

To illustrate, here is an compilable example:

const char* const MYSTRING = "ABC";
const char mystring[] = "ABC";
int main()
{
const char * cptr;
cptr = mystring; // line 6
cptr = MYSTRING; // line 7
static const char mystring[] = "ABC";
cptr = mystring; // line 9
static const char* const MYSTRING = "ABC";
cptr = MYSTRING; // line 11
}

I compiled that with MSVC 6.0 with default no optimization options (for
most straightforward translation) and /Fa for assembly listing output.
Here is the generated initialized data. You will notice the extra DD
storage for the two pointers, and that both of the "static" local
variables with the mangled names are in compile-time initialized
constant memory, not on the stack.

CONST SEGMENT
_MYSTRING DD FLAT:$SG265
_mystring DB 'ABC', 00H
_?mystring@?1??main@@9@4QBDB DB 'ABC', 00H
_?MYSTRING@?1??main@@9@4QBDB DD FLAT:$SG275
CONST ENDS
_DATA SEGMENT
$SG265 DB 'ABC', 00H
$SG275 DB 'ABC', 00H
_DATA ENDS

Now here is the MSVC generated code from the body of main(). Please
notice that the only variable on the stack is the non-static "cptr".
At no time does the code copy the characters "ABC\0" to the stack from
somewhere else. Also, there is the extra instruction required for
indirection in each of the pointer versions.

; Line 6
mov DWORD PTR _cptr$[ebp], OFFSET FLAT:_mystring
; Line 7
mov eax, DWORD PTR _MYSTRING
mov DWORD PTR _cptr$[ebp], eax
; Line 9
mov DWORD PTR _cptr$[ebp], OFFSET FLAT:_?mystring@?1??main@@9@4QBDB
; Line 11
mov ecx, DWORD PTR _?MYSTRING@?1??main@@9@4QBDB
mov DWORD PTR _cptr$[ebp], ecx

So you see, it is all exactly as I have told you.

Jul 22 '05 #17
"David Harmon" <so****@netcom.com> wrote in message
news:40***************@news.west.earthlink.net...
On Fri, 16 Apr 2004 20:46:22 +0300 in comp.lang.c++, "Ioannis Vranos"
<iv*@guesswh.at.emails.ru> wrote,
At first, i assumed the definition takes place in a local scope and not in
the global or a namespace scope.
I assumed otherwise, since I have seen some huge number of such #define
constants in C code, and a somewhat lesser number of const strings in
C++ code, and the vast majority of them were near the top of the file
before any functions, if not in headers included near the top of the
file before any functions.

The subject is a bit confused. In the case of macros, it doesn't count where
the macro is defined but where it is used, so since it was substituted
inside a function (turning MYSTRING[0] to "ABC"[0] before compilation takes
place), i considered it local. On the other hand he could place my
suggestions in a header file in the place of the macro definition, but it
doesn't matter anyway.
static const char mystring[] = "ABC";


There would be no point for this. The time cost for creating this thing is ajoke. :-) (Even the compiler may optimise it entirely out).


No point for what? There is certainly a point for putting "static" on
the declaration of that, at function scope, however small the cost of
omitting it on a string that happens to be very short.

In this case, i wouldn't use an array myself but a const char * const, but
never mind. If there isn't a specific advantage for making it static, why
should one make it of static storage?
No, not this time. Static variables wouldn't be static if they were on
the stack. If they were on the stack, where do you think their values
would be preserved from one call of the function to the next?

And where they get stored? As far as i know it is implementation-dependent
but i think the usual is stack.

To illustrate, here is an compilable example:

const char* const MYSTRING = "ABC";
const char mystring[] = "ABC";
int main()
{
const char * cptr;
cptr = mystring; // line 6
cptr = MYSTRING; // line 7
static const char mystring[] = "ABC";
cptr = mystring; // line 9
static const char* const MYSTRING = "ABC";
cptr = MYSTRING; // line 11
}

I compiled that with MSVC 6.0 with default no optimization options (for
most straightforward translation) and /Fa for assembly listing output.
Here is the generated initialized data. You will notice the extra DD
storage for the two pointers, and that both of the "static" local
variables with the mangled names are in compile-time initialized
constant memory, not on the stack.

CONST SEGMENT
_MYSTRING DD FLAT:$SG265
_mystring DB 'ABC', 00H
_?mystring@?1??main@@9@4QBDB DB 'ABC', 00H
_?MYSTRING@?1??main@@9@4QBDB DD FLAT:$SG275
CONST ENDS
_DATA SEGMENT
$SG265 DB 'ABC', 00H
$SG275 DB 'ABC', 00H
_DATA ENDS

I see a DD and a DB. But i do not know much of assembly, only very basic
theoretic, that we fetch data from memory to registers and vice versa,
e.t.c..

So you mean that it is in a memory area reserved by the implementation. I
can agree with that. The static storage space is implementation defined but
i thought that the usual is stack (at the beginning of it).


Now here is the MSVC generated code from the body of main(). Please
notice that the only variable on the stack is the non-static "cptr".
At no time does the code copy the characters "ABC\0" to the stack from
somewhere else.

You mean that the compiler optimises it out. I can agree with that, but
there is no guarantee that it will happen with all compilers, even with
different versions of the same compiler. The overall implementation details
we are discussing here are implementation-dependent. What i said is that if
we define a built in array like this as auto, there is no real performance
gain in most platforms. I think we should define a built in array to have
static storage only when we see actual benefit from it. In the
squeeze-every-cycle attitute (that i also had few years ago), you can gain 1
cycle or two after subsequent function calls with that char array, but in my
1,000,000 Hz CPU (and i bet you have a faster one) it will not be noticed,
especially when the system idle process of windows takes 95% of the CPU time
in the usual workload.

I consider the use of static only for some object whose creation/destruction
introduces significant time cost. Now if someone likes to optimise the
run-time of creation/destruction of some chars, it is fine with me. :-)


Ioannis Vranos

Jul 22 '05 #18
Christopher Benson-Manica wrote:
...
const char* const MYSTRING = "ABC";

const char mystring[] = "ABC";


Are there any situations where the behavior of these two constructs
differs?


Technically, yes. Remember that, firstly, string literal is an object
with static storage duration in C++. It has no name but it has its own
address in storage. And secondly, the implementation is allowed to merge
identical literals. The consequence of this is that in the following code

const char* const MYSTRING1 = "ABC";
const char* const MYSTRING2 = "ABC";

it is quite possible that both pointers will hold the same value
(depends on implementation).

However, if you do it this way

const char MYSTRING1[] = "ABC";
const char MYSTRING2[] = "ABC";

you can be sure that 'MYSTRING1' and 'MYSTRING2' are two different
objects and values of '&MYSTRING1' and '&MYSTRING2' are guaranteed to be
different.

In most cases this behavior makes no difference in the actual program.
But in some cases it could.

--
Best regards,
Andrey Tarasevich

Jul 22 '05 #19
On Fri, 16 Apr 2004 23:46:01 +0300, "Ioannis Vranos"
<iv*@guesswh.at.emails.ru> wrote in comp.lang.c++:
"David Harmon" <so****@netcom.com> wrote in message
news:40***************@news.west.earthlink.net...
[snip]
In this case, i wouldn't use an array myself but a const char * const, but
never mind. If there isn't a specific advantage for making it static, why
should one make it of static storage?
No, not this time. Static variables wouldn't be static if they were on
the stack. If they were on the stack, where do you think their values
would be preserved from one call of the function to the next?

And where they get stored? As far as i know it is implementation-dependent
but i think the usual is stack.


Since you have no idea at all how hardware stacks are used in typical
processors under typical C++ implementations, perhaps you shouldn't
try to answer questions here by discussing them incorrectly.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Jul 22 '05 #20
David Harmon wrote:

On Fri, 16 Apr 2004 16:05:00 +0000 (UTC) in comp.lang.c++, Christopher
Benson-Manica <at***@nospam.cyberspace.org> wrote,
Ioannis Vranos <iv*@guesswh.at.emails.ru> spoke thus:
Avoid macros completely.


Not all macros are evil.


Example?


#define NULL 0

#define offsetof(s,m) (size_t)&(((s *)0)->m)
Jul 22 '05 #21
"Julie" <ju***@nospam.com> wrote in message
news:40***************@nospam.com...

And some nicest alternatives:
#define NULL 0

const int NULL=0;

#define offsetof(s,m) (size_t)&(((s *)0)->m)

That appears to not work. You cast 0 to a struct/class pointer of s *, you
dereference that null pointer it to access a data member m which is illegal,
and then you get its address and cast it to size_t.


Ioannis Vranos

Jul 22 '05 #22
Ioannis Vranos wrote:
And some nicest alternatives:
#define NULL 0


const int NULL=0;


How about some justification as to why const is 'nicer' than #define, other
than rhetoric.
#define offsetof(s,m) (size_t)&(((s *)0)->m)


That appears to not work. You cast 0 to a struct/class pointer of s *, you
dereference that null pointer it to access a data member m which is illegal,
and then you get its address and cast it to size_t.


This is how it is implemented in my stddef.h -- the particulars are
implementation-defined, however the behavior is well-defined.

The previous poster wrote:
Not all macros are evil.


Example?


I've provided two examples of macros that satisfy his question.
Jul 22 '05 #23

"Julie" <ju***@nospam.com> wrote in message
news:40***************@nospam.com...
Ioannis Vranos wrote:
And some nicest alternatives:
#define NULL 0
const int NULL=0;


How about some justification as to why const is 'nicer' than #define,

other than rhetoric.
The C++ Programming Language" 3rd Edition or Special Edition by Bjarne
Stroustrup (the creator of C++), page 88:
5.1.1 Zero

Zero (0) is an int. Because of standard conversions (C.6.2.3), 0 can be
used as a constant of any integral (4.1.1), floating point, pointer, or
pointer to member type. The type of zero will be determined by context. Zero
will typically (but not necessarily) be represented by the bit pattern
all-zeros of the appropriate size.

No object is allocated with the address 0. Consequently, 0 acts as a pointer
literal, indicating that a pointer doesn't refer to an object.

In C, it has been popular to define a macro NULL to represent the zero
pointer. Because of C++'s tighter type checking, the use of plain 0, rather
than any suggested NULL macro, leads to fewer problems. If you feel you must
define NULL, use

const int NULL = 0;

The const qualifier (5.4) prevents accidental redefinition of NULL and
ensures that NULL can be used where a constant is required.

#define offsetof(s,m) (size_t)&(((s *)0)->m)


That appears to not work. You cast 0 to a struct/class pointer of s *, you
dereference that null pointer it to access a data member m which is illegal, and then you get its address and cast it to size_t.


This is how it is implemented in my stddef.h -- the particulars are
implementation-defined, however the behavior is well-defined.

That's a nice detail to quibble about.

As all know the C-style cast has also an equally dangerous equivalent.

If A, B two types:
(A)B is equivalent to A(B). A lame example:
char x=(char)5;

char x=char(5);

So the above thing does id equivalent to:

#define offsetof(s,m) (size_t)&((s *(0))->m)
It creates an s * pointer variable initialised to 0 and then accesses the m
data member. However the behaviour of both these is very system specific
*and* undefined.

The previous poster wrote: Not all macros are evil.


Example?


I've provided two examples of macros that satisfy his question.


And yours above is not evil?



Ioannis Vranos

Jul 22 '05 #24
Ioannis Vranos wrote:
> #define offsetof(s,m) (size_t)&(((s *)0)->m)

That appears to not work. You cast 0 to a struct/class pointer of s *, you dereference that null pointer it to access a data member m which is illegal, and then you get its address and cast it to size_t.
This is how it is implemented in my stddef.h -- the particulars are
implementation-defined, however the behavior is well-defined.


That's a nice detail to quibble about.


Not quibbling about.

Take a look at the standard library regarding offsetof. The behavior is well
defined. How it is implemented, is implementation defined.

Forget about the actual implementation that I posted for a minute, and consider
the macro behavior. It is useful, well-defined, and a valuable component of
the standard library, and it is a macro.

I've answered the PP's question.
And yours above is not evil?


It isn't mine, but an example of a useful and beneficial macro.

The notion that "all macros are bad" is more dangerous than the potential
misuse of macros.

Chew on that for a while, once you get out of the box.

end.
Jul 22 '05 #25
Julie wrote:

#define offsetof(s,m) (size_t)&(((s *)0)->m)


This is how it is implemented in my stddef.h -- the particulars are
implementation-defined, however the behavior is well-defined.


You can't get well-defined out of implementation-defined. The best you
can hope for is more implementation defined.

However, in this case there is no implementation-defined behavior. It is
completely undefined.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Jul 22 '05 #26
"Julie" <ju***@nospam.com> wrote in message
news:40***************@nospam.com...

Not quibbling about.

Take a look at the standard library regarding offsetof. The behavior is well defined. How it is implemented, is implementation defined.

Forget about the actual implementation that I posted for a minute, and consider the macro behavior. It is useful, well-defined, and a valuable component of the standard library, and it is a macro.

"Well-defined" and "implementation-defined" are different in ISO C++
terminology.

We can't discuss about implementation-defined programming. One could provide
a function, template function or some other interface and the implementation
in asm. When we say avoid the use of macros, is because the use of macros is
inherently dangerous, it may behave in an unexpected way, and bugs caused by
macro substitution of a macro defined in a header file which used in another
header file, which is used in our code are of the most difficult to trace.

C++ provides a superior alternative to macros (and void *s by the way) ,
templates. They are compile time checked and type safe.

The notion that "all macros are bad" is more dangerous than the potential
misuse of macros.

Well it is apparent that we will stick to our own opinions.

Chew on that for a while, once you get out of the box.

I am not in the box, i am in the hug of my LCD monitor. :-)


Ioannis Vranos

Jul 22 '05 #27
Kevin Goodsell wrote:

Julie wrote:

#define offsetof(s,m) (size_t)&(((s *)0)->m)


This is how it is implemented in my stddef.h -- the particulars are
implementation-defined, however the behavior is well-defined.


You can't get well-defined out of implementation-defined. The best you
can hope for is more implementation defined.

However, in this case there is no implementation-defined behavior. It is
completely undefined.


When you pick pieces out of context, you can make any argument that you want.

I said that the _particulars_ are implementation defined (meaning the
underlying implementation), the _behavior_ is well defined.

Contrary to your belief, this is the case, and is entirely possible.

The previous poster requested an example of a 'non-evil' macro, and I provided
that.

As I said: The notion that "all macros are bad" is more dangerous than the
potential
misuse of macros.
Jul 22 '05 #28
Julie wrote:


When you pick pieces out of context, you can make any argument that you want.

I said that the _particulars_ are implementation defined (meaning the
underlying implementation), the _behavior_ is well defined.
If you defined that macro yourself and used it, the behavior would NOT
be defined. You are free to use the library-supplied 'offsetof' macro,
and it will be well-defined, but that's not the same. An implementation
would be perfectly within its rights to (for example) crash on your
macro, even if it's identical to the standard library version.

Contrary to your belief, this is the case, and is entirely possible.
If you rely on implementation-defined behavior, you can't do better than
implementation-defined. But that's not particularly relevant, since
there was no implementation-defined behavior in the example.

The previous poster requested an example of a 'non-evil' macro, and I provided
that.


'Evil' is a technical term in C++ circles. It doesn't mean "not to be
used under any circumstances". This is in the FAQ.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Jul 22 '05 #29
Kevin Goodsell wrote:
Julie wrote:


When you pick pieces out of context, you can make any argument that you want.

I said that the _particulars_ are implementation defined (meaning the
underlying implementation), the _behavior_ is well defined.


If you defined that macro yourself and used it, the behavior would NOT
be defined. You are free to use the library-supplied 'offsetof' macro,
and it will be well-defined, but that's not the same. An implementation
would be perfectly within its rights to (for example) crash on your
macro, even if it's identical to the standard library version.

Contrary to your belief, this is the case, and is entirely possible.


If you rely on implementation-defined behavior, you can't do better than
implementation-defined. But that's not particularly relevant, since
there was no implementation-defined behavior in the example.

The previous poster requested an example of a 'non-evil' macro, and I provided
that.


'Evil' is a technical term in C++ circles. It doesn't mean "not to be
used under any circumstances". This is in the FAQ.


So what is your point to all of your responses w/ respect to the previous
poster's question and my response???

Do you agree that the offsetof() macro is an example of a 'non-evil' macro or
not?
Jul 22 '05 #30
On Sat, 17 Apr 2004 14:54:12 -0600 in comp.lang.c++, Julie
<ju***@nospam.com> wrote,

Do you agree that the offsetof() macro is an example of a 'non-evil' macro or
not?


It is very nasty in both intent and action. I think it would not exist
in C++ except for the need for backwards C compatibility.

In intent, it breaks encapsulation and encourages dependence on the
low-level layout and implementation of objects. Depend only upon the
classes' public interface. Use "pointer-to-member" when called for.

In action, it relies on non-portable tricks and cannot be defined within
standard C++. Or even C, I think, which is probably why it is in the
library instead of expecting self-abusers to supply their own.

Jul 22 '05 #31
"Ioannis Vranos" <iv*@guesswh.at.emails.ru> wrote in message
When we say avoid the use of macros, is because the use of macros is
inherently dangerous,
If you're going to make unilateral statements such as this, you need to actually
back it up with specifics instead of repeating prejudicial generalizations.
Macros are *not* inherently dangerous. Certain *uses* of macros are dangerous
and have other pitfalls, but by no means does this extend to the general notion
of macros. This extends to other constructs as well that have, at times, even
greater pitfalls in C++. The way to deal with these pitfalls is through idioms
and techniques that are not enforced by the language itself except in some cases
through diagnostics (and sometimes with no diagnostic required by the standard).
The preprocessor, and the macro mechanism in particular, is simply easier to
target as an isolated entity. The pronouncement that "macros are evil" is
merely an act of people being to lazy to define exactly what sorts of usages are
or are not evil with respect to macros. It is as ridiculous as saying that
templates are evil because undetected POI issues exist.
it may behave in an unexpected way, and bugs caused by
macro substitution of a macro defined in a header file which used in another
header file, which is used in our code are of the most difficult to trace.

C++ provides a superior alternative to macros (and void *s by the way) ,
templates. They are compile time checked and type safe.
Here your making another gross oversimplification. C++ provides a superior
alternative to using macros to define type/value generic constructs (such as
classes and functions) and inline functions (and sometimes constants). That
doesn't even come close to covering the range of uses of macros.
The notion that "all macros are bad" is more dangerous than the potential
misuse of macros.


I totally agree with this. Specifically, notions like the above are dangerous
because they show a lack of understanding and thought about when and where which
tool should be applied. It shows a serious lack of lateral thinking and logical
deduction.
Well it is apparent that we will stick to our own opinions.

Chew on that for a while, once you get out of the box.

I am not in the box, i am in the hug of my LCD monitor. :-)


:)

A statement like "macros are inherently dangerous" comes straight out of the
box. Consider Boost, which contains a great deal of out-of-the-box thinking
resulting in some incredible libraries that push the boundaries of all
previously existing design technique. And then consider further, that many of
those libraries are generated *with macros that have never caused a name clash
despite the relatively widespread use of Boost*. I'm not saying that macros are
the end-all-and-be-all, and I'm not saying that many uses (if not *most* uses in
practice) are not dangerous. What I am saying is that there are both good uses
and bad uses--just like with every other language feature or intersection of
features. Anything else is the result of people being too lazy to actually pin
down the problems or naivety caused by blind application of guidelines that are
themselves a product of previous laziness.

Regards,
Paul Mensonides
Jul 22 '05 #32
"Paul Mensonides" <le******@comcast.net> wrote in message
news:Se********************@comcast.com...

If you're going to make unilateral statements such as this, you need to actually back it up with specifics instead of repeating prejudicial generalizations. Macros are *not* inherently dangerous. Certain *uses* of macros are dangerous and have other pitfalls, but by no means does this extend to the general notion of macros. This extends to other constructs as well that have, at times, even greater pitfalls in C++. The way to deal with these pitfalls is through idioms and techniques that are not enforced by the language itself except in some cases through diagnostics (and sometimes with no diagnostic required by the standard). The preprocessor, and the macro mechanism in particular, is simply easier to target as an isolated entity. The pronouncement that "macros are evil" is
merely an act of people being to lazy to define exactly what sorts of usages are or are not evil with respect to macros. It is as ridiculous as saying that templates are evil because undetected POI issues exist.

With only few exceptions like inclusion guards, you can do whatever you can
do with macros with templates. So what remains at the end are the dangerous
uses.

it may behave in an unexpected way, and bugs caused by
macro substitution of a macro defined in a header file which used in another header file, which is used in our code are of the most difficult to trace.
C++ provides a superior alternative to macros (and void *s by the way) ,
templates. They are compile time checked and type safe.


Here your making another gross oversimplification. C++ provides a

superior alternative to using macros to define type/value generic constructs (such as classes and functions) and inline functions (and sometimes constants). That doesn't even come close to covering the range of uses of macros.

So do you think macros should be used in every day's code?
I totally agree with this. Specifically, notions like the above are dangerous because they show a lack of understanding and thought about when and where which tool should be applied. It shows a serious lack of lateral thinking and logical deduction.

I never said that "macros are evil". But (obviously) in the contrary of you,
i consider a good practice to try avoid using macros as much as it is
possible.


A statement like "macros are inherently dangerous" comes straight out of the box.

And also i never said the above. What i said is

"We must try to avoid using macros completely (mainly by using templates),
with very few exceptions that this can't be done (mainly the #ifndef
stuff)."

Consider Boost, which contains a great deal of out-of-the-box thinking
resulting in some incredible libraries that push the boundaries of all
previously existing design technique. And then consider further, that many of those libraries are generated *with macros that have never caused a name clash despite the relatively widespread use of Boost*. I'm not saying that macros are the end-all-and-be-all, and I'm not saying that many uses (if not *most* uses in practice) are not dangerous. What I am saying is that there are both good uses and bad uses--just like with every other language feature or intersection of features. Anything else is the result of people being too lazy to actually pin down the problems or naivety caused by blind application of guidelines that are themselves a product of previous laziness.

Well i agree. But i like to term the meaning of your phrase

"What I am saying is that there are both good uses and bad uses--just like
with every other language feature or intersection of features."

as

"We must avoid using macros where possible".


Ioannis Vranos

Jul 22 '05 #33
"Ioannis Vranos" <iv*@guesswh.at.emails.ru> wrote in message
With only few exceptions like inclusion guards, you can do whatever you can
do with macros with templates. So what remains at the end are the dangerous
uses.
No, you can't. For instance, you cannot generate the source code of templates
with templates, but you can with macros. You cannot generate a set of typesafe
overloaded functions with arity ranging from zero to any conceivable number of
parameters with templates, but you can with macros. You cannot define constants
that are usable to choose between various implementations each of which will
compile only on specific compilers on specific operating systems with underlying
language constants, but you can with macros. This list goes on and on.
it may behave in an unexpected way, and bugs caused by
macro substitution of a macro defined in a header file which used in another header file, which is used in our code are of the most difficult to trace.
C++ provides a superior alternative to macros (and void *s by the way) ,
templates. They are compile time checked and type safe.


Here your making another gross oversimplification. C++ provides a

superior
alternative to using macros to define type/value generic constructs (such

as
classes and functions) and inline functions (and sometimes constants).

That
doesn't even come close to covering the range of uses of macros.

So do you think macros should be used in every day's code?


"Every day code" is too general; it depends on what you are writing. If, for
example, you are writing a generic component (maybe some sort of "bind",
"compose", or "closure") you should, by all means, use the preprocessor to
generate code for you, such that you minimize the number of maintenance points
and increase the scalability of the component. OTOH, using macro definitions
instead of typedefs or using macro definitions instead of constant variables,
*is* pure evil most (but not all) of the time. Otherwise, macros can be used
locally (i.e. defined, used, undefined) for simple syntactic convenience. So,
to answer the question is, "Macros should be used when the use of macros is
better, and macros should not be used when the use of macros is not better."
Notice that the above doesn't present any black-and-white solution--it means you
have to *know* in any specific situation whether the use of macros is good,
evil, or the lesser of two evils.
I totally agree with this. Specifically, notions like the above are

dangerous
because they show a lack of understanding and thought about when and where

which
tool should be applied. It shows a serious lack of lateral thinking and

logical
deduction.

I never said that "macros are evil". But (obviously) in the contrary of you,
i consider a good practice to try avoid using macros as much as it is
possible.


You said that one should avoid using macros because macros are "inherently
dangerous."
That statement is incorrect. How about using some guidelines that have a
modicum of validity? Like:

1) use all uppercase names only for macros
2) macros defined in headers (that are intended to propogate out of those
headers) should always be prefixed with some project/library prefix (i.e. a name
space)
3) macros defined in headers for local use only need not be prefixed, but should
specifically *not* be all uppercase and should *always* be undefined after use
(i.e. to prevent the possibility of a clash with an actual "external" macro
name).

Even with these guidelines there are some exceptions. The point, in any case,
is that the avoidance of macros in general is not a good guideline. Rather,
avoidance of certain usages of macros are good guidelines, and so on.
Otherwise, you are just tying your hands behind your back.

A statement like "macros are inherently dangerous" comes straight out of

the
box.

And also i never said the above. What i said is

"We must try to avoid using macros completely (mainly by using templates),
with very few exceptions that this can't be done (mainly the #ifndef
stuff)."


And that is simply false; it should be, "We must try to avoid using macros for
these kinds of purposes ... unless there is an exceptional reason to use them,"
and also, "If macros are to be used, they should be used according to these
guidelines ... unless there is an exceptional reason not to." Anything else is
presumptious and leads to brain-dead coding.
> Consider Boost, which contains a great deal of out-of-the-box thinking
resulting in some incredible libraries that push the boundaries of all
previously existing design technique. And then consider further, that

many of
those libraries are generated *with macros that have never caused a name

clash
despite the relatively widespread use of Boost*. I'm not saying that

macros are
the end-all-and-be-all, and I'm not saying that many uses (if not *most*

uses in
practice) are not dangerous. What I am saying is that there are both good

uses
and bad uses--just like with every other language feature or intersection

of
features. Anything else is the result of people being too lazy to

actually pin
down the problems or naivety caused by blind application of guidelines

that are
themselves a product of previous laziness.

Well i agree. But i like to term the meaning of your phrase


Obviously you don't, because you obviously have no idea how macros are used in
modern libraries such as Boost. If you did, you would effectively be saying
that Boost is poorly implemented. If you are saying that, fine, but you have an
awfully high opinion of yourself to say such a thing. If you aren't saying
that, then you are naive regarding many of the issues involved in day to day
generic programming.
"What I am saying is that there are both good uses and bad uses--just like
with every other language feature or intersection of features."

as

"We must avoid using macros where possible".


The two are quite different, and the bad uses of macros do not outweight their
good uses enought (if they do at all) to draw an equivalence between the two
statements. According to your logic, you should also be saying, "We must avoid
using templates where possible." I.e. just because something *can* be used
poorly, doesn't mean that something cannot be used well, and, similarly, just
because something *can* be used well, doesn't mean that something cannot be used
poorly. In the case of templates, finding template-related bugs can be far far
worse than anything related to macros at all. Moral of the story, you cannot
condense good programming to a set of near black-and-white guidelines.

Regards,
Paul Mensonides
Jul 22 '05 #34
On Sat, 17 Apr 2004 21:07:07 -0700 in comp.lang.c++, "Paul Mensonides"
<le******@comcast.net> wrote,
"Ioannis Vranos" <iv*@guesswh.at.emails.ru> wrote in message
With only few exceptions like inclusion guards, you can do whatever you can
do with macros with templates. So what remains at the end are the dangerous
uses.


No, you can't. For instance, you cannot generate the source code of templates
with templates, but you can with macros. You cannot generate a set of typesafe
overloaded functions with arity ranging from zero to any conceivable number of
parameters with templates, but you can with macros.


Oh, that is all sophistry. You are saying basically, that you cannot
use templates in the identical fashion that you use macros. Well, so
what? The point is that you can accomplish the reasonable purpose
formerly served by macros, with templates, consts, and other C++
constructs that offer the advantages of being integrated with the
language. That you cannot perform exactly the same gyrations on the way
to getting there is not a bug, it's a feature.

Jul 22 '05 #35
"Paul Mensonides" <le******@comcast.net> wrote in message
news:xp********************@comcast.com...

The two are quite different, and the bad uses of macros do not outweight their good uses enought (if they do at all) to draw an equivalence between the two statements. According to your logic, you should also be saying, "We must avoid using templates where possible." I.e. just because something *can* be used poorly, doesn't mean that something cannot be used well, and, similarly, just because something *can* be used well, doesn't mean that something cannot be used poorly. In the case of templates, finding template-related bugs can be far far worse than anything related to macros at all. Moral of the story, you cannot condense good programming to a set of near black-and-white guidelines.


I think it is a matter of views. I did not say to remove macros from the
language but i do not consider the macros matter as a balanced issue - that
there are as many good uses as bad uses. Macros are not to be used in daily
application programming.

For example i program C++ applications for .NET and i see no need to use
macros. On the other hand you seem to work in libraries area and you use
macros daily to get the job done. So perhaps the "default" for each one of
us is different. I can understand the use of macros in libraries, but still
even in that case my "default" would not be to use macros but only where i
can't do work without them.

There are things one can do only with macros, and i would use macros only to
do those.
Some quotes from TC++PL 3:
Page 10:

"The template facility was primarily designed to support statically typed
containers (such as lists, vectors, and maps) and to support elegant and
efficient use of such containers (generic programming). A key aim was to
reduce the use of macros and casts (explicit type conversion)."
Page 14:

"1.6.1 Suggestions for C Programmers

The better one knows C, the harder it seems to be to avoid writing C++ in C
style, thereby losing some of the potential benefits of C++. Please take a
look at Appendix B, which describes the differences between C and C++. Here
are a few pointers to the areas in which C++ has better ways of doing
something than C has:

[1] Macros are almost never necessary in C++. Use const (5.4) or enum
(4.8) to define manifest constants, inline (7.1.1) to avoid function
calling overhead, templates (Chapter 13) to specify families of functions
and types, and namespaces (8.2) to avoid name clashes."

Page 160:

"7.8 Macros

Macros are very important in C but have far fewer uses in C++. The first
rule about macros is: Don't use them unless you have to. Almost every macro
demonstrates a flaw in the programming language, in the program, or in the
programmer. Because they rearrange the program text before the compiler
proper sees it, macros are also a major problem for many programming tools.
So when you use macros, you should expect inferior service from tools such
as debuggers, crossreference tools, and profilers. If you must use macros,
please read the reference manual for your own implementation of the C++
preprocessor carefully and try not to be too clever. Also to warn readers,
follow the convention to name macros using lots of capital letters."
Page 161:

"Using macros, you can design your own private language. Even if you prefer
this ''enhanced language'' to plain C++, it will be incomprehensible to most
C++ programmers. Furthermore, the C preprocessor is a very simple macro
processor. When you try to do something non-trivial, you are likely to find
it either impossible or unnecessarily hard to do. The const, inline,
template, and namespace mechanisms are intended as alternatives to many
traditional uses of preprocessor constructs.

For example:

const int answer = 42;
template<class T> inline T min(T a, T b) { return (a<b)?a:b; }"

Page 163:

"7.9 Advice

[1] Be suspicious of non-const reference arguments; if you want the function
to modify its arguments, use pointers and value return instead; 5.5.
[2] Use const reference arguments when you need to minimize copying of
arguments; 5.5.
[3] Use const extensively and consistently; 7.2.
[4] Avoid macros; 7.8."



Ioannis Vranos

Jul 22 '05 #36
"David Harmon" <so****@netcom.com> wrote in message
news:40****************@news.west.earthlink.net...
On Sat, 17 Apr 2004 21:07:07 -0700 in comp.lang.c++, "Paul Mensonides"
<le******@comcast.net> wrote,
"Ioannis Vranos" <iv*@guesswh.at.emails.ru> wrote in message
With only few exceptions like inclusion guards, you can do whatever you can
do with macros with templates. So what remains at the end are the dangerous
uses.


No, you can't. For instance, you cannot generate the source code of templateswith templates, but you can with macros. You cannot generate a set of typesafeoverloaded functions with arity ranging from zero to any conceivable number ofparameters with templates, but you can with macros.


Oh, that is all sophistry. You are saying basically, that you cannot
use templates in the identical fashion that you use macros. Well, so
what? The point is that you can accomplish the reasonable purpose
formerly served by macros, with templates, consts, and other C++
constructs that offer the advantages of being integrated with the
language. That you cannot perform exactly the same gyrations on the way
to getting there is not a bug, it's a feature.


No, it isn't sophistry. It's simply a gross reduction of solutions to issues of
which you apparently have no conception. I'm not talking about generating
functions or classes with varying types, and I'm certainly not advocating that
macros be used for such a purpose without a really good reason--that is what
templates are for. I'm talking about generating source code, be it templates or
overloaded functions or whatever (a lexical analyzer, perhaps) that is
impossible to achieve otherwise without an external code generator or with
excessive manual copying. The first requires another build step--which is
terrible in a library context--and the second dramatically increases the number
of maintenance points.

The point is that you can accomplish many *but by no means all* purposes
formally served by macros. I'm not disagreeing that there are better solutions
to many things that macros were used for at one time. It isn't a question of
getting to the same place a different way; instead, it is that the destination
is quite different. One way to look at it is that the preprocessor is to
templates as templates are to classes and functions. (That certainly doesn't
summarize the entire field, but it does summarize a large portion of it.)

Regarding your "bug/feature" statement... You are certainly correct that
templates are a great feature for what they are intended to do. The same
extends to constant variables vs. macros, but to a slightly lesser degree. I'm
not arguing that, and I never will. What I am arguing is that statements such
as "macros are evil" or "macros are inherently dangerous" (which are both common
statements) are prejudicial generalizations that simply aren't true. Macros are
not evil, certain usages of them are. Macros are not inherently dangerous,
certain uses of them are. That is no different than any other language feature
or intersection of features. The only difference is that many have been too
brainwashed by statements like the above to investigate the cause-and-effect of
feature intersections within the preprocessor (within macro expansion in
particular) and feature intersections between the preprocessor and the language
proper--like they have with the underlying language.

As an aside, the core language is no more protected from name clashes than the
preprocessor. Namespaces serve to classify and organize names, but they do not,
at a language level, protect them. The only things that stop name collision are
1) utilize existing and well-known idioms and techniques such as documenting
which namespaces are considered "owned" by a component or library and 2)
decrease the likelihood of a clash by effectively extending the name (i.e.
namespace qualification). For example, say some component/library has this code
in a header:

// library.h

namespace library {
struct abc {
operator int() const {
return 0;
}
};
}

And then some other library or project header has this code:

namespace library {
const struct {
int operator()() const {
return 1;
}
} abc = { };
}

The above two declarations can silently coexist, but the expression "abc()" can
silently mean a different thing depending on where it is used. Obviously, a
scenario such as the above is very unlikely, but the point remains--the language
does not protect against name clashes in general. Only good conventions like
"don't use the same namespace" protect code against such collisions. The same
is true for macros, but instead of having an explicit qualification syntax, you
have prefixing (such as LIBRARY_ABC) (or suffixing) and good conventions like
"use all uppercase names for macros and only for macros". Together, it
accomplishes the same thing--protection against name interference--as the use of
namespaces and the accompanying conventions that are relied on by namespace
authors and users. That is certainly not the only sort of problem that the use
of macros can cause, but it is a major one. There are many other examples,
similar to the above, that illustrate the lack of true name encapsulation in the
core language. Most of the time such a name clash isn't silent--just as it
usually isn't with macros. (In fact, silent changes (i.e. the *really* hard
ones to deal with) are rare even without the application of any convention
whatsoever.) Nevertheless, the problems that can surface can be extremely
roundabout--such as dealing with subtle POI issues in different translation
units--where a diagnostic is not required by standard. Consider, for example,
what can the following can do, in the right circumstances, to constant
expressions involving enumerations (e.g. template metaprogramming that doesn't
use static const):

template<class T, class U> T operator+(T, U);

It once again shows that names are not encapsulated--only organized, and why
convention is the true means of encapsulation against name clash. A reasonable
convention to handle the above would be "do not declare completely generic
operator overloads".

Regards,
Paul Mensonides
Jul 22 '05 #37
"Paul Mensonides" <le******@comcast.net> wrote in message
news:xI********************@comcast.com...

No, it isn't sophistry. It's simply a gross reduction of solutions to issues of which you apparently have no conception. I'm not talking about generating
functions or classes with varying types, and I'm certainly not advocating that macros be used for such a purpose without a really good reason--that is what templates are for. I'm talking about generating source code, be it templates or overloaded functions or whatever (a lexical analyzer, perhaps) that is
impossible to achieve otherwise without an external code generator or with
excessive manual copying. The first requires another build step--which is
terrible in a library context--and the second dramatically increases the number of maintenance points.

The point is that you can accomplish many *but by no means all* purposes
formally served by macros. I'm not disagreeing that there are better solutions to many things that macros were used for at one time. It isn't a question of getting to the same place a different way; instead, it is that the destination is quite different. One way to look at it is that the preprocessor is to
templates as templates are to classes and functions. (That certainly doesn't summarize the entire field, but it does summarize a large portion of it.)

Regarding your "bug/feature" statement... You are certainly correct that
templates are a great feature for what they are intended to do. The same
extends to constant variables vs. macros, but to a slightly lesser degree. I'm not arguing that, and I never will. What I am arguing is that statements such as "macros are evil" or "macros are inherently dangerous" (which are both common statements) are prejudicial generalizations that simply aren't true. Macros are not evil, certain usages of them are. Macros are not inherently dangerous, certain uses of them are. That is no different than any other language feature or intersection of features. The only difference is that many have been too brainwashed by statements like the above to investigate the cause-and-effect of feature intersections within the preprocessor (within macro expansion in
particular) and feature intersections between the preprocessor and the language proper--like they have with the underlying language.
Macros must be avoided where possible. In an effort to not hurt your
feelings we can rephrase that "Use macros only when needed". Choose whatever
fits you better, they are both the same. And C++ is not C, you may have been
a C programmer for some long time and have done a lot of real and excellent
work with macros, but C++ is not C and in most cases the language provides
superior alternatives.

On the other hand, if you *still* program in C and you use macros, then what
we discuss here does not apply.

As an aside, the core language is no more protected from name clashes than the preprocessor. Namespaces serve to classify and organize names, but they do not, at a language level, protect them. The only things that stop name

collision are
Namespaces do not exist to protect from name collisions. Namespaces are the
implementation of the modular programming paradigm, that is to place the
data and its functions in an area (you can call it as the ancestor of OO
but it is a non-obsolete useful paradim), so as to have them together. E.g.:
namespace whatever
{
int x;

void somefunc(const int a) { /* Do things with x; */ }
int someotherfunc(int a) { /* Do some other things with x */ }
// ...
}

That's the modular paradigm namespaces was made for. Today we use this
paradigm with classes, etc too. And they help use different implementations
of the same facilities, e.g. std::vector vs
some_other_implementation::vector.

And something most do not know is that the use of a global namespace
declaration is not good. E.g.
#include <iostream>
#include <vector>

using namespace std;
int main()
{
// ..
}
is bad style. For accuracy it is an attempt to defeat the namespace system.
That's why a typical C++ standard library implementation of <stdio.h> is (or
better should be):
--- stdio.h ---

#include <cstdio>
using std::printf;
using std::sprintf;
// ...
using std::scanf;

// etc

--- end of C++ stdio.h ---
In summary, namespaces are not made to protect from name collisions among
functions doing different things, but to organize work and *protect* from
name collisions of facilities doing the same things.


Regards,

Ioannis Vranos

Jul 22 '05 #38
"Ioannis Vranos" <iv*@guesswh.at.emails.ru> wrote in message
news:c5***********@ulysses.noc.ntua.gr...

And something most do not know is that the use of a global namespace
declaration is not good. E.g.
#include <iostream>
#include <vector>

using namespace std;
int main()
{
// ..
}
is bad style. For accuracy it is an attempt to defeat the namespace system. That's why a typical C++ standard library implementation of <stdio.h> is (or better should be):
--- stdio.h ---

#include <cstdio>
using std::printf;
using std::sprintf;
// ...
using std::scanf;

// etc

--- end of C++ stdio.h ---

Now it is an entirely new topic, but since i got in, it is not good to leave
it unexplained. In a brief summary we must try using namespace declarations
in as a small scope as possible in the style:

For a couple of facilities, we must use "using namespace_name::facility;" in
as a small scope as possible. Example:
#include <iostream>

int main()
{
using std::cout;
using std::endl;

// ...

cout<</* ... */<<endl;

// ...

cout<</* ... */<<endl;
}
For more than a couple of things, we must use "using namespace
namespace_name;" in as a small scoe as possible. Example:
#include <iostream>
#include <vector>

int main()
{
using namespace std;

vector<int>whatever(10);

// ...

for(vector<int>::size_type i=0; i<whatever.size(); ++i)
cout<<whatever[i]<<endl;

// ...

for(vector<int>::size_type i=0; i<whatever.size(); ++i)
cout<<whatever[i]<<endl;
}


Ioannis Vranos

Jul 22 '05 #39
On Sun, 18 Apr 2004 13:55:36 -0700 in comp.lang.c++, "Paul Mensonides"
<le******@comcast.net> wrote,
I'm talking about generating source code, be it templates or
overloaded functions or whatever (a lexical analyzer, perhaps) that is
impossible to achieve otherwise without an external code generator or with
excessive manual copying. The first requires another build step--which is
terrible in a library context--and the second dramatically increases the number
of maintenance points.


Lexical analyzer? Show me a C preprocessor implementation of anything
to compare with Joel de Guzman's Spirit parser template library.
http://spirit.sf.net

Jul 22 '05 #40
Ioannis Vranos wrote:
"Paul Mensonides" <le******@comcast.net> wrote in message
news:xp********************@comcast.com...

The two are quite different, and the bad uses of macros do not
outweight their good uses enought (if they do at all) to draw an
equivalence between the two statements. According to your logic,
you should also be saying, "We must avoid using templates where
possible." I.e. just because something *can* be used poorly,
doesn't mean that something cannot be used well, and, similarly,
just because something *can* be used well, doesn't mean that
something cannot be used poorly. In the case of templates, finding
template-related bugs can be far far worse than anything related to
macros at all. Moral of the story, you cannot condense good
programming to a set of near black-and-white guidelines.
I think it is a matter of views. I did not say to remove macros from
the language but i do not consider the macros matter as a balanced
issue - that there are as many good uses as bad uses. Macros are not
to be used in daily application programming.


And that is a wrong assessment. Macros are not to be used when the use of
something else is better--and vice versa. Whether it is library code or
application code is irrelevant. You cannot simplify it that easily.
For example i program C++ applications for .NET and i see no need to
use macros. On the other hand you seem to work in libraries area and
you use macros daily to get the job done. So perhaps the "default"
for each one of us is different. I can understand the use of macros
in libraries, but still even in that case my "default" would not be
to use macros but only where i can't do work without them.
I agree that the good uses of macros appear more often in library code than in
application code. However, there is no universally clear distinction between
what should be library code and what should be application code. And even if
there was, good uses for macros in application code still appear often enough
that such a generalization is invalid. It isn't that I disagree with you
regarding the use of templates, constant variables, inline functions, etc.. I
disagree that those things even come close to encompassing the totality of macro
use--many of which you probably aren't aware of. In essence, the guideline that
you espouse is invalid because it is too broad and needs to be broken down into
constituent guidelines which actually *are* valid. Otherwise, you propogate the
status quo of prejudice-oriented programming which avoids the singlular problem
of macro name collision while simultaneously producing suboptimal code that
likely includes maintenance nightmares. Use macros when macros are the best
option to do a thing, otherwise don't--no prejudice involved, but it implies
that you actually have to *know* what is good or bad and why. There is nothing
wrong with that at all--it is the antithesis of laziness.
There are things one can do only with macros, and i would use macros
only to do those.
What about things that can be done much easier and much more efficiently in
terms of both run-time performance and maintenance?
Some quotes from TC++PL 3:
Page 10:

"The template facility was primarily designed to support statically
typed containers (such as lists, vectors, and maps) and to support
elegant and efficient use of such containers (generic programming). A
key aim was to reduce the use of macros and casts (explicit type
conversion)."
Yes, and for that purpose (and others) templates are great.
Page 14:

"1.6.1 Suggestions for C Programmers

The better one knows C, the harder it seems to be to avoid writing
C++ in C style, thereby losing some of the potential benefits of C++.
Please take a look at Appendix B, which describes the differences
between C and C++. Here are a few pointers to the areas in which C++
has better ways of doing something than C has:

[1] Macros are almost never necessary in C++.
Wrong, for a variety of reasons. The most ironic of them is that various C++
implementations differ far more radically than various C implementations.
Use const (5.4) or enum
(4.8) to define manifest constants,
Most of time, yes--unless it is needed by the preprocessor for a good reason.
In such a case, it should be mirrored:

#define LIBRARY_XYZ 10

namespace library {
const int xyz = LIBRARY_XYZ;
}
inline (7.1.1) to avoid function
calling overhead,
Yes, except in very special cases where you actually *do* know better than the
compiler.
templates (Chapter 13) to specify families of
functions and types, and namespaces (8.2) to avoid name clashes."
Namespaces don't avoid name clashes per se. They provide a means to structure
and classify names. That indirectly avoids name clashes by effectively
increasing the length of the relevant names. That's a minor point, however, and
otherwise I agree.
Page 160:

"7.8 Macros

Macros are very important in C but have far fewer uses in C++.
Along certain lines, yes. Along other lines, the exact opposite is true.
The
first rule about macros is: Don't use them unless you have to. Almost
every macro demonstrates a flaw in the programming language, in the
program, or in the programmer.
The "first rule about macros" is wrong. It should be, don't use them when there
is a superior alternative within the language proper--where "superior" means the
total set of all possible ways in which something can be superior or inferior
(some of which are subjective, some of which are not).

Many macros do indeed demonstrate flaws in the programming language--one of them
being the lack of power that macros have (compared to other macro mechanisms).
This also represents a broad class of language deficiencies that are never going
to change. Some will, yes, but otherwise, so what? Flaws in the program and in
the programmer obviously exist, and many times the use of macros demonstrates
that--as does the use of many combinations of language elements. In any case,
the above is true if "almost every macro" means almost every existing macro
currently in existence. The above is not true if "almost every macro" is
supposed to mean "almost every possible use of macros".
Because they rearrange the program
text before the compiler proper sees it, macros are also a major
problem for many programming tools.
First, macros do not rearrange the program "text", they rearrange the program's
preprocessing tokens within a translation unit. Second, that is the fundamental
reason why the preprocessor is such a powerful tool in certain types of
situations. That is what provides both the power and the danger of the
preprocessor, and consequently (as a generalization) where and when the use of
macros can be good.
So when you use macros, you
should expect inferior service from tools such as debuggers,
crossreference tools, and profilers.
Wrong, or at least, not specific enough. This is entirely dependant on how
macros are used and for what purpose.
If you must use macros, please
read the reference manual for your own implementation of the C++
preprocessor carefully and try not to be too clever. Also to warn
readers, follow the convention to name macros using lots of capital
letters."
Absolutely. In addition, you should always undefine macros that are used only
locally.
Page 161:

"Using macros, you can design your own private language. Even if you
prefer this ''enhanced language'' to plain C++, it will be
incomprehensible to most C++ programmers.
The reference here is making C++ look like, for example, Pascal. I'm definitely
not advocating doing that--along with the reason given, you'd be trading a
concise language for an extremely verbose one. ;)
Furthermore, the C
preprocessor is a very simple macro processor. When you try to do
something non-trivial, you are likely to find it either impossible or
unnecessarily hard to do.
Which is why you have libraries that specialize in this sort of thing.
The const, inline, template, and namespace
mechanisms are intended as alternatives to many traditional uses of
preprocessor constructs.
And for many purposes, they are great alternatives. As I've said before, in
nearly all situations, these are better alternatives to their corresponding
macro formulations.
Page 163:

"7.9 Advice

[1] Be suspicious of non-const reference arguments; if you want the
function to modify its arguments, use pointers and value return
instead; 5.5. [2] Use const reference arguments when you need to
minimize copying of arguments; 5.5.
[3] Use const extensively and consistently; 7.2.
[4] Avoid macros; 7.8."


Which just illustrates Bjarne's well-known prejudice against macros resulting
from many of the traditional uses of them. So what?

Regards,
Paul Mensonides
Jul 22 '05 #41
David Harmon wrote:
On Sun, 18 Apr 2004 13:55:36 -0700 in comp.lang.c++, "Paul Mensonides"
<le******@comcast.net> wrote,
I'm talking about generating source code, be it templates or
overloaded functions or whatever (a lexical analyzer, perhaps) that
is impossible to achieve otherwise without an external code
generator or with excessive manual copying. The first requires
another build step--which is terrible in a library context--and the
second dramatically increases the number of maintenance points.


Lexical analyzer? Show me a C preprocessor implementation of anything
to compare with Joel de Guzman's Spirit parser template library.
http://spirit.sf.net


You want to know what is really funny about that? Joel de Guzman uses the
preprocessor in Spirit and Fusion for exactly the kind of stuff that I'm talking
about.

Regards,
Paul Mensonides
Jul 22 '05 #42
"Ioannis Vranos" <iv*@guesswh.at.emails.ru> wrote in message
news:c5***********@ulysses.noc.ntua.gr...

Namespaces do not exist to protect from name collisions. Namespaces are

the
Errata:

Namespaces do not exist to protect from general name collisions. Namespaces
are the


Regards,

Ioannis Vranos

Jul 22 '05 #43
"Paul Mensonides" <le******@comcast.net> wrote in message
news:Sa********************@comcast.com...

Which just illustrates Bjarne's well-known prejudice against macros resulting from many of the traditional uses of them. So what?

So we reach nowhere. :-)


Regards,

Ioannis Vranos

Jul 22 '05 #44
Ioannis Vranos wrote:
"Paul Mensonides" <le******@comcast.net> wrote in message Macros must be avoided where possible. In an effort to not hurt your
feelings we can rephrase that "Use macros only when needed".
You're not hurting my feelings, you're simply wrong and extremely naive.
Choose
whatever fits you better, they are both the same.
No, they are not. You simply have no concept of the things that I am talking
about because they are so far above your level of expertise in the fields in
which they apply.
And C++ is not C,
you may have been a C programmer for some long time and have done a
lot of real and excellent work with macros, but C++ is not C and in
most cases the language provides superior alternatives.
No, in *many* cases the language provides superior alternatives. What's amazing
here is your complete lack of willingness to accept that you don't know
everything. You think that you know what I'm talking about, but apparently you
have no idea. Otherwise, you wouldn't be saying that the functionality can be
replicated with, e.g., templates, because they can't.
On the other hand, if you *still* program in C and you use macros,
then what we discuss here does not apply.


I'm not talking about C, and the context that applies to what I'm saying applies
far more in C++ (though it still does in C).
As an aside, the core language is no more protected from name
clashes than the preprocessor. Namespaces serve to classify and
organize names, but they do not, at a language level, protect them.
The only things that stop name collision are

Namespaces do not exist to protect from name collisions. Namespaces
are the implementation of the modular programming paradigm


Which is exactly what I said, believe me, I know what namespaces are.

Regards,
Paul Mensonides
Jul 22 '05 #45
Kevin Goodsell <us*********************@neverbox.com> spoke thus:
'Evil' is a technical term in C++ circles. It doesn't mean "not to be
used under any circumstances". This is in the FAQ.


Indeed, and I'm sorry I didn't consider that FAQt (to make a pun, or
something) before making my claim.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #46
David Harmon <so****@netcom.com> spoke thus:
Example?


This is belated, and I'm sure you won't like it, but some time ago the
following appeared on comp.lang.c:

#define YEAR ((((__DATE__ [7] - '0') * 10 + (__DATE__ [8] - '0')) * 10 \
+ (__DATE__ [9] - '0')) * 10 + (__DATE__ [10] - '0'))

#define MONTH (__DATE__ [2] == 'n' ? 1 \
: __DATE__ [2] == 'b' ? 2 \
: __DATE__ [2] == 'r' ? (__DATE__ [0] == 'M' ? 3 : 4) \
: __DATE__ [2] == 'y' ? 5 \
: __DATE__ [2] == 'n' ? 6 \
: __DATE__ [2] == 'l' ? 7 \
: __DATE__ [2] == 'g' ? 8 \
: __DATE__ [2] == 'p' ? 9 \
: __DATE__ [2] == 't' ? 10 \
: __DATE__ [2] == 'v' ? 11 : 12)

#define DAY ((__DATE__ [4] == ' ' ? 0 : __DATE__ [4] - '0') * 10 \
+ (__DATE__ [5] - '0'))

#define DATE_AS_INT (((YEAR - 2000) * 12 + MONTH) * 31 + DAY)

It's nothing if not ingenious :)

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #47

"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in message
news:c6**********@chessie.cirr.com...
David Harmon <so****@netcom.com> spoke thus:
#define MONTH (__DATE__ [2] == 'n' ? 1 \
: __DATE__ [2] == 'b' ? 2 \
: __DATE__ [2] == 'r' ? (__DATE__ [0] == 'M' ? 3 : 4) \
: __DATE__ [2] == 'y' ? 5 \
: __DATE__ [2] == 'n' ? 6 \
: __DATE__ [2] == 'l' ? 7 \
: __DATE__ [2] == 'g' ? 8 \
: __DATE__ [2] == 'p' ? 9 \
: __DATE__ [2] == 't' ? 10 \
: __DATE__ [2] == 'v' ? 11 : 12)

how does this work for "january" and "june"?
Jul 22 '05 #48
David Harmon wrote:
Oh, that is all sophistry. You are saying basically, that you cannot
use templates in the identical fashion that you use macros. Well, so
what? The point is that you can accomplish the reasonable purpose
formerly served by macros, with templates, consts, and other C++
constructs that offer the advantages of being integrated with the
language. That you cannot perform exactly the same gyrations on the way
to getting there is not a bug, it's a feature.


Here's a question, not designed to be argumentative or contradictory but
rather a genuine request for information. What about macros similar to
assert(), that provide error-checking at a certain level of development
and then are removed in their entirety (test included) at another? Is
there another way to accomplish this without preprocessor constructs?

Brian Rodenborn
Jul 22 '05 #49

"Default User" <fi********@boeing.com.invalid> wrote in message
news:40***************@boeing.com.invalid...
David Harmon wrote:

Here's a question, not designed to be argumentative or contradictory but
rather a genuine request for information. What about macros similar to
assert(), that provide error-checking at a certain level of development
and then are removed in their entirety (test included) at another? Is
there another way to accomplish this without preprocessor constructs?

Brian Rodenborn


I believe this can be done with specialized templates. I think the BOOST
library has an example of this.

Jul 22 '05 #50

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

5 posts views Thread by lawrence | last post: by
25 posts views Thread by sql_server_2000_user | last post: by
2 posts views Thread by eric | last post: by
4 posts views Thread by marc.gibian | last post: by
10 posts views Thread by Adam Honek | last post: by
9 posts views Thread by fgh.vbn.rty | last post: by
xarzu
2 posts views Thread by xarzu | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.