Sie sind auf Seite 1von 49

1. What is a Pointer?

A pointer is a variable which contains the address in memory of another


variable. We can have a pointer to any variable type.
The unary or monadic operator & gives the ``address of a variable''.
The indirection or dereference operator * gives the ``contents of an object
pointed to by a pointer''.
To declare a pointer to a variable do:
int *pointer;
NOTE: We must associate a pointer to a particular type: You can't assign the
address of a short int to a long int, for instance.

Consider the effect of the following code:

int x = 1, y = 2;

int *ip;
ip = &x;
y = *ip;
x = ip;
*ip = 3;
It is worth considering what is going on at the machine level in memory to fully
understand how pointer work. Consider Fig. 9.1. Assume for the sake of this
discussion that variable x resides at memory location 100, y at 200 and ip at
1000. Note A pointer is a variable and thus its values need to be stored
somewhere. It is the nature of the pointers value that is new.
Fig. 9.1 Pointer, Variables and Memory Now the assignments x = 1 and y = 2
obviously load these values into the variables. ip is declared to be a pointer to
an integer and is assigned to the address of x (&x). So ip gets loaded with the
value 100.
Next y gets assigned to the contents of ip. In this example ip currently points
to memory location 100 -- the location of x. So y gets assigned to the values of
x -- which is 1.
We have already seen that C is not too fussy about assigning values of different
type. Thus it is perfectly legal (although not all that common) to assign the
current value of ip to x. The value of ip at this instant is 100.
Finally we can assign a value to the contents of a pointer (*ip).
IMPORTANT: When a pointer is declared it does not point anywhere. You must
set it to point somewhere before you use it.
So ...
int *ip;
*ip = 100;
will generate an error (program crash!!).
The correct use is:

int *ip;
int x;
ip = &x;
*ip = 100;
We can do integer arithmetic on a pointer:

float *flp, *flq;

*flp = *flp + 10;


++*flp;
(*flp)++;
flq = flp;
NOTE: A pointer to any variable type is an address in memory -- which is an
integer address. A pointer is definitely NOT an integer.
The reason we associate a pointer to a data type is so that it knows how many
bytes the data is stored in. When we increment a pointer we increase the
pointer by one ``block'' memory.
So for a character pointer ++ch_ptr adds 1 byte to the address.
For an integer or float ++ip or ++flp adds 4 bytes to the address.
Consider a float variable (fl) and a pointer to a float (flp) as shown in Fig. 9.2.

Fig. 9.2 Pointer Arithmetic Assume that flp points to fl then if we increment the
pointer ( ++flp) it moves to the position shown 4 bytes on. If on the other hand
we added 2 to the pointer then it moves 2 float positions i.e 8 bytes as shown
in the Figure.

2. List out all the conditional statements available in C.


If , If – else if statement, switch, while, do-while, for statement.

3. List out all the unconditional statements available in C.


Break, continue, goto.
4. What are the different storage classes available in C?
Auto, extern, register, static.
5. Which storage class is the default for the variables?
Auto for local variables, static for global variables.
6. What is a self referential structure?
A self-referential structure is a data structure that includes references to other
data of its same type. A simple example of this would be an implementation in C
of a linked list:
typedef struct listnode {
void *data;
struct listnode *next;
} list_t;

The reference to a listnode struct from within a listnode struct is the self-
referential aspect of the structure.
7. What are the different iterative statements available in C?
While , do-while, for.
8. Differentiate structure from union?
(a) In union , the different members share the same memory location.

The total memory allocated to the union is equal to the maximum size of the
member.
Union can hold data of only one member at a time.
(b) In structure, the different members have different memory location.

The total memory allocated to the structure is equal to the sum of memory
allocated for each member.

Structure can hold data of more than one member at a time.


