but then gnu does it's own thing too. my point stands though. any
actual evaluation of thirtytwok into something OTHER THAN (1<<15) in the
actual emitted code is IMPLEMENTATION-SPECIFIC.
in the case if gnu, you do appear to be right though, in disregard to K&R.
one could also argue that my return(0) is implementation-specific, as
exit(0) would be proper by the numbers.
my point still stands, that although it may be cute to have (1<<15) in
the define, it is not good practice.
9:21:33pm orb(13): cat bs4.c
#include <stdio.h>
#define thirtytwok (1<<15)
int main(void)
{
int toshiftornottoshift = thirtytwok;
printf("%d\n", toshiftornottoshift);
return(0);
}
9:21:39pm orb(14): cc -S -O2 -o bs4.s bs4.c
9:21:56pm orb(15): cat bs4.s
.file "bs4.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%d\n"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB3:
subq $8, %rsp
.LCFI0:
movl $32768, %esi
movl $.LC0, %edi
xorl %eax, %eax
call printf
xorl %eax, %eax
addq $8, %rsp
ret
.LFE3:
.size main, .-main
.section .eh_frame,"a",@progbits
.Lframe1:
.long .LECIE1-.LSCIE1
.LSCIE1:
.long 0x0
.byte 0x1
.string "zR"
.uleb128 0x1
.sleb128 -8
.byte 0x10
.uleb128 0x1
.byte 0x3
.byte 0xc
.uleb128 0x7
.uleb128 0x8
.byte 0x90
.uleb128 0x1
.align 8
.LECIE1:
.LSFDE1:
.long .LEFDE1-.LASFDE1
.LASFDE1:
.long .LASFDE1-.Lframe1
.long .LFB3
.long .LFE3-.LFB3
.uleb128 0x0
.byte 0x4
.long .LCFI0-.LFB3
.byte 0xe
.uleb128 0x10
.align 8
.LEFDE1:
.ident "GCC: (GNU) 4.2.1 20070719 [FreeBSD]"
9:22:00pm orb(16):
Jim Bryant wrote:
well, i can't speak for K&R 1978, as i can't currently find my copy,
but, for a quick brush up, you might want to read pages 80 and 81 from
K&R 2nd Ed. 1988.
your idea that the preprocessor will evaluate
#define thirtytwok (1<<15)
into 0x8000
at compile time is totally incorrect, and in fact wouldn't be in
compliance with standards. i have iso and fips handy, care for quotes?
microsoft used to do compile-time eval of preprocessor statements
instead of substitution, but that was implementation-specific and
non-standard.
From K&R, 2nd Ed. pp80-81 (1988):
4.11.2 Macro Substitution
A definition has the form
#define name replacement text
It calls for a macro substitution of the simplest kind - subsequent
occurrences of the token
name will be replaced by the replacement text. The name in a #define
has the same form as a
variable name; the replacement text is arbitrary. Normally the
replacement text is the rest of
the line, but a long definition may be continued onto several lines by
placing a \ at the end of
each line to be continued. The scope of a name defined with #define is
from its point of
definition to the end of the source file being compiled. A definition
may use previous
definitions. Substitutions are made only for tokens, and do not take
place within quoted
strings. For example, if YES is a defined name, there would be no
substitution in
printf("YES") or in YESMAN.
Any name may be defined with any replacement text. For example
#define forever for (;;) /* infinite loop */
defines a new word, forever, for an infinite loop.
It is also possible to define macros with arguments, so the
replacement text can be different
for different calls of the macro. As an example, define a macro called
max:
#define max(A, B) ((A) > (B) ? (A) : (B))
Although it looks like a function call, a use of max expands into
in-line code. Each occurrence
of a formal parameter (here A or B) will be replaced by the
corresponding actual argument.
Thus the line
x = max(p+q, r+s);
will be replaced by the line
x = ((p+q) > (r+s) ? (p+q) : (r+s));
So long as the arguments are treated consistently, this macro will
serve for any data type;
there is no need for different kinds of max for different data types,
as there would be with
functions.
81
If you examine the expansion of max, you will notice some pitfalls.
The expressions are
evaluated twice; this is bad if they involve side effects like
increment operators or input and
output. For instance
max(i++, j++) /* WRONG */
will increment the larger twice. Some care also has to be taken with
parentheses to make sure
the order of evaluation is preserved; consider what happens when the
macro
#define square(x) x * x /* WRONG */
is invoked as square(z+1).
Nonetheless, macros are valuable. One practical example comes from
<stdio.h>, in which
getchar and putchar are often defined as macros to avoid the run-time
overhead of a
function call per character processed. The functions in <ctype.h> are
also usually
implemented as macros.
Names may be undefined with #undef, usually to ensure that a routine
is really a function, not
a macro:
#undef getchar
int getchar(void) { ... }
Formal parameters are not replaced within quoted strings. If, however,
a parameter name is
preceded by a # in the replacement text, the combination will be
expanded into a quoted string
with the parameter replaced by the actual argument. This can be
combined with string
concatenation to make, for example, a debugging print macro:
#define dprint(expr) printf(#expr " = %g\n", expr)
When this is invoked, as in
dprint(x/y)
the macro is expanded into
printf("x/y" " = &g\n", x/y);
and the strings are concatenated, so the effect is
printf("x/y = &g\n", x/y);
Within the actual argument, each " is replaced by \" and each \ by \\,
so the result is a legal
string constant.
The preprocessor operator ## provides a way to concatenate actual
arguments during macro
expansion. If a parameter in the replacement text is adjacent to a ##,
the parameter is replaced
by the actual argument, the ## and surrounding white space are
removed, and the result is rescanned.
For example, the macro paste concatenates its two arguments:
#define paste(front, back) front ## back
so paste(name, 1) creates the token name1.
The rules for nested uses of ## are arcane; further details may be
found in Appendix A.
Exercise 4-14. Define a macro swap(t,x,y) that interchanges two
arguments of type t.
(Block structure will help.)
Jim Bryant wrote:
ummmm.. you were saying???
8:58:44pm orb(19): cat bs3.c
#include <stdio.h>
int main(void)
{
int toshiftornottoshift = 0x8000;
printf("%d\n", toshiftornottoshift);
return(0);
}
8:58:48pm orb(20): cc -S -O2 -o bs3.s bs3.c
8:58:53pm orb(21): cat bs3.s
.file "bs3.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%d\n"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB3:
subq $8, %rsp
.LCFI0:
/*
* this doesn't look like the compiler generates a shift to me.
*/
movl $32768, %esi
movl $.LC0, %edi
xorl %eax, %eax
call printf
xorl %eax, %eax
addq $8, %rsp
ret
.LFE3:
.size main, .-main
.section .eh_frame,"a",@progbits
.Lframe1:
.long .LECIE1-.LSCIE1
.LSCIE1:
.long 0x0
.byte 0x1
.string "zR"
.uleb128 0x1
.sleb128 -8
.byte 0x10
.uleb128 0x1
.byte 0x3
.byte 0xc
.uleb128 0x7
.uleb128 0x8
.byte 0x90
.uleb128 0x1
.align 8
.LECIE1:
.LSFDE1:
.long .LEFDE1-.LASFDE1
.LASFDE1:
.long .LASFDE1-.Lframe1
.long .LFB3
.long .LFE3-.LFB3
.uleb128 0x0
.byte 0x4
.long .LCFI0-.LFB3
.byte 0xe
.uleb128 0x10
.align 8
.LEFDE1:
.ident "GCC: (GNU) 4.2.1 20070719 [FreeBSD]"
[email protected] wrote:
Jim Bryant <[email protected]> wrote:
what kind of idiot defines a constant assignment for a 32k buffer
as a 15 bit left shift of 1?
clever, yes. but in production, stupid.
a constant should be just that, a constant, and thus require no
computation at runtime.
Er, did you bother to look at the generated code before spouting off?
Most compilers, even as far back as K&R 1st edition, will compute
constant expressions like that at compile time.
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-usb
To unsubscribe, send any mail to "[email protected]"