First of all, the preprocessor token concatenation feature can result in C identifiers that are composed of multiple CScout identifiers. Consider the following example, which uses a macro to define a number of different functions. (Yes, I am familiar with the C++ templates, this is just an example.)
#define typefun(name, type, op) \ type type ## _ ## name(type a, type b) { return a op b; } typefun(add, int, +) typefun(sub, int, -) typefun(mul, int, *) typefun(div, int, /) typefun(add, double, +) typefun(sub, double, -) typefun(mul, double, *) typefun(div, double, /) main() { printf("%d\n", int_add(5, 4)); printf("%g\n", double_mul(3.14, 2.0)); }In the CScout environment the
int_add
C identifier is
actually composed of three separate parts:
int
_
add
int
identifier into integer
would change it in five different places: the argument to the four
typefun
macro invocations, and the part of int_add
.
In addition, preprocessor macro definitions can confuse the notion of the C scope, bringing together scopes that would be considered separate in the context of the C language-proper. Consider the following (slightly contrived) example:
struct foo { int foo; }; struct bar { int foo; }; #define getpart(tag, name) (((struct tag *)p)->name) #define getfoo(var) (var.foo) #define get(name) (name(0) + ((struct name *)p)->name) #define conditional(x) do {if (!x(0)) goto x; return x(0);} while(0) int foo(void *p) { struct foo f; struct bar b; foo: if (p && getpart(foo, foo)) return getpart(bar, foo); else if (getfoo(f)) return get(foo); else if (getfoo(b)) conditional(foo); else return 0; }The identifier
foo
is occuring in a number of different
scopes:
foo
identifier,
CScout will change all the instances marked below,
in order to obtain a program that has the same meaning as the original
one.
Identifier foo: test.c(Use the tab key to move to each marked element.) struct foo {
|
#define macro() middlemacro() #define middlemacro() innemacro() #define innemacro() function1() function1() {} function2() {} main() { macro(); function2(); function3(); printf("Hello"); }The corresponding call graph is as follows:
Note that in CScout functions are separate entities from identifiers. The name of a function can consist of multiple identifiers; an identifier can exist in more than one function names.
For instance,
the page for the _
(underscore) identifier in the
typefun
macro example we saw earlier
will appear as follows.
Identifier: _CScout 2.0 - 2004/07/31 12:37:12 |
Note how each function name is composed of three separate parts,
and that this instance of the _
identifier occurs in
8 different function names.
Contents | « Previous Next (The Web Interface) » |