10. What is preprocessor?
The C preprocessor (cpp) is the preprocessor for the C programming
language. In many C implementations, it is a separate program invoked by the
compiler as the first part of translation. The preprocessor handles directives for
source file inclusion (#include), macro definitions (#define), and conditional
inclusion (#if). The language of preprocessor directives is not strictly specific to
the grammar of C, so the C preprocessor can also be used independently to
process other types of files.
The transformations it makes on its input form the first four of C's so-called
Phases of Translation. Though an implementation may choose to perform some
or all phases simultaneously, it must behave as if it performed them one-by-one
in order.

Examples
This section goes into some detail about C preprocessor usage. Good
programming practice when writing C macros is crucial, particularly in a
collaborative setting, so notes on this have been included. Of course, it is
possible to abuse these features, but this is not recommended in a production
environment.
Including files
The most common use of the preprocessor is to include another file:
#include <stdio.h>
int main (void)
{
printf("Hello, world!\n");
return 0;
}
The preprocessor replaces the line #include <stdio.h> with the system header file of that
name, which declares the printf() function amongst other things. More precisely, the
entire text of the file 'stdio.h' replaces the #include directive.
This can also be written using double quotes, e.g. #include "stdio.h". The angle brackets
were originally used to indicate 'system' include files, and double quotes user-written
include files, and it is good practice to retain this distinction. C compilers and
programming environments all have a facility which allows the programmer to define
where include files can be found. This can be introduced through a command line flag,
which can be parameterized using a makefile, so that a different set of include files can
be swapped in for different operating systems, for instance.
By convention, include files are given a .h extension, and files not included by
others are given a .c extension. However, there is no requirement that this be
observed. Occasionally you will see files with other extensions included, in
particular files with a .def extension may denote files designed to be included
multiple times, each time expanding the same repetitive content.
#include often compels the use of #include guards or #pragma once to prevent
double inclusion.

Conditional compilation
The #ifdef, #ifndef, #else, #elif and #endif directives can be used for conditional
compilation.
#define __WINDOWS__
#ifdef __WINDOWS__
#include <windows.h>
#else
#include <unistd.h>
#endif
The first line defines a macro __WINDOWS__. The macro could be defined
implicitly by the compiler, or specified on the compiler's command line, perhaps
to control compilation of the program from a make file.
The subsequent code tests if a macro __WINDOWS__ is defined. If it is, as in
this example, the file <windows.h> is included, otherwise <unistd.h>.
Since the preprocessor can also be invoked independently to process files
apart from compiling source code, it can also be used as a "general purpose
preprocessor" for other types of text processing (see General purpose
preprocessor for examples).

Macro definition and expansion


There are two types of macros, object-like and function-like. Function-like
macros take parameters; object-like macros don't. The generic syntax for
declaring an identifier as a macro of each type is, respectively,
#define <identifier> <replacement token list>
#define <identifier>(<parameter list>) <replacement token list>
Note that there must not be any whitespace between the macro identifier and
the left parenthesis.
Wherever the identifier appears in the source code it is replaced with the
replacement token list, which can be empty. For an identifier declared to be a
function-like macro, it is only replaced when the following token is also a left
parenthesis that begins the argument list of the macro invocation. The exact
procedure followed for expansion of function-like macros with arguments is
subtle.
Object-like macros are conventionally used as part of good programming
practice to create symbolic names for constants, e.g.
#define PI 3.14159
instead of hard-coding those numbers throughout one's code.
An example of a function-like macro is:
#define RADTODEG(x) ((x) * 57.29578)
This defines a radians to degrees conversion which can be written
subsequently, e.g. RADTODEG(34). This is expanded in-place, so the caller
does not need to litter copies of the multiplication constant all over his code.
The macro here is written as all uppercase to emphasize that it is a macro, not
a compiled function.
Multiple evaluation of side effects
Another example of a function-like macro is:
#define MIN(a,b) ((a)>(b)?(b):(a))
This illustrates one of the dangers of using function-like macros. One of the
arguments, a or b, will be evaluated twice when this "function" is called. So, if
the expression MIN(++firstnum,secondnum) is evaluated, then firstnum may be
incremented twice, not once as would be expected.
A safer way to achieve the same would be to use a typeof-construct:

#define max(a,b) \
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })
This will cause the arguments to be evaluated only once, and it won't be type-specific anymore. This construct is
not legal ANSI C; both the typeof keyword, and the construct of placing a compound statement within
parentheses, are non-standard extensions implemented in the popular gnu C compiler (gcc). If you are using gcc,
the same general problem can also be solved using a static inline function, which is as efficient as a #define. The
inline function allows the compiler to check/coerce parameter types -- in this particular example this appears to be
a disadvantage, since the 'max' function as shown works equally well with different parameter types, but in general
having the type coercion is often an advantage.
Within ANSI C, there's no reliable general solution to the issue of side-effects in macro arguments.
Semicolons
One stylistic note about the above macro is that the semicolon on the last line
of the macro definition is omitted so that the macro looks 'natural' when written.
It could be included in the macro definition, but then there would be lines in the
code without semicolons at the end which would throw off the casual reader.
Worse, the user could be tempted to include semicolons anyway; in most cases
this would be harmless (an extra semicolon denotes an empty statement) but it
would cause errors in control flow blocks:
#define PRETTY_PRINT(s) \
printf ("Message: \"%s\"\n", s);
if (n < 10)
PRETTY_PRINT("n is less than 10");
else
PRETTY_PRINT("n is at least 10");
This expands to give two statements – the intended printf and an empty
statement – in each branch of the if/else construct, which will cause the
compiler to give an error message similar to:
error: expected expression before ‘else’
12. How many bytes, different data types require on a typical computer
system?

