Date: Sun, 29 Aug 2010 21:26:43 -0500 From: Jim Bryant <kc5vdj.freebsd@gmail.com> To: perryh@pluto.rain.com Cc: freebsd-usb@freebsd.org Subject: Re: writing usb drivers under 8.x Message-ID: <4C7B16E3.8020808@gmail.com> In-Reply-To: <4C7B1510.1000601@gmail.com> References: <4C76AB76.4070806@gmail.com> <201008270856.43512.hselasky@c2i.net> <4C777D12.3040900@gmail.com> <201008271053.27731.hselasky@c2i.net> <4C78B0F4.4020002@gmail.com> <4c799393.wU/d2YpTieErDrD7%perryh@pluto.rain.com> <4C7B1139.4050106@gmail.com> <4C7B1510.1000601@gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
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]" >> >> perryh@pluto.rain.com wrote: >>> Jim Bryant <kc5vdj.freebsd@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. >>> >>> >> >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4C7B16E3.8020808>