Beruflich Dokumente
Kultur Dokumente
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:
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.
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.
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).
#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?
argv[1] - "aaa"
argv[2] - "bbb"
argv[3] - "ccc"
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)
if (j > 0)
* this block */
printf("i is %d\n",i);
}
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 */
}