Type Length Range


unsigned char 8 bits 0 to 255
char 8 bits -128 to 127
enum 16 bits -32,768 to 32,767
unsigned int 16 bits 0 to 65,535
short int 16 bits -32,768 to 32,767
int 16 bits -32,768 to 32,767
unsigned long 32 bits 0 to 4,294,967,295
long 32 bits -2,147,483,648 to 2,147,483,647
float 32 bits 3.4 * (10**-38) to 3.4 * (10**+38)
double 64 bits 1.7 * (10**-308) to 1.7 * (10**+308)
long double 80 bits 3.4 * (10**-4932) to 1.1 * (10**+4932)

13. What is a flow chart?


A flowchart (also spelled flow-chart and flow chart) is a schematic representation
of an algorithm or a process flowchart is one of the seven basic tools of quality control,
which include the histogram, Pareto chart, check sheet, control chart, cause-and-effect
diagram, flowchart, and scatter diagram.
14. What is an algorithm?
An algorithm (pronounced AL-go-rith-um) is a procedure or formula for
solving a problem. The word derives from the name of the mathematician,
Mohammed ibn-Musa al-Khwarizmi, who was part of the royal court in Baghdad
and who lived from about 780 to 850. Al-Khwarizmi's work is the likely source
for the word algebra as well.
A computer program can be viewed as an elaborate algorithm. In mathematics
and computer science, an algorithm usually means a small procedure that
solves a recurrent problem.
15. Differentiate while from do-while.
- While and do-while loops are used when u want to repeat the execution of a
certain statement or a set of statements.
-Before entering into the loop, the while condition is evaluated. If it is true then
only the body is executed.
-Do-while executes the loop body at least once. The condition is checked after
executing the loop body once.
16. What are the different types of comments available in C?
1.There are two kinds of comments. Block comments begin with `/*' and
continue until the next `*/'. Block comments do not nest:
/* this is /* one comment */ text outside comment
2.Line comments begin with `//' and continue to the end of the current line. Line
comments do not nest either, but it does not matter, because they would end in
the same place anyway.
// this is // one comment
text outside comment
It is safe to put line comments inside block comments, or vice versa.
/* block comment
// contains line comment
yet more comment
*/ outside comment
// line comment /* contains
block comment */
But beware of commenting out one end of a block comment with a line
comment.
// l.c. /* block comment
begins
oops! this isn't a
comment anymore */
Comments are not recognized within string literals. "/* blah */" is the string
constant `/* blah */', not an empty string.
17. Assume a C program consists of a set of functions. From which point
its execution starts?
Program execution always starts from Main().
18. What are command line arguments?
Program Execution
Depending on the operating system and programming environment, a C
program can be executed either by selecting an icon ifrom a graphical user
interface desktop or by entering a command in a command window (DOS
or UNIX command window). It is usually easier to write programs that are
run by entering a command in a command window.
When a command is entered in a command window, it is executed by a
command-line interpreter. The operation of a command interpreter is quite
complex, but as a first approximation, it interpreter breaks up a command
into words separated by spaces. The first word is treated as the name of a
program. The interpreter searches for the program and starts it executing
with the command words passed as arguments.
A C program is executed by calling its main() function. The function is called
with one argument that indicates how how many words are in the command
and another argument that is an array containing the command words.
Accessing Command-Line Arguments
In order to access the command words, the main() function must have a
prototype similar to the following.
int main(int argc, char * argv[])
The names argc and argv are usually used for the parameters, but a
programmer could use different names.
The command words can be accessed as argv[0] through argv[argc - 1]. The
program name is the first word on the command line, which is argv[0]. The
command-line arguments are argv[1] through argv[argc - 1].
An Example - myecho.C
The file myecho.C encodes a program that echoes its command-line
arguments. This program is similar to the UNIX echo command. Suppose that
the program is compiled to an executable program myecho and that the
program is executed with the following command.
myecho aaa bbb ccc
When this command is executed, the command interpreter calls the main()
function of the myecho program with 4 passed as the argc argument and an
array of 4 strings as the argv argument. argc contains the following strings.
argv[0] - "myecho"

argv[1] - "aaa"

argv[2] - "bbb"

argv[3] - "ccc"

19. What is structured programming?


