1293 lines
48 KiB
Plaintext
1293 lines
48 KiB
Plaintext
This is Info file gcc.info, produced by Makeinfo-1.47 from the input
|
||
file gcc.texi.
|
||
|
||
This file documents the use and the internals of the GNU compiler.
|
||
|
||
Copyright (C) 1988, 1989, 1992 Free Software Foundation, Inc.
|
||
|
||
Permission is granted to make and distribute verbatim copies of this
|
||
manual provided the copyright notice and this permission notice are
|
||
preserved on all copies.
|
||
|
||
Permission is granted to copy and distribute modified versions of
|
||
this manual under the conditions for verbatim copying, provided also
|
||
that the sections entitled "GNU General Public License" and "Boycott"
|
||
are included exactly as in the original, and provided that the entire
|
||
resulting derived work is distributed under the terms of a permission
|
||
notice identical to this one.
|
||
|
||
Permission is granted to copy and distribute translations of this
|
||
manual into another language, under the above conditions for modified
|
||
versions, except that the sections entitled "GNU General Public
|
||
License" and "Boycott", and this permission notice, may be included in
|
||
translations approved by the Free Software Foundation instead of in the
|
||
original English.
|
||
|
||
|
||
File: gcc.info, Node: Cross-Compiler, Next: PA Install, Prev: Other Dir, Up: Installation
|
||
|
||
Building and Installing a Cross-Compiler
|
||
========================================
|
||
|
||
GNU CC can function as a cross-compiler for many machines, but not
|
||
all.
|
||
|
||
* Cross-compilers for the Mips as target do not work because the
|
||
auxiliary programs `mips-tdump.c' and `mips-tfile.c' can't be
|
||
compiled on anything but a Mips.
|
||
|
||
* Cross-compilers to or from the Vax probably don't work completely
|
||
because the Vax uses an incompatible floating point format (not
|
||
IEEE format).
|
||
|
||
Since GNU CC generates assembler code, you probably need a
|
||
cross-assembler that GNU CC can run, in order to produce object files.
|
||
If you want to link on other than the target machine, you need a
|
||
cross-linker as well. You also need header files and libraries suitable
|
||
for the target machine that you can install on the host machine.
|
||
|
||
To build GNU CC as a cross-compiler, you start out by running
|
||
`configure'. You must specify two different configureations, the host
|
||
and the target. Use the `--host=HOST' option for the host and
|
||
`--target=TARGET' to specify the target type. For example, here is how
|
||
to configure for a cross-compiler that runs on a hypothetical Intel 386
|
||
system and produces code for an HP 68030 system running BSD:
|
||
|
||
configure --target=m68k-hp-bsd4.3 --host=i386-bozotheclone-bsd4.3
|
||
|
||
Next you should install the cross-assembler and cross-linker (and
|
||
`ar' and `ranlib'). Put them in the directory `/usr/local/TARGET'.
|
||
The installation of GNU CC will find them there and copy or link them
|
||
to the proper place to find them when you run the cross-compiler later.
|
||
|
||
If you want to install any additional libraries to use with the
|
||
cross-compiler, put them in the directory `/usr/local/TARGET/lib'; all
|
||
files in that subdirectory will be installed in the proper place when
|
||
you install the cross-compiler. Likewise, put the header files for the
|
||
target machine in `/usr/local/TARGET/include'.
|
||
|
||
Then you can proceed just as for compiling a single-machine compiler
|
||
through the step of building stage 1.
|
||
|
||
When you are using a cross-compiler configuration, building stage 1
|
||
does not compile all of GNU CC. This is because one part of building,
|
||
the compilation of `libgcc2.c', requires use of the cross-compiler.
|
||
|
||
However, when you type `make install' to install the bulk of the
|
||
cross-compiler, that will also compile `libgcc2.c' and install the
|
||
resulting `libgcc.a'.
|
||
|
||
You will find it necessary to produce a substitute for `libgcc1.a'.
|
||
Normally this file is compiled with the "native compiler" for the
|
||
target machine; compiling it with GNU CC does not work. But compiling
|
||
it with the host machine's compiler also doesn't work--that produces a
|
||
file that would run on the host, and you need it to run on the target.
|
||
|
||
We can't give you any automatic way to produce this substitute. For
|
||
some targets, the subroutines in `libgcc1.c' are not actually used. You
|
||
need not provide the ones that won't be used. The ones that most
|
||
commonly are used are the multiplication, division and remainder
|
||
routines--many RISC machines rely on the library for this. One way to
|
||
make them work is to define the appropriate `perform_...' macros for
|
||
the subroutines that you need. If these definitions do not use the C
|
||
arithmetic operators that they are meant to implement, you might be
|
||
able to compile them with the cross-compiler you have just built.
|
||
|
||
Do not try to build stage 2 for a cross-compiler. It doesn't work to
|
||
rebuild GNU CC as a cross-compiler using the cross-compiler, because
|
||
that would produce a program that runs on the target machine, not on the
|
||
host. For example, if you compile a 386-to-68030 cross-compiler with
|
||
itself, the result will not be right either for the 386 (because it was
|
||
compiled into 68030 code) or for the 68030 (because it was configured
|
||
for a 386 as the host). If you want to compile GNU CC into 68030 code,
|
||
whether you compile it on a 68030 or with a cross-compiler on a 386, you
|
||
must specify a 68030 as the host when you configure it.
|
||
|
||
|
||
File: gcc.info, Node: PA Install, Next: Sun Install, Prev: Cross-Compiler, Up: Installation
|
||
|
||
Installing GNU CC on the HP Precision Architecture
|
||
==================================================
|
||
|
||
There are two variants of this CPU, called 1.0 and 1.1, which have
|
||
different machine descriptions. You must use the right one for your
|
||
machine. All 7NN machines and 8N7 machines use 1.1, while all other
|
||
8NN machines use 1.0.
|
||
|
||
The easiest way to handle this problem is to use `configure hpNNN'
|
||
or `configure hpNNN-hpux', where NNN is the model number of the
|
||
machine. Then `configure' will figure out if the machine is a 1.0 or
|
||
1.1. Use `uname -a' to find out the model number of your machine.
|
||
|
||
`-g' does not work on HP-UX, since that system uses a peculiar
|
||
debugging format which GNU CC does not know about. There is a
|
||
preliminary version available of some modified GNU tools including the
|
||
GDB debugger which do work with GNU CC for debugging. You can get them
|
||
by anonymous ftp from `mancos.cs.utah.edu' in the `dist' subdirectory.
|
||
You would need to install GAS in the file
|
||
|
||
/usr/local/lib/gcc-lib/CONFIGURATION/GCCVERSION/as
|
||
|
||
where CONFIGURATION is the configuration name (perhaps `hpNNN-hpux')
|
||
and GCCVERSION is the GNU CC version number.
|
||
|
||
If you do this, delete the line
|
||
|
||
#undef DBX_DEBUGGING_INFO
|
||
|
||
from `tm.h' before you build GNU CC, to enable generation of debugging
|
||
information.
|
||
|
||
|
||
File: gcc.info, Node: Sun Install, Next: 3b1 Install, Prev: PA Install, Up: Installation
|
||
|
||
Installing GNU CC on the Sun
|
||
============================
|
||
|
||
Make sure the environment variable `FLOAT_OPTION' is not set when
|
||
you compile `libgcc.a'. If this option were set to `f68881' when
|
||
`libgcc.a' is compiled, the resulting code would demand to be linked
|
||
with a special startup file and would not link properly without special
|
||
pains.
|
||
|
||
There is a bug in `alloca' in certain versions of the Sun library.
|
||
To avoid this bug, install the binaries of GNU CC that were compiled by
|
||
GNU CC. They use `alloca' as a built-in function and never the one in
|
||
the library.
|
||
|
||
Some versions of the Sun compiler crash when compiling GNU CC. The
|
||
problem is a segmentation fault in cpp. This problem seems to be due to
|
||
the bulk of data in the environment variables. You may be able to avoid
|
||
it by using the following command to compile GNU CC with Sun CC:
|
||
|
||
make CC="TERMCAP=x OBJS=x LIBFUNCS=x STAGESTUFF=x cc"
|
||
|
||
|
||
File: gcc.info, Node: 3b1 Install, Next: Unos Install, Prev: Sun Install, Up: Installation
|
||
|
||
Installing GNU CC on the 3b1
|
||
============================
|
||
|
||
Installing GNU CC on the 3b1 is difficult if you do not already have
|
||
GNU CC running, due to bugs in the installed C compiler. However, the
|
||
following procedure might work. We are unable to test it.
|
||
|
||
1. Comment out the `#include "config.h"' line on line 37 of `cccp.c'
|
||
and do `make cpp'. This makes a preliminary version of GNU cpp.
|
||
|
||
2. Save the old `/lib/cpp' and copy the preliminary GNU cpp to that
|
||
file name.
|
||
|
||
3. Undo your change in `cccp.c', or reinstall the original version,
|
||
and do `make cpp' again.
|
||
|
||
4. Copy this final version of GNU cpp into `/lib/cpp'.
|
||
|
||
5. Replace every occurrence of `obstack_free' in the file `tree.c'
|
||
with `_obstack_free'.
|
||
|
||
6. Run `make' to get the first-stage GNU CC.
|
||
|
||
7. Reinstall the original version of `/lib/cpp'.
|
||
|
||
8. Now you can compile GNU CC with itself and install it in the normal
|
||
fashion.
|
||
|
||
|
||
File: gcc.info, Node: Unos Install, Next: VMS Install, Prev: 3b1 Install, Up: Installation
|
||
|
||
Installing GNU CC on Unos
|
||
=========================
|
||
|
||
Use `configure unos' for building on Unos.
|
||
|
||
The Unos assembler is named `casm' instead of `as'. For some
|
||
strange reason linking `/bin/as' to `/bin/casm' changes the behavior,
|
||
and does not work. So, when installing GNU CC, you should install the
|
||
following script as `as' in the subdirectory where the passes of GCC
|
||
are installed:
|
||
|
||
#!/bin/sh
|
||
casm $*
|
||
|
||
The default Unos library is named `libunos.a' instead of `libc.a'.
|
||
To allow GNU CC to function, either change all references to `-lc' in
|
||
`gcc.c' to `-lunos' or link `/lib/libc.a' to `/lib/libunos.a'.
|
||
|
||
When compiling GNU CC with the standard compiler, to overcome bugs in
|
||
the support of `alloca', do not use `-O' when making stage 2. Then use
|
||
the stage 2 compiler with `-O' to make the stage 3 compiler. This
|
||
compiler will have the same characteristics as the usual stage 2
|
||
compiler on other systems. Use it to make a stage 4 compiler and
|
||
compare that with stage 3 to verify proper compilation.
|
||
|
||
(Perhaps simply defining `ALLOCA' in `x-crds' as described in the
|
||
comments there will make the above paragraph superfluous. Please
|
||
inform us of whether this works.)
|
||
|
||
Unos uses memory segmentation instead of demand paging, so you will
|
||
need a lot of memory. 5 Mb is barely enough if no other tasks are
|
||
running. If linking `cc1' fails, try putting the object files into a
|
||
library and linking from that library.
|
||
|
||
|
||
File: gcc.info, Node: VMS Install, Prev: Unos Install, Up: Installation
|
||
|
||
Installing GNU CC on VMS
|
||
========================
|
||
|
||
The VMS version of GNU CC is distributed in a backup saveset
|
||
containing both source code and precompiled binaries.
|
||
|
||
To install the `gcc' command so you can use the compiler easily, in
|
||
the same manner as you use the VMS C compiler, you must install the VMS
|
||
CLD file for GNU CC as follows:
|
||
|
||
1. Define the VMS logical names `GNU_CC' and `GNU_CC_INCLUDE' to
|
||
point to the directories where the GNU CC executables (`gcc-cpp',
|
||
`gcc-cc1', etc.) and the C include files are kept. This should be
|
||
done with the commands:
|
||
|
||
$ assign /system /translation=concealed -
|
||
disk:[gcc.] gnu_cc
|
||
$ assign /system /translation=concealed -
|
||
disk:[gcc.include.] gnu_cc_include
|
||
|
||
with the appropriate disk and directory names. These commands can
|
||
be placed in your system startup file so they will be executed
|
||
whenever the machine is rebooted. You may, if you choose, do this
|
||
via the `GCC_INSTALL.COM' script in the `[GCC]' directory.
|
||
|
||
2. Install the `GCC' command with the command line:
|
||
|
||
$ set command /table=sys$common:[syslib]dcltables -
|
||
/output=sys$common:[syslib]dcltables gnu_cc:[000000]gcc
|
||
$ install replace sys$common:[syslib]dcltables
|
||
|
||
3. To install the help file, do the following:
|
||
|
||
$ lib/help sys$library:helplib.hlb gcc.hlp
|
||
|
||
Now you can invoke the compiler with a command like `gcc /verbose
|
||
file.c', which is equivalent to the command `gcc -v -c file.c' in
|
||
Unix.
|
||
|
||
If you wish to use GNU C++ you must first install GNU CC, and then
|
||
perform the following steps:
|
||
|
||
1. Define the VMS logical name `GNU_GXX_INCLUDE' to point to the
|
||
directory where the preprocessor will search for the C++ header
|
||
files. This can be done with the command:
|
||
|
||
$ assign /system /translation=concealed -
|
||
disk:[gcc.gxx_include.] gnu_gxx_include
|
||
|
||
with the appropriate disk and directory name. If you are going to
|
||
be using libg++, this is where the libg++ install procedure will
|
||
install the libg++ header files.
|
||
|
||
2. Obtain the file `gcc-cc1plus.exe', and place this in the same
|
||
directory that `gcc-cc1.exe' is kept.
|
||
|
||
The GNU C++ compiler can be invoked with a command like `gcc /plus
|
||
/verbose file.cc', which is equivalent to the command `g++ -v -c
|
||
file.cc' in Unix.
|
||
|
||
We try to put corresponding binaries and sources on the VMS
|
||
distribution tape. But sometimes the binaries will be from an older
|
||
version that the sources, because we don't always have time to update
|
||
them. (Use the `/version' option to determine the version number of
|
||
the binaries and compare it with the source file `version.c' to tell
|
||
whether this is so.) In this case, you should use the binaries you get
|
||
to recompile the sources. If you must recompile, here is how:
|
||
|
||
1. Copy the file `vms.h' to `tm.h', `xm-vms.h' to `config.h',
|
||
`vax.md' to `md.' and `vax.c' to `aux-output.c'. The files to be
|
||
copied are found in the subdirectory named `config'; they should
|
||
be copied to the main directory of GNU CC. If you wish, you may
|
||
use the command file `config-gcc.com' to perform these steps for
|
||
you.
|
||
|
||
2. Setup the logical names and command tables as defined above. In
|
||
addition, define the VMS logical name `GNU_BISON' to point at the
|
||
to the directories where the Bison executable is kept. This
|
||
should be done with the command:
|
||
|
||
$ assign /system /translation=concealed -
|
||
disk:[bison.] gnu_bison
|
||
|
||
You may, if you choose, use the `INSTALL_BISON.COM' script in the
|
||
`[BISON]' directory.
|
||
|
||
3. Install the `BISON' command with the command line:
|
||
|
||
$ set command /table=sys$common:[syslib]dcltables -
|
||
/output=sys$common:[syslib]dcltables -
|
||
gnu_bison:[000000]bison
|
||
$ install replace sys$common:[syslib]dcltables
|
||
|
||
4. Type `@make-gcc' to recompile everything (alternatively, you may
|
||
submit the file `make-gcc.com' to a batch queue). If you wish to
|
||
build the GNU C++ compiler as well as the GNU CC compiler, you must
|
||
first edit `make-gcc.com' and follow the instructions that appear
|
||
in the comments.
|
||
|
||
5. In order to use GCC, you need a library of functions which GCC
|
||
compiled code will call to perform certain tasks, and these
|
||
functions are defined in the file `libgcc2.c'. To compile this
|
||
you should use the command procedure `make-l2.com', which will
|
||
generate the library `libgcc2.olb'. `libgcc2.olb' should be built
|
||
using the compiler built from the same distribution that
|
||
`libgcc2.c' came from, and `make-gcc.com' will automatically do
|
||
all of this for you.
|
||
|
||
To install the library, use the following commands:
|
||
|
||
$ lib gnu_cc:[000000]gcclib/delete=(new,eprintf)
|
||
$ lib libgcc2/extract=*/output=libgcc2.obj
|
||
$ lib gnu_cc:[000000]gcclib libgcc2.obj
|
||
|
||
The first command simply removes old modules that will be replaced
|
||
with modules from libgcc2. If the VMS librarian complains about
|
||
those modules not being present, simply ignore the message and
|
||
continue on with the next command.
|
||
|
||
Whenever you update the compiler on your system, you should also
|
||
update the library with the above procedure.
|
||
|
||
You may wish to build GCC in such a way that no files are written
|
||
to the directory where the source files reside. An example would
|
||
be the when the source files are on a read-only disk. In these
|
||
cases, execute the following DCL commands (substituting your
|
||
actual path names):
|
||
|
||
$ assign dua0:[gcc.build_dir.]tran=conc, -
|
||
dua1:[gcc.source_dir.]/tran=conc gcc_build
|
||
$ set default gcc_build:[000000]
|
||
|
||
where `dua1:[gcc.source_dir.]' contains the source code, and
|
||
`dua0:[gcc.build_dir.]' is meant to contain all of the generated
|
||
object files and executables. Once you have done this, you can
|
||
proceed building GCC as described above. (Keep in mind that
|
||
`gcc_build' is a rooted logical name, and thus the device names in
|
||
each element of the search list must be an actual physical device
|
||
name rather than another rooted logical name).
|
||
|
||
*If you are building GNU CC with a previous version of GNU CC, you
|
||
also should check to see that you have the newest version of the
|
||
assembler*. In particular, GNU CC version 2 treats global constant
|
||
variables slightly differently from GNU CC version 1, and GAS
|
||
version 1.38.1 does not have the patches required to work with GCC
|
||
version 2. If you use GAS 1.38.1, then `extern const' variables
|
||
will not have the read-only bit set, and the linker will generate
|
||
warning messages about mismatched psect attributes for these
|
||
variables. These warning messages are merely a nuisance, and can
|
||
safely be ignored.
|
||
|
||
If you are compiling with a version of GNU CC older than 1.33,
|
||
specify `/DEFINE=("inline=")' as an option in all the
|
||
compilations. This requires editing all the `gcc' commands in
|
||
`make-cc1.com'. (The older versions had problems supporting
|
||
`inline'.) Once you have a working 1.33 or newer GNU CC, you can
|
||
change this file back.
|
||
|
||
Under previous versions of GNU CC, the generated code would
|
||
occasionally give strange results when linked to the sharable `VAXCRTL'
|
||
library. Now this should work.
|
||
|
||
Even with this version, however, GNU CC itself should not be linked
|
||
to the sharable `VAXCRTL'. The `qsort' routine supplied with `VAXCRTL'
|
||
has a bug which can cause a compiler crash.
|
||
|
||
Similarly, the preprocessor should not be linked to the sharable
|
||
`VAXCRTL'. The `strncat' routine supplied with `VAXCRTL' has a bug
|
||
which can cause the preprocessor to go into an infinite loop.
|
||
|
||
If you attempt to link to the sharable `VAXCRTL', the VMS linker
|
||
will strongly resist any effort to force it to use the `qsort' and
|
||
`strncat' routines from `gcclib'. Until the bugs in `VAXCRTL' have
|
||
been fixed, linking any of the compiler components to the sharable
|
||
VAXCRTL is not recommended. (These routines can be bypassed by placing
|
||
duplicate copies of `qsort' and `strncat' in `gcclib' under different
|
||
names, and patching the compiler sources to use these routines). Both
|
||
of the bugs in `VAXCRTL' are still present in VMS version 5.4-1, which
|
||
is the most recent version as of this writing.
|
||
|
||
The executables that are generated by `make-cc1.com' and
|
||
`make-cccp.com' use the nonshared version of `VAXCRTL' (and thus use
|
||
the `qsort' and `strncat' routines from `gcclib.olb').
|
||
|
||
|
||
File: gcc.info, Node: Extensions, Next: Trouble, Prev: Installation, Up: Top
|
||
|
||
GNU Extensions to the C Language
|
||
********************************
|
||
|
||
GNU C provides several language features not found in ANSI standard
|
||
C. (The `-pedantic' option directs GNU CC to print a warning message if
|
||
any of these features is used.) To test for the availability of these
|
||
features in conditional compilation, check for a predefined macro
|
||
`__GNUC__', which is always defined under GNU CC.
|
||
|
||
* Menu:
|
||
|
||
* Statement Exprs:: Putting statements and declarations inside expressions.
|
||
* Local Labels:: Labels local to a statement-expression.
|
||
* Labels as Values:: Getting pointers to labels, and computed gotos.
|
||
* Nested Functions:: As in Algol and Pascal, lexical scoping of functions.
|
||
* Naming Types:: Giving a name to the type of some expression.
|
||
* Typeof:: `typeof': referring to the type of an expression.
|
||
* Lvalues:: Using `?:', `,' and casts in lvalues.
|
||
* Conditionals:: Omitting the middle operand of a `?:' expression.
|
||
* Long Long:: Double-word integers--`long long int'.
|
||
* Zero Length:: Zero-length arrays.
|
||
* Variable Length:: Arrays whose length is computed at run time.
|
||
* Macro Varargs:: Macros with variable number of arguments.
|
||
* Subscripting:: Any array can be subscripted, even if not an lvalue.
|
||
* Pointer Arith:: Arithmetic on `void'-pointers and function pointers.
|
||
* Initializers:: Non-constant initializers.
|
||
* Constructors:: Constructor expressions give structures, unions
|
||
or arrays as values.
|
||
* Labeled Elements:: Labeling elements of initializers.
|
||
* Cast to Union:: Casting to union type from any member of the union.
|
||
* Case Ranges:: `case 1 ... 9' and such.
|
||
* Function Attributes:: Declaring that functions have no side effects,
|
||
or that they can never return.
|
||
* Function Prototypes:: Prototype declarations and old-style definitions.
|
||
* Dollar Signs:: Dollar sign is allowed in identifiers.
|
||
* Character Escapes:: `\e' stands for the character ESC.
|
||
* Variable Attributes:: Specifying attributes of variables.
|
||
* Alignment:: Inquiring about the alignment of a type or variable.
|
||
* Inline:: Defining inline functions (as fast as macros).
|
||
* Extended Asm:: Assembler instructions with C expressions as operands.
|
||
(With them you can define "built-in" functions.)
|
||
* Asm Labels:: Specifying the assembler name to use for a C symbol.
|
||
* Explicit Reg Vars:: Defining variables residing in specified registers.
|
||
* Alternate Keywords:: `__const__', `__asm__', etc., for header files.
|
||
* Incomplete Enums:: `enum foo;', with details to follow.
|
||
|
||
|
||
File: gcc.info, Node: Statement Exprs, Next: Local Labels, Up: Extensions
|
||
|
||
Statements and Declarations within Expressions
|
||
==============================================
|
||
|
||
A compound statement enclosed in parentheses may appear as an
|
||
expression in GNU C. This allows you to use loops, switches, and local
|
||
variables within an expression.
|
||
|
||
Recall that a compound statement is a sequence of statements
|
||
surrounded by braces; in this construct, parentheses go around the
|
||
braces. For example:
|
||
|
||
({ int y = foo (); int z;
|
||
if (y > 0) z = y;
|
||
else z = - y;
|
||
z; })
|
||
|
||
is a valid (though slightly more complex than necessary) expression for
|
||
the absolute value of `foo ()'.
|
||
|
||
The last thing in the compound statement should be an expression
|
||
followed by a semicolon; the value of this subexpression serves as the
|
||
value of the entire construct. (If you use some other kind of statement
|
||
last within the braces, the construct has type `void', and thus
|
||
effectively no value.)
|
||
|
||
This feature is especially useful in making macro definitions "safe"
|
||
(so that they evaluate each operand exactly once). For example, the
|
||
"maximum" function is commonly defined as a macro in standard C as
|
||
follows:
|
||
|
||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||
|
||
But this definition computes either A or B twice, with bad results if
|
||
the operand has side effects. In GNU C, if you know the type of the
|
||
operands (here let's assume `int'), you can define the macro safely as
|
||
follows:
|
||
|
||
#define maxint(a,b) \
|
||
({int _a = (a), _b = (b); _a > _b ? _a : _b; })
|
||
|
||
Embedded statements are not allowed in constant expressions, such as
|
||
the value of an enumeration constant, the width of a bit field, or the
|
||
initial value of a static variable.
|
||
|
||
If you don't know the type of the operand, you can still do this,
|
||
but you must use `typeof' (*note Typeof::.) or type naming (*note
|
||
Naming Types::.).
|
||
|
||
|
||
File: gcc.info, Node: Local Labels, Next: Labels as Values, Prev: Statement Exprs, Up: Extensions
|
||
|
||
Locally Declared Labels
|
||
=======================
|
||
|
||
Each statement expression is a scope in which "local labels" can be
|
||
declared. A local label is simply an identifier; you can jump to it
|
||
with an ordinary `goto' statement, but only from within the statement
|
||
expression it belongs to.
|
||
|
||
A local label declaration looks like this:
|
||
|
||
__label__ LABEL;
|
||
|
||
or
|
||
|
||
__label__ LABEL1, LABEL2, ...;
|
||
|
||
Local label declarations must come at the beginning of the statement
|
||
expression, right after the `({', before any ordinary declarations.
|
||
|
||
The label declaration defines the label *name*, but does not define
|
||
the label itself. You must do this in the usual way, with `LABEL:',
|
||
within the statements of the statement expression.
|
||
|
||
The local label feature is useful because statement expressions are
|
||
often used in macros. If the macro contains nested loops, a `goto' can
|
||
be useful for breaking out of them. However, an ordinary label whose
|
||
scope is the whole function cannot be used: if the macro can be
|
||
expanded several times in one function, the label will be multiply
|
||
defined in that function. A local label avoids this problem. For
|
||
example:
|
||
|
||
#define SEARCH(array, target) \
|
||
({ \
|
||
__label__ found; \
|
||
typeof (target) _SEARCH_target = (target); \
|
||
typeof (*(array)) *_SEARCH_array = (array); \
|
||
int i, j; \
|
||
int value; \
|
||
for (i = 0; i < max; i++) \
|
||
for (j = 0; j < max; j++) \
|
||
if (_SEARCH_array[i][j] == _SEARCH_target) \
|
||
{ value = i; goto found; } \
|
||
value = -1; \
|
||
found: \
|
||
value; \
|
||
})
|
||
|
||
|
||
File: gcc.info, Node: Labels as Values, Next: Nested Functions, Prev: Local Labels, Up: Extensions
|
||
|
||
Labels as Values
|
||
================
|
||
|
||
You can get the address of a label defined in the current function
|
||
(or a containing function) with the unary operator `&&'. The value has
|
||
type `void *'. This value is a constant and can be used wherever a
|
||
constant of that type is valid. For example:
|
||
|
||
void *ptr;
|
||
...
|
||
ptr = &&foo;
|
||
|
||
To use these values, you need to be able to jump to one. This is
|
||
done with the computed goto statement(1), `goto *EXP;'. For example,
|
||
|
||
goto *ptr;
|
||
|
||
Any expression of type `void *' is allowed.
|
||
|
||
One way of using these constants is in initializing a static array
|
||
that will serve as a jump table:
|
||
|
||
static void *array[] = { &&foo, &&bar, &&hack };
|
||
|
||
Then you can select a label with indexing, like this:
|
||
|
||
goto *array[i];
|
||
|
||
Note that this does not check whether the subscript is in bounds--array
|
||
indexing in C never does that.
|
||
|
||
Such an array of label values serves a purpose much like that of the
|
||
`switch' statement. The `switch' statement is cleaner, so use that
|
||
rather than an array unless the problem does not fit a `switch'
|
||
statement very well.
|
||
|
||
Another use of label values is in an interpreter for threaded code.
|
||
The labels within the interpreter function can be stored in the
|
||
threaded code for super-fast dispatching.
|
||
|
||
You can use this mechanism to jump to code in a different function.
|
||
If you do that, totally unpredictable things will happen. The best way
|
||
to avoid this is to store the label address only in automatic variables
|
||
and never pass it as an argument.
|
||
|
||
---------- Footnotes ----------
|
||
|
||
(1) The analogous feature in Fortran is called an assigned goto,
|
||
but that name seems inappropriate in C, where one can do more than
|
||
simply store label addresses in label variables.
|
||
|
||
|
||
File: gcc.info, Node: Nested Functions, Next: Naming Types, Prev: Labels as Values, Up: Extensions
|
||
|
||
Nested Functions
|
||
================
|
||
|
||
A "nested function" is a function defined inside another function.
|
||
The nested function's name is local to the block where it is defined.
|
||
For example, here we define a nested function named `square', and call
|
||
it twice:
|
||
|
||
foo (double a, double b)
|
||
{
|
||
double square (double z) { return z * z; }
|
||
|
||
return square (a) + square (b);
|
||
}
|
||
|
||
The nested function can access all the variables of the containing
|
||
function that are visible at the point of its definition. This is
|
||
called "lexical scoping". For example, here we show a nested function
|
||
which uses an inherited variable named `offset':
|
||
|
||
bar (int *array, int offset, int size)
|
||
{
|
||
int access (int *array, int index)
|
||
{ return array[index + offset]; }
|
||
int i;
|
||
...
|
||
for (i = 0; i < size; i++)
|
||
... access (array, i) ...
|
||
}
|
||
|
||
It is possible to call the nested function from outside the scope of
|
||
its name by storing its address or passing the address to another
|
||
function:
|
||
|
||
hack (int *array, int size)
|
||
{
|
||
void store (int index, int value)
|
||
{ array[index] = value; }
|
||
|
||
intermediate (store, size);
|
||
}
|
||
|
||
Here, the function `intermediate' receives the address of `store' as
|
||
an argument. If `intermediate' calls `store', the arguments given to
|
||
`store' are used to store into `array'. But this technique works only
|
||
so long as the containing function (`hack', in this example) does not
|
||
exit. If you try to call the nested function through its address after
|
||
the containing function has exited, all hell will break loose.
|
||
|
||
A nested function can jump to a label inherited from a containing
|
||
function, provided the label was explicitly declared in the containing
|
||
function (*note Local Labels::.). Such a jump returns instantly to the
|
||
containing function, exiting the nested function which did the `goto'
|
||
and any intermediate functions as well. Here is an example:
|
||
|
||
bar (int *array, int offset, int size)
|
||
{
|
||
__label__ failure;
|
||
int access (int *array, int index)
|
||
{
|
||
if (index > size)
|
||
goto failure;
|
||
return array[index + offset];
|
||
}
|
||
int i;
|
||
...
|
||
for (i = 0; i < size; i++)
|
||
... access (array, i) ...
|
||
...
|
||
return 0;
|
||
|
||
/* Control comes here from `access'
|
||
if it detects an error. */
|
||
failure:
|
||
return -1;
|
||
}
|
||
|
||
A nested function always has internal linkage. Declaring one with
|
||
`extern' is erroneous. If you need to declare the nested function
|
||
before its definition, use `auto' (which is otherwise meaningless for
|
||
function declarations).
|
||
|
||
bar (int *array, int offset, int size)
|
||
{
|
||
__label__ failure;
|
||
auto int access (int *, int);
|
||
...
|
||
int access (int *array, int index)
|
||
{
|
||
if (index > size)
|
||
goto failure;
|
||
return array[index + offset];
|
||
}
|
||
...
|
||
}
|
||
|
||
|
||
File: gcc.info, Node: Naming Types, Next: Typeof, Prev: Nested Functions, Up: Extensions
|
||
|
||
Naming an Expression's Type
|
||
===========================
|
||
|
||
You can give a name to the type of an expression using a `typedef'
|
||
declaration with an initializer. Here is how to define NAME as a type
|
||
name for the type of EXP:
|
||
|
||
typedef NAME = EXP;
|
||
|
||
This is useful in conjunction with the statements-within-expressions
|
||
feature. Here is how the two together can be used to define a safe
|
||
"maximum" macro that operates on any arithmetic type:
|
||
|
||
#define max(a,b) \
|
||
({typedef _ta = (a), _tb = (b); \
|
||
_ta _a = (a); _tb _b = (b); \
|
||
_a > _b ? _a : _b; })
|
||
|
||
The reason for using names that start with underscores for the local
|
||
variables is to avoid conflicts with variable names that occur within
|
||
the expressions that are substituted for `a' and `b'. Eventually we
|
||
hope to design a new form of declaration syntax that allows you to
|
||
declare variables whose scopes start only after their initializers;
|
||
this will be a more reliable way to prevent such conflicts.
|
||
|
||
|
||
File: gcc.info, Node: Typeof, Next: Lvalues, Prev: Naming Types, Up: Extensions
|
||
|
||
Referring to a Type with `typeof'
|
||
=================================
|
||
|
||
Another way to refer to the type of an expression is with `typeof'.
|
||
The syntax of using of this keyword looks like `sizeof', but the
|
||
construct acts semantically like a type name defined with `typedef'.
|
||
|
||
There are two ways of writing the argument to `typeof': with an
|
||
expression or with a type. Here is an example with an expression:
|
||
|
||
typeof (x[0](1))
|
||
|
||
This assumes that `x' is an array of functions; the type described is
|
||
that of the values of the functions.
|
||
|
||
Here is an example with a typename as the argument:
|
||
|
||
typeof (int *)
|
||
|
||
Here the type described is that of pointers to `int'.
|
||
|
||
If you are writing a header file that must work when included in
|
||
ANSI C programs, write `__typeof__' instead of `typeof'. *Note
|
||
Alternate Keywords::.
|
||
|
||
A `typeof'-construct can be used anywhere a typedef name could be
|
||
used. For example, you can use it in a declaration, in a cast, or
|
||
inside of `sizeof' or `typeof'.
|
||
|
||
* This declares `y' with the type of what `x' points to.
|
||
|
||
typeof (*x) y;
|
||
|
||
* This declares `y' as an array of such values.
|
||
|
||
typeof (*x) y[4];
|
||
|
||
* This declares `y' as an array of pointers to characters:
|
||
|
||
typeof (typeof (char *)[4]) y;
|
||
|
||
It is equivalent to the following traditional C declaration:
|
||
|
||
char *y[4];
|
||
|
||
To see the meaning of the declaration using `typeof', and why it
|
||
might be a useful way to write, let's rewrite it with these macros:
|
||
|
||
#define pointer(T) typeof(T *)
|
||
#define array(T, N) typeof(T [N])
|
||
|
||
Now the declaration can be rewritten this way:
|
||
|
||
array (pointer (char), 4) y;
|
||
|
||
Thus, `array (pointer (char), 4)' is the type of arrays of 4
|
||
pointers to `char'.
|
||
|
||
|
||
File: gcc.info, Node: Lvalues, Next: Conditionals, Prev: Typeof, Up: Extensions
|
||
|
||
Generalized Lvalues
|
||
===================
|
||
|
||
Compound expressions, conditional expressions and casts are allowed
|
||
as lvalues provided their operands are lvalues. This means that you
|
||
can take their addresses or store values into them.
|
||
|
||
For example, a compound expression can be assigned, provided the last
|
||
expression in the sequence is an lvalue. These two expressions are
|
||
equivalent:
|
||
|
||
(a, b) += 5
|
||
a, (b += 5)
|
||
|
||
Similarly, the address of the compound expression can be taken.
|
||
These two expressions are equivalent:
|
||
|
||
&(a, b)
|
||
a, &b
|
||
|
||
A conditional expression is a valid lvalue if its type is not void
|
||
and the true and false branches are both valid lvalues. For example,
|
||
these two expressions are equivalent:
|
||
|
||
(a ? b : c) = 5
|
||
(a ? b = 5 : (c = 5))
|
||
|
||
A cast is a valid lvalue if its operand is an lvalue. A simple
|
||
assignment whose left-hand side is a cast works by converting the
|
||
right-hand side first to the specified type, then to the type of the
|
||
inner left-hand side expression. After this is stored, the value is
|
||
converted back to the specified type to become the value of the
|
||
assignment. Thus, if `a' has type `char *', the following two
|
||
expressions are equivalent:
|
||
|
||
(int)a = 5
|
||
(int)(a = (char *)(int)5)
|
||
|
||
An assignment-with-arithmetic operation such as `+=' applied to a
|
||
cast performs the arithmetic using the type resulting from the cast,
|
||
and then continues as in the previous case. Therefore, these two
|
||
expressions are equivalent:
|
||
|
||
(int)a += 5
|
||
(int)(a = (char *)(int) ((int)a + 5))
|
||
|
||
You cannot take the address of an lvalue cast, because the use of its
|
||
address would not work out coherently. Suppose that `&(int)f' were
|
||
permitted, where `f' has type `float'. Then the following statement
|
||
would try to store an integer bit-pattern where a floating point number
|
||
belongs:
|
||
|
||
*&(int)f = 1;
|
||
|
||
This is quite different from what `(int)f = 1' would do--that would
|
||
convert 1 to floating point and store it. Rather than cause this
|
||
inconsistency, we think it is better to prohibit use of `&' on a cast.
|
||
|
||
If you really do want an `int *' pointer with the address of `f',
|
||
you can simply write `(int *)&f'.
|
||
|
||
|
||
File: gcc.info, Node: Conditionals, Next: Long Long, Prev: Lvalues, Up: Extensions
|
||
|
||
Conditional Expressions with Omitted Operands
|
||
=============================================
|
||
|
||
The middle operand in a conditional expression may be omitted. Then
|
||
if the first operand is nonzero, its value is the value of the
|
||
conditional expression.
|
||
|
||
Therefore, the expression
|
||
|
||
x ? : y
|
||
|
||
has the value of `x' if that is nonzero; otherwise, the value of `y'.
|
||
|
||
This example is perfectly equivalent to
|
||
|
||
x ? x : y
|
||
|
||
In this simple case, the ability to omit the middle operand is not
|
||
especially useful. When it becomes useful is when the first operand
|
||
does, or may (if it is a macro argument), contain a side effect. Then
|
||
repeating the operand in the middle would perform the side effect
|
||
twice. Omitting the middle operand uses the value already computed
|
||
without the undesirable effects of recomputing it.
|
||
|
||
|
||
File: gcc.info, Node: Long Long, Next: Zero Length, Prev: Conditionals, Up: Extensions
|
||
|
||
Double-Word Integers
|
||
====================
|
||
|
||
GNU C supports data types for integers that are twice as long as
|
||
`long int'. Simply write `long long int' for a signed integer, or
|
||
`unsigned long long int' for an unsigned integer.
|
||
|
||
You can use these types in arithmetic like any other integer types.
|
||
Addition, subtraction, and bitwise boolean operations on these types
|
||
are open-coded on all types of machines. Multiplication is open-coded
|
||
if the machine supports fullword-to-doubleword a widening multiply
|
||
instruction. Division and shifts are open-coded only on machines that
|
||
provide special support. The operations that are not open-coded use
|
||
special library routines that come with GNU CC.
|
||
|
||
There may be pitfalls when you use `long long' types for function
|
||
arguments, unless you declare function prototypes. If a function
|
||
expects type `int' for its argument, and you pass a value of type `long
|
||
long int', confusion will result because the caller and the subroutine
|
||
will disagree about the number of bytes for the argument. Likewise, if
|
||
the function expects `long long int' and you pass `int'. The best way
|
||
to avoid such problems is to use prototypes.
|
||
|
||
|
||
File: gcc.info, Node: Zero Length, Next: Variable Length, Prev: Long Long, Up: Extensions
|
||
|
||
Arrays of Length Zero
|
||
=====================
|
||
|
||
Zero-length arrays are allowed in GNU C. They are very useful as
|
||
the last element of a structure which is really a header for a
|
||
variable-length object:
|
||
|
||
struct line {
|
||
int length;
|
||
char contents[0];
|
||
};
|
||
|
||
{
|
||
struct line *thisline = (struct line *)
|
||
malloc (sizeof (struct line) + this_length);
|
||
thisline->length = this_length;
|
||
}
|
||
|
||
In standard C, you would have to give `contents' a length of 1, which
|
||
means either you waste space or complicate the argument to `malloc'.
|
||
|
||
|
||
File: gcc.info, Node: Variable Length, Next: Macro Varargs, Prev: Zero Length, Up: Extensions
|
||
|
||
Arrays of Variable Length
|
||
=========================
|
||
|
||
Variable-length automatic arrays are allowed in GNU C. These arrays
|
||
are declared like any other automatic arrays, but with a length that is
|
||
not a constant expression. The storage is allocated at the point of
|
||
declaration and deallocated when the brace-level is exited. For
|
||
example:
|
||
|
||
FILE *
|
||
concat_fopen (char *s1, char *s2, char *mode)
|
||
{
|
||
char str[strlen (s1) + strlen (s2) + 1];
|
||
strcpy (str, s1);
|
||
strcat (str, s2);
|
||
return fopen (str, mode);
|
||
}
|
||
|
||
Jumping or breaking out of the scope of the array name deallocates
|
||
the storage. Jumping into the scope is not allowed; you get an error
|
||
message for it.
|
||
|
||
You can use the function `alloca' to get an effect much like
|
||
variable-length arrays. The function `alloca' is available in many
|
||
other C implementations (but not in all). On the other hand,
|
||
variable-length arrays are more elegant.
|
||
|
||
There are other differences between these two methods. Space
|
||
allocated with `alloca' exists until the containing *function* returns.
|
||
The space for a variable-length array is deallocated as soon as the
|
||
array name's scope ends. (If you use both variable-length arrays and
|
||
`alloca' in the same function, deallocation of a variable-length array
|
||
will also deallocate anything more recently allocated with `alloca'.)
|
||
|
||
You can also use variable-length arrays as arguments to functions:
|
||
|
||
struct entry
|
||
tester (int len, char data[len][len])
|
||
{
|
||
...
|
||
}
|
||
|
||
The length of an array is computed once when the storage is allocated
|
||
and is remembered for the scope of the array in case you access it with
|
||
`sizeof'.
|
||
|
||
If you want to pass the array first and the length afterward, you can
|
||
use a forward declaration in the parameter list--another GNU extension.
|
||
|
||
struct entry
|
||
tester (int len; char data[len][len], int len)
|
||
{
|
||
...
|
||
}
|
||
|
||
The `int len' before the semicolon is a "parameter forward
|
||
declaration", and it serves the purpose of making the name `len' known
|
||
when the declaration of `data' is parsed.
|
||
|
||
You can write any number of such parameter forward declarations in
|
||
the parameter list. They can be separated by commas or semicolons, but
|
||
the last one must end with a semicolon, which is followed by the "real"
|
||
parameter declarations. Each forward declaration must match a "real"
|
||
declaration in parameter name and data type.
|
||
|
||
|
||
File: gcc.info, Node: Macro Varargs, Next: Subscripting, Prev: Variable Length, Up: Extensions
|
||
|
||
Macros with Variable Numbers of Arguments
|
||
=========================================
|
||
|
||
In GNU C, a macro can accept a variable number of arguments, much as
|
||
a function can. The syntax for defining the macro looks much like that
|
||
used for a function. Here is an example:
|
||
|
||
#define eprintf(format, args...) \
|
||
fprintf (stderr, format, ## args)
|
||
|
||
Here `args' is a "rest argument": it takes in zero or more
|
||
arguments, as many as the call contains. All of them plus the commas
|
||
between them form the value of `args', which is substituted into the
|
||
macro body where `args' is used. Thus, we have these expansions:
|
||
|
||
eprintf ("%s:%d: ", input_file_name, line_number)
|
||
==>
|
||
fprintf (stderr, "%s:%d: ", input_file_name, line_number)
|
||
|
||
Note that the comma after the string constant comes from the definition
|
||
of `eprintf', whereas the last comma comes from the value of `args'.
|
||
|
||
The reason for using `##' is to handle the case when `args' matches
|
||
no arguments at all. In this case, `args' has an empty value. In this
|
||
case, the second comma in the definition becomes an embarrassment: if
|
||
it got through to the expansion of the macro, we would get something
|
||
like this:
|
||
|
||
fprintf (stderr, "success!\n", )
|
||
|
||
which is invalid C syntax. `##' gets rid of the comma, so we get the
|
||
following instead:
|
||
|
||
fprintf (stderr, "success!\n")
|
||
|
||
This is a special feature of the GNU C preprocessor: `##' adjacent
|
||
to a rest argument discards the token on the other side of the `##', if
|
||
the rest argument value is empty.
|
||
|
||
|
||
File: gcc.info, Node: Subscripting, Next: Pointer Arith, Prev: Macro Varargs, Up: Extensions
|
||
|
||
Non-Lvalue Arrays May Have Subscripts
|
||
=====================================
|
||
|
||
Subscripting is allowed on arrays that are not lvalues, even though
|
||
the unary `&' operator is not. For example, this is valid in GNU C
|
||
though not valid in other C dialects:
|
||
|
||
struct foo {int a[4];};
|
||
|
||
struct foo f();
|
||
|
||
bar (int index)
|
||
{
|
||
return f().a[index];
|
||
}
|
||
|
||
|
||
File: gcc.info, Node: Pointer Arith, Next: Initializers, Prev: Subscripting, Up: Extensions
|
||
|
||
Arithmetic on `void'- and Function-Pointers
|
||
===========================================
|
||
|
||
In GNU C, addition and subtraction operations are supported on
|
||
pointers to `void' and on pointers to functions. This is done by
|
||
treating the size of a `void' or of a function as 1.
|
||
|
||
A consequence of this is that `sizeof' is also allowed on `void' and
|
||
on function types, and returns 1.
|
||
|
||
The option `-Wpointer-arith' requests a warning if these extensions
|
||
are used.
|
||
|
||
|
||
File: gcc.info, Node: Initializers, Next: Constructors, Prev: Pointer Arith, Up: Extensions
|
||
|
||
Non-Constant Initializers
|
||
=========================
|
||
|
||
The elements of an aggregate initializer for an automatic variable
|
||
are not required to be constant expressions in GNU C. Here is an
|
||
example of an initializer with run-time varying elements:
|
||
|
||
foo (float f, float g)
|
||
{
|
||
float beat_freqs[2] = { f-g, f+g };
|
||
...
|
||
}
|
||
|
||
|
||
File: gcc.info, Node: Constructors, Next: Labeled Elements, Prev: Initializers, Up: Extensions
|
||
|
||
Constructor Expressions
|
||
=======================
|
||
|
||
GNU C supports constructor expressions. A constructor looks like a
|
||
cast containing an initializer. Its value is an object of the type
|
||
specified in the cast, containing the elements specified in the
|
||
initializer.
|
||
|
||
Usually, the specified type is a structure. Assume that `struct
|
||
foo' and `structure' are declared as shown:
|
||
|
||
struct foo {int a; char b[2];} structure;
|
||
|
||
Here is an example of constructing a `struct foo' with a constructor:
|
||
|
||
structure = ((struct foo) {x + y, 'a', 0});
|
||
|
||
This is equivalent to writing the following:
|
||
|
||
{
|
||
struct foo temp = {x + y, 'a', 0};
|
||
structure = temp;
|
||
}
|
||
|
||
You can also construct an array. If all the elements of the
|
||
constructor are (made up of) simple constant expressions, suitable for
|
||
use in initializers, then the constructor is an lvalue and can be
|
||
coerced to a pointer to its first element, as shown here:
|
||
|
||
char **foo = (char *[]) { "x", "y", "z" };
|
||
|
||
Array constructors whose elements are not simple constants are not
|
||
very useful, because the constructor is not an lvalue. There are only
|
||
two valid ways to use it: to subscript it, or initialize an array
|
||
variable with it. The former is probably slower than a `switch'
|
||
statement, while the latter does the same thing an ordinary C
|
||
initializer would do. Here is an example of subscripting an array
|
||
constructor:
|
||
|
||
output = ((int[]) { 2, x, 28 }) [input];
|
||
|
||
Constructor expressions for scalar types and union types are is also
|
||
allowed, but then the constructor expression is equivalent to a cast.
|
||
|
||
|
||
File: gcc.info, Node: Labeled Elements, Next: Cast to Union, Prev: Constructors, Up: Extensions
|
||
|
||
Labeled Elements in Initializers
|
||
================================
|
||
|
||
Standard C requires the elements of an initializer to appear in a
|
||
fixed order, the same as the order of the elements in the array or
|
||
structure being initialized.
|
||
|
||
In GNU C you can give the elements in any order, specifying the array
|
||
indices or structure field names they apply to.
|
||
|
||
To specify an array index, write `[INDEX]' before the element value.
|
||
For example,
|
||
|
||
int a[6] = { [4] 29, [2] 15 };
|
||
|
||
is equivalent to
|
||
|
||
int a[6] = { 0, 0, 15, 0, 29, 0 };
|
||
|
||
The index values must be constant expressions, even if the array being
|
||
initialized is automatic.
|
||
|
||
In a structure initializer, specify the name of a field to initialize
|
||
with `FIELDNAME:' before the element value. For example, given the
|
||
following structure,
|
||
|
||
struct point { int x, y; };
|
||
|
||
the following initialization
|
||
|
||
struct point p = { y: yvalue, x: xvalue };
|
||
|
||
is equivalent to
|
||
|
||
struct point p = { xvalue, yvalue };
|
||
|
||
You can also use an element label when initializing a union, to
|
||
specify which element of the union should be used. For example,
|
||
|
||
union foo { int i; double d; };
|
||
|
||
union foo f = { d: 4 };
|
||
|
||
will convert 4 to a `double' to store it in the union using the second
|
||
element. By contrast, casting 4 to type `union foo' would store it
|
||
into the union as the integer `i', since it is an integer. (*Note Cast
|
||
to Union::.)
|
||
|
||
You can combine this technique of naming elements with ordinary C
|
||
initialization of successive elements. Each initializer element that
|
||
does not have a label applies to the next consecutive element of the
|
||
array or structure. For example,
|
||
|
||
int a[6] = { [1] v1, v2, [4] v4 };
|
||
|
||
is equivalent to
|
||
|
||
int a[6] = { 0, v1, v2, 0, v4, 0 };
|
||
|
||
Labeling the elements of an array initializer is especially useful
|
||
when the indices are characters or belong to an `enum' type. For
|
||
example:
|
||
|
||
int whitespace[256]
|
||
= { [' '] 1, ['\t'] 1, ['\h'] 1,
|
||
['\f'] 1, ['\n'] 1, ['\r'] 1 };
|
||
|
||
|
||
File: gcc.info, Node: Case Ranges, Next: Function Attributes, Prev: Cast to Union, Up: Extensions
|
||
|
||
Case Ranges
|
||
===========
|
||
|
||
You can specify a range of consecutive values in a single `case'
|
||
label, like this:
|
||
|
||
case LOW ... HIGH:
|
||
|
||
This has the same effect as the proper number of individual `case'
|
||
labels, one for each integer value from LOW to HIGH, inclusive.
|
||
|
||
This feature is especially useful for ranges of ASCII character
|
||
codes:
|
||
|
||
case 'A' ... 'Z':
|
||
|
||
*Be careful:* Write spaces around the `...', for otherwise it may be
|
||
parsed wrong when you use it with integer values. For example, write
|
||
this:
|
||
|
||
case 1 ... 5:
|
||
|
||
rather than this:
|
||
|
||
case 1...5:
|
||
|
||
|
||
File: gcc.info, Node: Cast to Union, Next: Case Ranges, Prev: Labeled Elements, Up: Extensions
|
||
|
||
Cast to a Union Type
|
||
====================
|
||
|
||
A cast to union type is like any other cast, except that the type
|
||
specified is a union type. You can specify the type either with `union
|
||
TAG' or with a typedef name.
|
||
|
||
The types that may be cast to the union type are those of the members
|
||
of the union. Thus, given the following union and variables:
|
||
|
||
union foo { int i; double d; };
|
||
int x;
|
||
double y;
|
||
|
||
both `x' and `y' can be cast to type `union' foo.
|
||
|
||
Using the cast as the right-hand side of an assignment to a variable
|
||
of union type is equivalent to storing in a member of the union:
|
||
|
||
union foo u;
|
||
...
|
||
u = (union foo) x == u.i = x
|
||
u = (union foo) y == u.d = y
|
||
|
||
You can also use the union cast as a function argument:
|
||
|
||
void hack (union foo);
|
||
...
|
||
hack ((union foo) x);
|
||
|
||
|