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]"

per...@pluto.rain.com wrote:
Jim Bryant <kc5vdj.free...@gmail.com> 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.


_______________________________________________
freebsd-usb@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-usb
To unsubscribe, send any mail to "freebsd-usb-unsubscr...@freebsd.org"

Reply via email to