Structured programming is often (but not always) associated with a "top-down"
approach to design.
Structured programming languages
It is possible to do structured programming in any programming language,
though it is
preferable to use something like a procedural programming language. Since
about
1970 when structured programming began to gain popularity as a technique,
most new
procedural programming languages have included features to encourage
structured
programming (and sometimes have left out features that would make
unstructured programming
easy). Some of the better known structured programming languages are
Pascal, C, PL/I
(programming language)|PL/I]], and Ada.
20. What is block structured programming?
block-structured
<language> Any programming language in which sections of source code
contained within pairs of matching delimiters such as "{" and "}" (e.g. in C) or
"begin" and "end" (e.g. Algol) are executed as a single unit. A block of code may
be the body of a subroutine or function, or it may be controlled by conditional
execution (if statement) or repeated execution (while statement, for statement,
etc.).
In all but the most primitive block structured languages a variable's scope can
be limited to the block in which it is declared.
Block-structured languages support structured programming where each block
can be written without detailed knowledge of the inner workings of other blocks,
thus allowing a top-down design approach.
top-down design
<programming> (Or "stepwise refinement"). The software design technique which aims to describe
functionality at a very high level, then partition it repeatedly into more detailed levels one level at a
time until the detail is sufficient to allow coding. This approach to software design probably
originated at IBM, and grew out of structured programming practices.
21. What is a local variable?
Local variables
Local variables must always be defined at the top of a block.
When a local variable is defined - it is not initalised by the system, you must
initalise it yourself.
A local variable is defined inside a block and is only visable from within the
block.
main()
{
int i=4;
i++;
}

When execution of the block starts the variable is available, and when the block
ends the variable 'dies'.
A local variable is visible within nested blocks unless a variable with the same
name is defined within the nested block.
main()

int i=4;

int j=10;

i++;

if (j > 0)

printf("i is %d\n",i); /* i defined in 'main' can be seen */

if (j > 0)

int i=100; /* 'i' is defined and so local to

* this block */

printf("i is %d\n",i);

} /* 'i' (value 100) dies here */

printf("i is %d\n",i); /* 'i' (value 5) is now visable. */

}
22. What is a global variable? How do you declare it?
Global variables
Global variables ARE initialized by the system when you define them!
Data Type Initialser

int 0

char '\0'

float 0

pointer NULL

In the next example i is a global variable, it can be seen and modified by main
and any other functions that may reference it.

int i=4;
main()
{
i++;
}
Now, this example has global and Internal variables.
int i=4; /* Global
definition */

main()
{ i++; /* global
variable */
func
}

func()
{ int i=10; /* Internal
declaration
i++; */ /* Internal
variable */
}

i in main is global and will be incremented to 5. i in func is internal and will be


incremented to 11. When control returns to main the internal variable will die
and and any reference to i will be to the global.
static variables can be 'seen' within all functions in this source file. At link time,
the static variables defined here will not be seen by the object modules that are
brought in.
23. In general, how many characters are allowed in forming the name of
an identifier?
C Identifiers
“Identifiers” or “symbols” are the names you supply for variables, types,
functions, and labels in your program. Identifier names must differ in spelling
and case from any keywords. You cannot use keywords (either C or Microsoft)
as identifiers; they are reserved for special use. You create an identifier by
specifying it in the declaration of a variable, type, or function. In this example,
result is an identifier for an integer variable, and main and printf are identifier
names for functions.
void main() { int result; if ( result != 0 ) printf( "Bad file handle\n" ); }
Once declared, you can use the identifier in later program statements to refer to
the associated value.
A special kind of identifier, called a statement label, can be used in goto
statements. (Declarations are described in, Declarations and Types. Statement
labels are described in The goto and Labeled Statements in Statements.)
Syntax
identifier :
nondigit
identifier nondigit
identifier digit
nondigit : one of
_abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
digit : one of
0123456789
The first character of an identifier name must be a nondigit (that is, the first
character must be an underscore or an uppercase or lowercase letter). ANSI
allows six significant characters in an external identifier’s name and 31 for
names of internal (within a function) identifiers. External identifiers (ones
declared at global scope or declared with storage class extern) may be subject
to additional naming restrictions because these identifiers have to be processed
by other software such as linkers.

Although ANSI allows 6 significant characters in external identifier names and


31 for names of internal (within a function) identifiers, the Microsoft C compiler
allows 247 characters in an internal or external identifier name. If you aren’t
concerned with ANSI compatibility, you can modify this default to a smaller or
larger number using the /H (restrict length of external names) option.
24. What is a white space character?
White Space
1. Blank Space
2. Horizontal Tab
3. Carriage Return
4. New Line
5. Form Feed
25. what are all the different characters allowed in forming the name of an
identifier?
identifier :
nondigit
identifier nondigit
identifier digit
nondigit : one of
_abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
digit : one of
0123456789
The first character of an identifier name must be a nondigit (that is, the first
character must be an underscore or an uppercase or lowercase letter). ANSI
allows six significant characters in an external identifier’s name and 31 for
names of internal (within a function) identifiers. External identifiers (ones
declared at global scope or declared with storage class extern) may be subject
to additional naming restrictions because these identifiers have to be processed
by other software such as linkers.

Although ANSI allows 6 significant characters in external identifier names and


31 for names of internal (within a function) identifiers, the Microsoft C compiler
allows 247 characters in an internal or external identifier name. If you aren’t
concerned with ANSI compatibility, you can modify this default to a smaller or
larger number using the /H (restrict length of external names) option.

26. What is a token in the context of a C program?


C Tokens
In a C source program, the basic element recognized by the compiler is the
“token.” A token is source-program text that the compiler does not break down
into component elements.
Syntax
token :
keyword
identifier
constant
string-literal
operator
punctuator
The keywords, identifiers, constants, string literals, and operators described in
this chapter are examples of tokens. Punctuation characters such as brackets ([
]), braces ({ }), parentheses ( ( ) ), and commas (,) are also tokens.

27. What is the range of values an unsigned char can accommodate?


Assume that the char takes one byte.
8 bits (0 to 255)
31. How do u declare a constant?
C Floating-Point Constants
A “floating-point constant” is a decimal number that represents a signed real
number. The representation of a signed real number includes an integer
portion, a fractional portion, and an exponent. Use floating-point constants to
represent floating-point values that cannot be changed.
Syntax
floating-point-constant :
fractional-constant exponent-part opt floating-suffix opt
digit-sequence exponent-part floating-suffix opt
fractional-constant :
digit-sequence opt . digit-sequence
digit-sequence .
exponent-part :
e sign opt digit-sequence
E sign opt digit-sequence
sign : one of
+–
digit-sequence :
digit
digit-sequence digit
floating-suffix : one of
flFL
You can omit either the digits before the decimal point (the integer portion of the
value) or the digits after the decimal point (the fractional portion), but not both.
You can leave out the decimal point only if you include an exponent. No white-
space characters can separate the digits or characters of the constant.
The following examples illustrate some forms of floating-point constants and
expressions:
15.75 1.575E1 /* = 15.75 */ 1575e-2 /* = 15.75 */ -2.5e-3 /* = -0.0025 */ 25E-4 /*
= 0.0025 */
Floating-point constants are positive unless they are preceded by a minus sign
(–). In this case, the minus sign is treated as a unary arithmetic negation
operator. Floating-point constants have type float, double, long, or long
double.
A floating-point constant without an f, F, l, or L suffix has type double. If the
letter f or F is the suffix, the constant has type float. If suffixed by the letter l or
L, it has type long double. For example:
100L /* Has type long double */ 100F /* Has type float */ 100D /* Has type
double */
Note that the Microsoft C compiler maps long double to type double. You can
omit the integer portion of the floating-point constant, as shown in the following
examples. The number .75 can be expressed in many ways, including the
following:
.0075e2 0.075e1 .075e1 75e-2
C Integer Constants
An “integer constant” is a decimal (base 10), octal (base 8), or hexadecimal
(base 16) number that represents an integral value. Use integer constants to
represent integer values that cannot be changed.
Syntax
integer-constant :
decimal-constant integer-suffix opt
octal-constant integer-suffix opt
hexadecimal-constant integer-suffix opt
decimal-constant :
nonzero-digit
decimal-constant digit
octal-constant :
0
octal-constant octal-digit
hexadecimal-constant :
0x hexadecimal-digit
0X hexadecimal-digit
hexadecimal-constant hexadecimal-digit
nonzero-digit : one of
123456789
octal-digit : one of
01234567
hexadecimal-digit : one of
0123456789
abcdef
ABCDEF
integer-suffix :
unsigned-suffix long-suffix opt
long-suffix unsigned-suffix opt
unsigned-suffix : one of
uU
long-suffix : one of
lL
64-bit integer-suffix :
i64
Integer constants are positive unless they are preceded by a minus sign (–).
The minus sign is interpreted as the unary arithmetic negation operator. If an
integer constant begins with the letters 0x or 0X, it is hexadecimal. If it begins
with the digit 0, it is octal. Otherwise, it is assumed to be decimal.
The following lines are equivalent:
0x1C /* = Hexadecimal representation for decimal 28 */ 034 /* = Octal
representation for decimal 28 */
No white-space characters can separate the digits of an integer constant.
These examples show valid decimal, octal, and hexadecimal constants.
/* Decimal Constants */ 10 132 32179 /* Octal Constants */ 012 0204 076663 /*
Hexadecimal Constants */ 0xa or 0xA 0x84 0x7dB3 or 0X7DB3
Character Types
An integer character constant not preceded by the letter L has type int. The
value of an integer character constant containing a single character is the
numerical value of the character interpreted as an integer. For example, the
numerical value of the character a is 97 in decimal and 61 in hexadecimal.
Syntactically, a “wide-character constant” is a character constant prefixed by
the letter L. A wide-character constant has type wchar_t, an integer type
defined in the STDDEF.H header file. For example:
char schar = 'x'; /* A character constant */ wchar_t wchar = L'x'; /* A wide-
character constant for the same character */
Wide-character constants are 16 bits wide and specify members of the
extended execution character set. They allow you to express characters in
alphabets that are too large to be represented by type char.
32. What are the problems associated with #define preprocessor
directive?
Macros
A macro is a sort of abbreviation which you can define once and then use later.
There are many complicated features associated with macros in the C
preprocessor.
Simple Macros
A simple macro is a kind of abbreviation. It is a name which stands for a
fragment of code. Some people refer to these as manifest constants.
Before you can use a macro, you must define it explicitly with the `#define'
directive. `#define' is followed by the name of the macro and then the code it
should be an abbreviation for. For example,
#define BUFFER_SIZE 1020
defines a macro named `BUFFER_SIZE' as an abbreviation for the text `1020'.
If somewhere after this `#define' directive there comes a C statement of the
form
foo = (char *) xmalloc (BUFFER_SIZE);
then the C preprocessor will recognize and expand the macro
`BUFFER_SIZE', resulting in
foo = (char *) xmalloc (1020);
The use of all upper case for macro names is a standard convention. Programs
are easier to read when it is possible to tell at a glance which names are
macros.
Normally, a macro definition must be a single line, like all C preprocessing
directives. (You can split a long macro definition cosmetically with Backslash-
Newline.) There is one exception: Newlines can be included in the macro
definition if within a string or character constant. This is because it is not
possible for a macro definition to contain an unbalanced quote character; the
definition automatically extends to include the matching quote character that
ends the string or character constant. Comments within a macro definition may
contain Newlines, which make no difference since the comments are entirely
replaced with Spaces regardless of their contents.
Aside from the above, there is no restriction on what can go in a macro body.
Parentheses need not balance. The body need not resemble valid C code. (But
if it does not, you may get error messages from the C compiler when you use
the macro.)
The C preprocessor scans your program sequentially, so macro definitions take
effect at the place you write them. Therefore, the following input to the C
preprocessor
foo = X;
#define X 4
bar = X;
produces as output
foo = X;
bar = 4;
After the preprocessor expands a macro name, the macro's definition body is
appended to the front of the remaining input, and the check for macro calls
continues. Therefore, the macro body can contain calls to other macros. For
example, after
#define BUFSIZE 1020
#define TABLESIZE BUFSIZE
the name `TABLESIZE' when used in the program would go through two stages
of expansion, resulting ultimately in `1020'.
This is not at all the same as defining `TABLESIZE' to be `1020'. The `#define'
for `TABLESIZE' uses exactly the body you specify--in this case, `BUFSIZE'---
and does not check to see whether it too is the name of a macro. It's only when
you use `TABLESIZE' that the result of its expansion is checked for more
macro names. See section Cascaded Use of Macros.
Macros with Arguments
A simple macro always stands for exactly the same text, each time it is used.
Macros can be more flexible when they accept arguments. Arguments are
fragments of code that you supply each time the macro is used. These
fragments are included in the expansion of the macro according to the
directions in the macro definition. A macro that accepts arguments is called a
function-like macro because the syntax for using it looks like a function call.
To define a macro that uses arguments, you write a `#define' directive with a list
of argument names in parentheses after the name of the macro. The argument
names may be any valid C identifiers, separated by commas and optionally
whitespace. The open-parenthesis must follow the macro name immediately,
with no space in between.
For example, here is a macro that computes the minimum of two numeric
values, as it is defined in many C programs:
#define min(X, Y) ((X) < (Y) ? (X) : (Y))
(This is not the best way to define a "minimum" macro in GNU C. See section
Duplication of Side Effects, for more information.)
To use a macro that expects arguments, you write the name of the macro followed by a
list of actual arguments in parentheses, separated by commas. The number of actual
arguments you give must match the number of arguments the macro expects. Examples
of use of the macro `min' include `min (1, 2)' and `min (x + 28, *p)'.
The expansion text of the macro depends on the arguments you use. Each of
the argument names of the macro is replaced, throughout the macro definition,
with the corresponding actual argument. Using the same macro `min' defined
above, `min (1, 2)' expands into
((1) < (2) ? (1) : (2))
where `1' has been substituted for `X' and `2' for `Y'.
Likewise, `min (x + 28, *p)' expands into
((x + 28) < (*p) ? (x + 28) : (*p))
Parentheses in the actual arguments must balance; a comma within
parentheses does not end an argument. However, there is no requirement for
brackets or braces to balance, and they do not prevent a comma from
separating arguments. Thus,
macro (array[x = y, x + 1])
passes two arguments to macro: `array[x = y' and `x + 1]'. If you want to supply
`array[x = y, x + 1]' as an argument, you must write it as `array[(x = y, x + 1)]',
which is equivalent C code.
After the actual arguments are substituted into the macro body, the entire result
is appended to the front of the remaining input, and the check for macro calls
continues. Therefore, the actual arguments can contain calls to other macros,
either with or without arguments, or even to the same macro. The macro body
can also contain calls to other macros. For example, `min (min (a, b), c)'
expands into this text:
((((a) < (b) ? (a) : (b))) < (c)
? (((a) < (b) ? (a) : (b)))
: (c))
(Line breaks shown here for clarity would not actually be generated.)
If a macro foo takes one argument, and you want to supply an empty argument,
you must write at least some whitespace between the parentheses, like this:
`foo ( )'. Just `foo ()' is providing no arguments, which is an error if foo expects
an argument. But `foo0 ()' is the correct way to call a macro defined to take zero
arguments, like this:
#define foo0() ...
If you use the macro name followed by something other than an open-
parenthesis (after ignoring any spaces, tabs and comments that follow), it is not
a call to the macro, and the preprocessor does not change what you have
written. Therefore, it is possible for the same name to be a variable or function
in your program as well as a macro, and you can choose in each instance
whether to refer to the macro (if an actual argument list follows) or the variable
or function (if an argument list does not follow).
Such dual use of one name could be confusing and should be avoided except
when the two meanings are effectively synonymous: that is, when the name is
both a macro and a function and the two have similar effects. You can think of
the name simply as a function; use of the name for purposes other than calling
it (such as, to take the address) will refer to the function, while calls will expand
the macro and generate better but equivalent code. For example, you can use a
function named `min' in the same source file that defines the macro. If you write
`&min' with no argument list, you refer to the function. If you write `min (x, bb)',
with an argument list, the macro is expanded. If you write `(min) (a, bb)', where
the name `min' is not followed by an open-parenthesis, the macro is not
expanded, so you wind up with a call to the function `min'.
You may not define the same name as both a simple macro and a macro with
arguments.
In the definition of a macro with arguments, the list of argument names must
follow the macro name immediately with no space in between. If there is a
space after the macro name, the macro is defined as taking no arguments, and
all the rest of the line is taken to be the expansion. The reason for this is that it
is often useful to define a macro that takes no arguments and whose definition
begins with an identifier in parentheses. This rule about spaces makes it
possible for you to do either this:
#define FOO(x) - 1 / (x)
(which defines `FOO' to take an argument and expand into minus the reciprocal
of that argument) or this:
#define BAR (x) - 1 / (x)
(which defines `BAR' to take no argument and always expand into `(x) - 1 / (x)').
Note that the uses of a macro with arguments can have spaces before the left
parenthesis; it's the definition where it matters whether there is a space.
33. What is the usage of enum data type?
C Enumeration Declarations
An enumeration consists of a set of named integer constants. An enumeration type
declaration gives the name of the (optional) enumeration tag and defines the set of
named integer identifiers (called the "enumeration set," "enumerator constants,"
"enumerators," or "members"). A variable with enumeration type stores one of the values
of the enumeration set defined by that type.
Variables of enum type can be used in indexing expressions and as operands of all
arithmetic and relational operators. Enumerations provide an alternative to the #define
preprocessor directive with the advantages that the values can be generated for you and
obey normal scoping rules.
In ANSI C, the expressions that define the value of an enumerator constant always have
int type; thus, the storage associated with an enumeration variable is the storage
required for a single int value. An enumeration constant or a value of enumerated type
can be used anywhere the C language permits an integer expression.
Syntax
enum-specifier:
enum identifier opt { enumerator-list }
enum identifier
The optional identifier names the enumeration type defined by enumerator-list.
This identifier is often called the "tag" of the enumeration specified by the list. A
type specifier of the form
enum identifier { enumerator-list }
declares identifier to be the tag of the enumeration specified by the enumerator-
list nonterminal. The enumerator-list defines the "enumerator content." The
enumerator-list is described in detail below.
If the declaration of a tag is visible, subsequent declarations that use the tag but
omit enumerator-list specify the previously declared enumerated type. The tag
must refer to a defined enumeration type, and that enumeration type must be in
current scope. Since the enumeration type is defined elsewhere, the
enumerator-list does not appear in this declaration. Declarations of types
derived from enumerations and typedef declarations for enumeration types can
use the enumeration tag before the enumeration type is defined.
Syntax
enumerator-list:
enumerator
enumerator-list , enumerator
enumerator:
enumeration-constant
enumeration-constant = constant-expression
enumeration-constant:
identifier
Each enumeration-constant in an enumeration-list names a value of the
enumeration set. By default, the first enumeration-constant is associated with
the value 0. The next enumeration-constant in the list is associated with the
value of ( constant-expression + 1 ), unless you explicitly associate it with
another value. The name of an enumeration-constant is equivalent to its value.
You can use enumeration-constant = constant-expression to override the
default sequence of values. Thus, if enumeration-constant = constant-
expression appears in the enumerator-list, the enumeration-constant is
associated with the value given by constant-expression. The constant-
expression must have int type and can be negative.
The following rules apply to the members of an enumeration set:
•· An enumeration set can contain duplicate constant values. For
example, you could associate the value 0 with two different identifiers,
perhaps named null and zero, in the same set.

•· The identifiers in the enumeration list must be distinct from other


identifiers in the same scope with the same visibility, including ordinary
variable names and identifiers in other enumeration lists.
•· Enumeration tags obey the normal scoping rules. They must be
distinct from other enumeration, structure, and union tags with the same
visibility.
Examples
These examples illustrate enumeration declarations:
enum DAY /* Defines an enumeration type */ { saturday, /* Names day
and declares a */ sunday = 0, /* variable named workday with */ monday, /*
that type */ tuesday, wednesday, /* wednesday is associated with 3 */
thursday, friday } workday;
The value 0 is associated with saturday by default. The identifier sunday is
explicitly set to 0. The remaining identifiers are given the values 1 through 5
by default.
In this example, a value from the set DAY is assigned to the variable today.
enum DAY today = wednesday;
Note that the name of the enumeration constant is used to assign the value.
Since the DAY enumeration type was previously declared, only the enumeration
tag DAY is necessary.
To explicitly assign an integer value to a variable of an enumerated data type,
use a type cast:
workday = ( enum DAY ) ( day_value - 1 );
This cast is recommended in C but is not required.
enum BOOLEAN /* Declares an enumeration data type called BOOLEAN */ {
false, /* false = 0, true = 1 */ true }; enum BOOLEAN end_flag, match_flag; /*
Two variables of type BOOLEAN */
enum BOOLEAN { false, true } end_flag, match_flag;\
or as
enum BOOLEAN { false, true } end_flag; enum BOOLEAN match_flag;
An example that uses these variables might look like this:
if ( match_flag == false ) { . . /* statement */ . } end_flag = true;
Unnamed enumerator data types can also be declared. The name of the data
type is omitted, but variables can be declared. The variable response is a
variable of the type defined:
enum { yes, no } response;
34. Why the usage of goto statement considered inappropriate?
Unconditionally transfer control.
goto may be used for transfering control from one place to another. The syntax
is:
goto identifier;
Control is unconditionally transferred to the location of a local label specified by
identifier. For example,
Again:
...
goto Again;
Jumping out of scope (for example out of the body of the for loop) is legal, but
jumping into a scope (for example from one function to another) is not allowed.
35. How many arguments printf() function take?
Syntax:
int printf ( const char *format [, argument, ...]);
The ...printf functions do the following:
Accept a series of arguments
Apply to each argument a format specifier
contained in the format string *format
Output the formatted data (to the screen, a stream, stdin, or a string)
These functions apply the first format specifier to the first argument, the
second specifier to the second argument, the third to the third, etc., to
the end of the format.
There must be enough arguments for the format.
If there are not, the results will be unpredictable and likely disastrous.
Excess arguments (more than required by the format) are merely ignored.
36. How many times an infinity loop executes?
Infinite number of times.

Das könnte Ihnen auch gefallen