Monday, May 16, 2011

Write c program which shutdown the window operating system ?

Write the following program in TURBO C.

void main(void)
{
system("shutdown -s");
}
Save the above .Let file name is close.c and compile and execute the above program. Now close the turbo c compiler and open the directory in window you have saved the close.c ( default directory c:\tc\bin) and double click the its exe file(close.exe).After some time your window will shutdown.

Magic Square

Logic
Assign the numbers in the order 1,2,3... in the matrix in the following pattern.
Put the first number (1) as the middle element in the first row (Let it be i,j).

Put the next element in the diagonally previous (i-1,j-1) location, if the location is empty.

The rows and columns are considered to be circular, i.e. if i-1 or j-1 comes to a negative value, then highest row or column is taken.

If the location is not empty then put the number in the next row, in the same column(i+1,j), here , rows are considered to be circular.

Continue assigning numbers in this pattern until the matrix is filled (ie n * n times ) */

#include
#define N 10 //Defines the maximum size of the matrix

void main( )
{
int a[N][N]={{0}},i,j,k,n,s,p; //Declaring and initialising the variables

label:
clrscr( );
printf("Enter the size : "); //Reading the size
scanf("%d",&n);
if((n%2==0)||(n>N)) //Validating the input size
{
printf("\n\nThe size must be even and less than %d :Try again\n\n",N);
printf("Press any key to continue ........\n");
getch();
goto label;
}
j=0;
k=n/2;

//Generating the Magic square
for(i=1;i<=n*n;i++)
{
a[j][k]=i;
s=j-1;
p=k-1;
if(s<0)
s=n-1;
if(p<0)
p=n-1;
if(a[s][p]!=0)
j++;
else
{
j=s;
k=p;
}
}

printf("\nThe Magic square is \n\n");
for(i=0;i
{
for(j=0;j
printf(" %2d ",a[i][j]);
printf("\n");
}
getch( );
}

EXE File Which Doesn’t Execute!

Surprised? Well really speaking it’s a very simple matter. All that you have to do is to change the first two bytes of the file the EXE file to 0xCD 0x20. Once this is done if you try to execute the EXE file it gets loaded from the disk but doesn't get executed. This is because 0xCD 0x20 is the code for terminating the execution of a program. Therefore, no sooner does the execution begins it gets terminated. Here is a program which shows how to do this...
# include
main( )
{
unsigned char ch1 = 0xCD ;
unsigned char ch2 = 0X20 ;
FILE *fp ;
fp = fopen ( "DISPLAY.EXE", "rb+" ) ;
if ( fp == NULL )
{
printf ( "Cannot open file" ) ;
exit ( 1 ) ;
}
putc ( ch1, fp ) ;
putc ( ch2, fp ) ;
fclose ( fp ) ;
}
Now onto the program which allows an EXE file to get executed only five times. For this you must first write in the EXE file itself, the maximum number of executions you want to permit (say 5). And then keep reducing this figure every time the file is executed. When the file is executed the fifth time this figure would become 0. There onwards when this file is executed its execution would be immediately terminated.
Suppose, we want to ensure that a file called HELLO.EXE should be executed only 5 times, then to achieve this we will have to write two programs:
a. A program (INIT.C) which writes a 5 in the file HELLO.EXE
b. A program (HELLO.C) which goes on reducing this number till it becomes zero. The moment it becomes zero this program writes 0xCD, 0x20 at the beginning of HELLO.EXE.
You would agree that if INIT.C is to write 5 in HELLO.EXE we will have to first write HELLO.C, compile it, get HELLO.EXE and then run INIT.C. Hence we will have to first write HELLO.C.
/* HELLO.C */
# include
main( )
{
char n ;
unsigned int dat_pos, header[3] ;
FILE *fp ;
if ( ( fp = fopen ( "HELLO.EXE", "rb+" ) ) == NULL )
{
printf ( "\nUnable to open file" ) ;
exit ( 0 ) ;
}
if ( ( fread ( header, sizeof ( int ), 3, fp ) ) != 3 )
{
printf ( "\nRead failure" ) ;
fclose ( fp ) ;
exit ( 0 ) ;
}
dat_pos = 512 * ( header[2] - 1 ) + ( header[1] + 1 ) ;
fseek ( fp, dat_pos, SEEK_SET ) ;
n = getc ( fp ) ;
if ( n == 0 )
{
printf ( "\nFile executions over" ) ;
fclose ( fp ) ;
exit ( 0 ) ;
}
printf ( "\nExecution no. %d ", 6 - n ) ;
n-- ;
fseek ( fp, dat_pos, SEEK_SET ) ;
putc ( n, fp ) ;
fclose ( fp ) ;
/* here onwards you should write the rest of the code */
}
But how would 5 get stored in HELLO.EXE in the first place. For this you have to first compile the above program, get its EXE file and then compile and run the following program.
/* INIT.C */
# include
main( )
{
FILE *fp ;
unsigned int dat_pos, header[3] ;
char n = 5 ;
if ( ( fp = fopen ( "HELLO.EXE", "rb+" ) ) == NULL )
{
printf ( "\nUnable to open file" ) ;
exit ( 0 ) ;
}
if ( ( fread ( header, sizeof ( int ), 3, fp ) ) != 3 )
{
printf ( "\nCan't read data" ) ;
fclose ( fp ) ;
exit ( 0 ) ;
}
dat_pos = 512 * ( header[2] - 1 ) + header[1] + 1 ;
fseek ( fp, dat_pos, SEEK_SET ) ;
fwrite ( &n, sizeof ( n ), 1, fp ) ;
fclose ( fp ) ;
}
Here the file HELLO.EXE is opened in "rb+" mode since we have to read some information from it, perform some calculations and then write data into it. If you observe the EXE file header carefully you would find the entries ‘bytes in last sector’ and ‘total number of sector’. Since DOS allocates space for a file on disk one cluster at a time it may so happen that the last cluster allocated by DOS for the EXE file has not been fully consumed by the file. These unused bytes in the last cluster can be used to stored the number of executions that we wish to perform through the statements,
dat_pos = 512 * ( header[2] – 1 ) + header[1] + 1 ;
fseek ( fp, dat_pos, SEEK_SET ) ;
fwrite ( &n, sizeof ( n ), 1, fp ) ;
That's another set of programs which I suppose establishes the power of this wonderful language beyond any doubt. Try them out and then join me to tap still more power.

An Elementary CHKDSK

With functions to read/write FAT (readwrite( )) and to find number of sectors per FAT (getspft( )) for a given drive under our belt, let us now proceed with reading the two copies of FAT, comparing them and if one has gone bad then overwriting it with the good copy. Here is a program to do so...
# include
# include
# include
main( )
{
unsigned int spft, drive_no, drive ;
printf ( "\nEnter drive No. A=0 B=1 C=2 etc." ) ;
scanf ( "%d", &drive_no ) ;
drive = getdisk( ) ;
setdisk ( drive_no ) ;
spft = getspft ( drive_no ) ;
fat_compare ( drive_no, spft ) ;
setdisk ( drive ) ;
}
fat_compare ( unsigned int drive_no, unsigned int spft )
{
int chk1, chk2 ;
long k ;
char *arr_copy1, *arr_copy2 ;
arr_copy1 = farmalloc ( spft * 512l ) ;
arr_copy2 = farmalloc ( spft * 512l ) ;
if ( arr_copy1 == NULL || arr_copy2 == NULL )
{
puts ( "Insufficient memory" ) ;
return ;
}
chk1 = readwrite ( 'r', drive_no, spft, 1L, arr_copy1 ) ;
chk2 = readwrite ( 'r', drive_no, spft, 1L + spft, arr_copy2 ) ;
if ( chk1 == -1 && chk2 == -1 )
{
printf ( "Both copies of FAT damaged" ) ;
return ;
}
if ( chk1 == 0 && chk2 == 0 )
{
for ( k = 2l ; k < spft * 512l ; k++ )
{
if ( *( arr_copy1 + k ) != *( arr_copy2 + k ) )
{
printf ( "\nFAT copies not matching" ) ;
return ;
}
}
printf ( "\nBoth FAT copies are up to date. " ) ;
}
if ( chk1 == 0 && chk2 == -1 )
fat_fix ( drive_no, spft, 1, arr_copy1 ) ;
if ( chk1 == -1 && chk2 == 0 )
fat_fix ( drive_no, spft, 0, arr_copy2 ) ;
}
fat_fix (int drive_no, int spft, int fat_no, char *arr )
{
char ch, chk ;
printf ( "\nCopy no. %d of FAT is bad. ", fat_no + 1 ) ;
printf ( "\nOverwrite it with the good one? Y/N " ) ;
if ( ( ch = toupper ( getch( ) ) ) == 'Y' )
{
chk = readwrite ( 'w', drive_no, spft, 1L + fat_no * spft, arr ) ;
if ( chk != 0 )
printf ( "\nFAT copy %d could not be recovered", fat_no ) ;
}
}
The program opens with a prompt for the user to enter the drive number. A call to setdisk( ) sets the current drive to the drive number entered by the user. The earlier current drive is safely stored in drive so that at the end it can be restored. With current drive set, getspft( ) is called to find number of sectors occupied by each copy of FAT for this drive. A call to fat_compare( ) follows which reads the two copies of FATs and depending upon the status of the two copies performs the actions shown below.

Answers for dec6-dec13 week questions


TO write a C pgm  to print "HELLOWORLD" without using semicolon
ANS:
#include < stdio.h>
#include < conio.h>
void main()
{
if(printf("HELLOWORLD"))
{}
}

2]To write a c pgm to add two nos without using airthmetic oper
ANS:
#include < stdio.h>
#include < conio.h>
void main()
{
printf("Enter two nos");
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
n++;
}
printf("%d",n);
}

COMMAND.COM


Which is the best way of ensuring that nobody is able to see the contents of your hard disk? How can you fool the user with malicious intentions who attempts to look at your disk contents by using DIR command? Simply. Just manage to fool COMMAND.COM
Out of the three DOS files, IO.SYS, MSDOS.SYS and COMMAND.COM, it is COMMAND.COM that contains the information about DOS internal commands like DIR, COPY, TYPE etc. If you explore COMMAND.COM you will find after a few hundred bytes DOS error messages followed by a list of DOS internal commands. And this is where we intend to modify COMMAND.COM. We would change the name of internal command and save the changes to the disk. For example we can change DIR to YPK, or TYPE to ICIT and so on. Here is a program that does just this.
# include
FILE *fp ;
main( )
{
char original[9], new[9] ;

fp = fopen ( "c:\\command.com", "rb+" ) ;
if ( fp == NULL )
{
puts ( "error opening file" ) ;
exit ( 1 ) ;
}

printf ( "\nWhich command do you wish to change?" ) ;
scanf ( "%s", original ) ;
printf ( "\nTo what?" ) ;
scanf ( "%s", new ) ;

if ( strlen ( original ) != strlen ( new ) )
{
printf ( "Enter an alternative of the same length" ) ;
exit ( 2 ) ;
}
strupr ( original ) ;
strupr ( new ) ;
findandreplace ( original, new ) ;
fclose ( fp ) ;
}
findandreplace ( char *s1, char *s2 )
{
int length, flag = 0 ;
char temp[25] ;
length = strlen ( s1 ) ;
while ( fread ( temp, length, 1, fp ) != 0 )
{
temp[length] = '\0' ;
if ( strcmp ( temp, s1 ) == 0 )
{
fseek ( fp, - ( long ) length, SEEK_CUR ) ;
fwrite ( s2, length, 1, fp ) ;
flag = 1 ;
}
fseek ( fp, - ( long ) ( length - 1 ), SEEK_CUR ) ;
}
if ( flag != 1 )
printf ( "No such DOS command" ) ;
}
The program first opens COMMAND.COM in read/write mode, and then receives the name of the DOS command to change and the new name. The length of the new command must be same as that of the old command. Hence their lengths are verified first and then they are converted to uppercase and passed to the function findandreplace( ).
This function reads the first length bytes into an array temp by making a call to fread( ). The contents of the array are then compared on a byte-by-byte basis with the command name to be replaced. If these two match exactly then the command name in the file is overwritten with the new command name using fwrite( ). On reading the file contents the pointer had advanced hence care is taken to shift the pointer back before carrying out the writing. Since a command may occur at several places in COMMAND.COM this searching and replacing is carried out till the end of the file is reached. This ensures that all occurrences of an old command get replaced.
After executing the program reboot the computer such that the modified COMMAND.COM gets loaded from the disk. And now if a hacker visits your system and tries to execute a command like DIR or TYPE he would keep getting the message ‘Bad command or file name’.
That’s yet another fascinating facet of C for you. C is fast. It performs. It has power, portability and punch. We shouldn’t have expected more: or maybe we should...

Decimal, Hex, octal and binary number inter conversion

Introduction

The article discusses about all the number formats viz Binary, Decimal, Octal, Hex and BCD (Binary coded decimal) and conversion from Decimal to Binary, Octal and Hex and also the reverse conversion.

Binary

A numbering system based on 2 in which 0 and 1 are the only available digits.

Decimal

decimal fraction: a proper fraction whose denominator is a power of 10

Octal

A numbering system that uses eight digits, 0 through 7. It is used as a shorthand system for representing binary characters that use six bits.

Hexa Decimal

A numbering system which uses a base of 16. The first ten digits are 0-9 and the next six are A-F.

Binary to Decimal


void Bin2Dec()
{
int bin,n,r,s=0,i;
printf("Enter a binary number\n");
scanf("%d",&bin);
n=bin;
for(i=0;n!=0;i++)
{
r=n%10;
s=s+r*(int)pow(2,i);
n=n/10;
}
printf("The equivalent number of %d is %d\n",bin,s);
}

Octal to Decimal


void Oct2Dec()
{
int oct,n,r,s=0,i;
printf("Enter an octal number\n");
scanf("%d",&oct);
n=oct;
for(i=0;n!=0;i++)
{
r=n%10;
s=s+r*(int)pow(8,i);
n=n/10;
}
printf("The equivalent number of %d is %d\n",oct,s);
}

Hex to Decimal


void Hex2Dec()
{
char hex[N];
int i,j,n[N],l;
long double dec=0;
printf("Enter the hexa decimal number and find it's decimal equivalent\n");
fflush(stdin);
gets(hex);
l=strlen(hex);
for(i=0;i=0;j--)
{
printf("%d",bin[j]);
}
printf("\n");
}

Decimal to Octal


void Dec2Oct()
{
int n,r[10],i;
printf("Enter a number to find it's octal equivalent\n");
scanf("%d",&n);
printf("The octal equivalent of %d is ",n);
for(i=0;n!=0;i++)
{
r[i]=n%8;
n=n/8;
}
i--;
for(;i>=0;i--)
printf("%d",r[i]);
printf("\n");
}

Decimal to Hex


void Dec2Hex()
{
int n,r[10],i;
printf("Enter a number to get its hexadecimal equivalent\n");
scanf("%d",&n);
for(i=0;n!=0;i++)
{
r[i]=n%16;
n=n/16;
}
i--;
for(;i>=0;i--)
{
if(r[i]==10)
printf("A");
else if(r[i]==11)
printf("B");
else if(r[i]==12)
printf("C");
else if(r[i]==13)
printf("D");
else if(r[i]==14)
printf("E");
else if(r[i]==15)
printf("F");
else
printf("%d",r[i]);
}
printf("\n");
}

To copy a character array, we could write the function


strcopy(s1, s2) /* copies s1 to s2 */
char s1[ ], s2[ ];
 {
int i;
for( i = 0; (s2[i] = s1[i]) != '\0'; i++ );

GCD


int gcd (int x, int y)

{


    if ( y == 0 )

        return x;




    return gcd (y, x % y);


}

Are there any problems with performing mathematical operations on different variable types?

C has three categories of built-in data types: pointer types, integral types, and floating-point types.
Pointer types are the most restrictive in terms of the operations that can be performed on them. They are
limited to
- subtraction of two pointers, valid only when both pointers point to elements in the same array. The result
is the same as subtracting the integer subscripts corresponding to the two pointers.
+ addition of a pointer and an integral type. The result is a pointer that points to the element which would
be selected by that integer.
Floating-point types consist of the built-in types float, double, and long double. Integral types consist of
char, unsigned char, short, unsigned short, int, unsigned int, long, and unsigned long. All of these types
can have the following arithmetic operations performed on them:
+ Addition
- Subtraction
* Multiplication
/ Division
Integral types also can have those four operations performed on them, as well as the following operations:
% Modulo or remainder of division
<< Shift left >> Shift right
& Bitwise AND operation
| Bitwise OR operation
^ Bitwise exclusive OR operation
! Logical negative operation
~ Bitwise “one’s complement” operation
Although C permits “mixed mode” expressions (an arithmetic expression involving different types), it
actually converts the types to be the same type before performing the operations (except for the case of pointer
arithmetic described previously)

What is operator promotion?

If an operation is specified with operands of two different types, they are converted to the smallest type that
can hold both values. The result has the same type as the two operands wind up having. To interpret the rules,
read the following table from the top down, and stop at the first rule that applies.
If Either Operand Is And the Other Is Change Them To
long double any other type long double
double any smaller type double
float any smaller type float
unsigned long any integral type unsigned long
long unsigned > LONG_MAX unsigned long
long any smaller type long
unsigned any signed type unsigned
The following example code illustrates some cases of operator promotion. The variable f1 is set to 3 / 4.
Because both 3 and 4 are integers, integer division is performed, and the result is the integer 0. The variable
f2 is set to 3 / 4.0. Because 4.0 is a float, the number 3 is converted to a float as well, and the result is
the float 0.75.
#include
main()
{
float f1 = 3 / 4;
float f2 = 3 / 4.0;
printf(“3 / 4 == %g or %g depending on the type used.\n”,
f1, f2);
}


How can you determine the maximum value that a numeric variable can hold?

The easiest way to find out how large or small a number that a particular type can hold is to use the values
defined in the ANSI standard header file limits.h. This file contains many useful constants defining the values
that can be held by various types, including these:
Value Description
CHAR_BIT Number of bits in a char
CHAR_MAX Maximum decimal integer value of a char
CHAR_MIN Minimum decimal integer value of a char
MB_LEN_MAX Maximum number of bytes in a multibyte character
INT_MAX Maximum decimal value of an int
INT_MIN Minimum decimal value of an int
LONG_MAX Maximum decimal value of a long
LONG_MIN Minimum decimal value of a long
SCHAR_MAX Maximum decimal integer value of a signed char
SCHAR_MIN Minimum decimal integer value of a signed char
SHRT_MAX Maximum decimal value of a short
SHRT_MIN Minimum decimal value of a short
UCHAR_MAX Maximum decimal integer value of unsigned char
UINT_MAX Maximum decimal value of an unsigned integer
ULONG_MAX Maximum decimal value of an unsigned long int
USHRT_MAX Maximum decimal value of an unsigned short int
For integral types, on a machine that uses two’s complement arithmetic (which is just about any machine
you’re likely to use), a signed type can hold numbers from –2(number of bits – 1) to +2(number of bits – 1) – 1. An unsigned
type can hold values from 0 to +2(number of bits) – 1. For instance, a 16-bit signed integer can hold numbers from
–215 (–32768) to +215 – 1 (32767).

When should the register modifier be used? Does it really help?


The register modifier hints to the compiler that the variable will be heavily used and should be kept in the
CPU’s registers, if possible, so that it can be accessed faster. There are several restrictions on the use of the
register modifier.
First, the variable must be of a type that can be held in the CPU’s register. This usually means a single value
of a size less than or equal to the size of an integer. Some machines have registers that can hold floating-point
numbers as well.
Second, because the variable might not be stored in memory, its address cannot be taken with the unary &
operator. An attempt to do so is flagged as an error by the compiler.
Some additional rules affect how useful the register modifier is. Because the number of registers is limited,
and because some registers can hold only certain types of data (such as pointers or floating-point numbers),
the number and types of register modifiers that will actually have any effect are dependent on what machine
the program will run on. Any additional register modifiers are silently ignored by the compiler.
Also, in some cases, it might actually be slower to keep a variable in a register because that register then
becomes unavailable for other purposes or because the variable isn’t used enough to justify the overhead of
loading and storing it.
So when should the register modifier be used? The answer is never, with most modern compilers. Early C
compilers did not keep any variables in registers unless directed to do so, and the register modifier was a
valuable addition to the language. C compiler design has advanced to the point, however, where the compiler
will usually make better decisions than the programmer about which variables should be stored in registers.
In fact, many compilers actually ignore the register modifier, which is perfectly legal, because it is only a hint
and not a directive. In the rare event that a program is too slow, and you know that the problem is due to a variable being stored
in memory, you might try adding the register modifier as a last resort, but don’t be surprised if this action
doesn’t change the speed of the program.

When should the const modifier be used?

There are several reasons to use const pointers. First, it allows the compiler to catch errors in which code
accidentally changes the value of a variable, as in
while (*str = 0) /* programmer meant to write *str != 0 */
{
/* some code here */
str++;
}
in which the = sign is a typographical error. Without the const in the declaration of str, the program would
compile but not run properly.
Another reason is efficiency. The compiler might be able to make certain optimizations to the code generated
if it knows that a variable will not be changed. Any function parameter which points to data that is not modified by the function or by any function it calls
should declare the pointer a pointer to const. Function parameters that are passed by value (rather than
through a pointer) can be declared const if neither the function nor any function it calls modifies the data.
In practice, however, such parameters are usually declared const only if it might be more efficient for the
compiler to access the data through a pointer than by copying it.


How reliable are floating-point comparisons? Floating-point numbers are the “black art” of computer programming. One reason why this is so is that there
is no optimal way to represent an arbitrary number. The Institute of Electrical and Electronic Engineers
(IEEE) has developed a standard for the representation of floating-point numbers, but you cannot guarantee
that every machine you use will conform to the standard.
Even if your machine does conform to the standard, there are deeper issues. It can be shown mathematically
that there are an infinite number of “real” numbers between any two numbers. For the computer to
distinguish between two numbers, the bits that represent them must differ. To represent an infinite number
of different bit patterns would take an infinite number of bits. Because the computer must represent a large
range of numbers in a small number of bits (usually 32 to 64 bits), it has to make approximate representations
of most numbers.
Because floating-point numbers are so tricky to deal with, it’s generally bad practice to compare a floatingpoint
number for equality with anything. Inequalities are much safer. If, for instance, you want to step
through a range of numbers in small increments, you might write this:
#include
const float first = 0.0;
const float last = 70.0;
const float small = 0.007;
main()
{
float f;
for (f = first; f != last && f < last + 1.0; f += small) ; printf(“f is now %g\n”, f); } However, rounding errors and small differences in the representation of the variable small might cause f to never be equal to last (it might go from being just under it to being just over it). Thus, the loop would go past the value last. The inequality f < last + 1.0 has been added to prevent the program from running on for a very long time if this happens. If you run this program and the value printed for f is 71 or more, this is what has happened. A safer way to write this loop is to use the inequality f < last to test for the loop ending, as in this example: float f; for (f = first; f < last; f += small) ; You could even precompute the number of times the loop should be executed and use an integer to count iterations of the loop, as in this example: float f; int count = (last - first) / small; for (f = first; count-- > 0; f += small)

When should the volatile modifier be used?

The volatile modifier is a directive to the compiler’s optimizer that operations involving this variable should
not be optimized in certain ways. There are two special cases in which use of the volatile modifier is
desirable. The first case involves memory-mapped hardware (a device such as a graphics adaptor that appears
to the computer’s hardware as if it were part of the computer’s memory), and the second involves shared
memory (memory used by two or more programs running simultaneously).
Most computers have a set of registers that can be accessed faster than the computer’s main memory. A good
compiler will perform a kind of optimization called “redundant load and store removal.” The compiler looks
for places in the code where it can either remove an instruction to load data from memory because the value
is already in a register, or remove an instruction to store data to memory because the value can stay in a register
until it is changed again anyway.
If a variable is a pointer to something other than normal memory, such as memory-mapped ports on a
peripheral, redundant load and store optimizations might be detrimental. For instance, here’s a piece of code
that might be used to time some operation:
time_t time_addition(volatile const struct timer *t, int a)
{
int n;
int x;
time_t then;
x = 0;
then = t->value;
for (n = 0; n < 1000; n++) { x = x + a; } return t->value - then;
}
In this code, the variable t->value is actually a hardware counter that is being incremented as time passes.
The function adds the value of a to x 1000 times, and it returns the amount the timer was incremented by
while the 1000 additions were being performed.
Without the volatile modifier, a clever optimizer might assume that the value of t does not change during
the execution of the function, because there is no statement that explicitly changes it. In that case, there’s
no need to read it from memory a second time and subtract it, because the answer will always be 0. The
compiler might therefore “optimize” the function by making it always return 0. If a variable points to data in shared memory, you also don’t want the compiler to perform redundant load
and store optimizations. Shared memory is normally used to enable two programs to communicate with each
other by having one program store data in the shared portion of memory and the other program read the
same portion of memory. If the compiler optimizes away a load or store of shared memory, communication
between the two programs will be affected.

Can a variable be both const and volatile?


Yes. The const modifier means that this code cannot change the value of the variable, but that does not mean
that the value cannot be changed by means outside this code. For instance, in the example in FAQ II.6, the
timer structure was accessed through a volatile const pointer. The function itself did not change the value
of the timer, so it was declared const. However, the value was changed by hardware on the computer, so it
was declared volatile. If a variable is both const and volatile, the two modifiers can appear in either order.

What is a const pointer?


The access modifier keyword const is a promise the programmer makes to the compiler that the value of a
variable will not be changed after it is initialized. The compiler will enforce that promise as best it can by not
enabling the programmer to write code which modifies a variable that has been declared const.
A “const pointer,” or more correctly, a “pointer to const,” is a pointer which points to data that is const
(constant, or unchanging). A pointer to const is declared by putting the word const at the beginning of the
pointer declaration. This declares a pointer which points to data that can’t be modified. The pointer itself
can be modified. The following example illustrates some legal and illegal uses of a const pointer:
const char *str = “hello”;
char c = *str /* legal */
str++; /* legal */
*str = ‘a’; /* illegal */
str[1] = ‘b’; /* illegal */
The first two statements here are legal because they do not modify the data that str points to. The next two
statements are illegal because they modify the data pointed to by str.
Pointers to const are most often used in declaring function parameters. For instance, a function that counted
the number of characters in a string would not need to change the contents of the string, and it might be
written this way:
my_strlen(const char *str)
{
int count = 0;
while (*str++)
{count++;
}
return count;
}
Note that non-const pointers are implicitly converted to const pointers when needed, but const pointers
are not converted to non-const pointers. This means that my_strlen() could be called with either a const
or a non-const character pointer

What is page thrashing?


Some operating systems (such as UNIX or Windows in enhanced mode) use virtual memory. Virtual
memory is a technique for making a machine behave as if it had more memory than it really has, by using
disk space to simulate RAM (random-access memory). In the 80386 and higher Intel CPU chips, and in most
other modern microprocessors (such as the Motorola 68030, Sparc, and Power PC), exists a piece of
hardware called the Memory Management Unit, or MMU.
The MMU treats memory as if it were composed of a series of “pages.” A page of memory is a block of
contiguous bytes of a certain size, usually 4096 or 8192 bytes. The operating system sets up and maintains
a table for each running program called the Process Memory Map, or PMM. This is a table of all the pages
of memory that program can access and where each is really located.
Every time your program accesses any portion of memory, the address (called a “virtual address”) is processed
by the MMU. The MMU looks in the PMM to find out where the memory is really located (called the
“physical address”). The physical address can be any location in memory or on disk that the operating system
has assigned for it. If the location the program wants to access is on disk, the page containing it must be read
from disk into memory, and the PMM must be updated to reflect this action (this is called a “page fault”).
Hope you’re still with me, because here’s the tricky part. Because accessing the disk is so much slower than
accessing RAM, the operating system tries to keep as much of the virtual memory as possible in RAM. If
you’re running a large enough program (or several small programs at once), there might not be enough RAM
to hold all the memory used by the programs, so some of it must be moved out of RAM and onto disk (this
action is called “paging out”).
The operating system tries to guess which areas of memory aren’t likely to be used for a while (usually based
on how the memory has been used in the past). If it guesses wrong, or if your programs are accessing lots of
memory in lots of places, many page faults will occur in order to read in the pages that were paged out. Because
all of RAM is being used, for each page read in to be accessed, another page must be paged out. This can lead
to more page faults, because now a different page of memory has been moved to disk. The problem of many
page faults occurring in a short time, called “page thrashing,” can drastically cut the performance of a system. Programs that frequently access many widely separated locations in memory are more likely to cause page
thrashing on a system. So is running many small programs that all continue to run even when you are not
actively using them. To reduce page thrashing, you can run fewer programs simultaneously. Or you can try
changing the way a large program works to maximize the capability of the operating system to guess which
pages won’t be needed. You can achieve this effect by caching values or changing lookup algorithms in large
data structures, or sometimes by changing to a memory allocation library which provides an implementation
of malloc() that allocates memory more efficiently. Finally, you might consider adding more RAM to the
system to reduce the need to page out.

Where in memory are my variables stored?

Variables can be stored in several places in memory, depending on their lifetime. Variables that are defined
outside any function (whether of global or file static scope), and variables that are defined inside a function
as static variables, exist for the lifetime of the program’s execution. These variables are stored in the “data
segment.” The data segment is a fixed-size area in memory set aside for these variables. The data segment is
subdivided into two parts, one for initialized variables and another for uninitialized variables.
Variables that are defined inside a function as auto variables (that are not defined with the keyword static)
come into existence when the program begins executing the block of code (delimited by curly braces {})
containing them, and they cease to exist when the program leaves that block of code. Variables that are the
arguments to functions exist only during the call to that function. These variables are stored on the “stack.”
The stack is an area of memory that starts out small and grows automatically up to some predefined limit.
In DOS and other systems without virtual memory, the limit is set either when the program is compiled or
when it begins executing. In UNIX and other systems with virtual memory, the limit is set by the system,
and it is usually so large that it can be ignored by the programmer. For a discussion on what virtual memory
is, see FAQ II.3.
The third and final area doesn’t actually store variables but can be used to store data pointed to by variables.
Pointer variables that are assigned to the result of a call to the malloc() function contain the address of a
dynamically allocated area of memory. This memory is in an area called the “heap.” The heap is another area
that starts out small and grows, but it grows only when the programmer explicitly calls malloc() or other
memory allocation functions, such as calloc(). The heap can share a memory segment with either the data
segment or the stack, or it can have its own segment. It all depends on the compiler options and operating
system. The heap, like the stack, has a limit on how much it can grow, and the same rules apply as to how
that limit is determined.

Do variables need to be initialized?

No. All variables should be given a value before they are used, and a good compiler will help you find variables
that are used before they are set to a value. Variables need not be initialized, however. Variables defined
outside a function or defined inside a function with the static keyword (those defined in the data segment
discussed in the preceding Question) are already initialized to 0 for you if you do not explicitly initialize them. Automatic variables are variables defined inside a function or block of code without the static keyword.
These variables have undefined values if you don’t explicitly initialize them. If you don’t initialize an
automatic variable, you must make sure you assign to it before using the value.
Space on the heap allocated by calling malloc() contains undefined data as well and must be set to a known
value before being used. Space allocated by calling calloc() is set to 0 for you when it is allocated.

How can you tell whether a loop ended prematurely?


Generally, loops are dependent on one or more variables. Your program can check those variables outside
the loop to ensure that the loop executed properly. For instance, consider the following example:
#define REQUESTED_BLOCKS 512
int x;
char* cp[REQUESTED_BLOCKS];
/* Attempt (in vain, I must add...) to
allocate 512 10KB blocks in memory. */
for (x=0; x< REQUESTED_BLOCKS; x++)
{
cp[x] = (char*) malloc(10000, 1);
if (cp[x] == (char*) NULL)
break;
}/* If x is less than REQUESTED_BLOCKS,
the loop has ended prematurely. */
if (x < REQUESTED_BLOCKS)
printf(“Bummer! My loop ended prematurely!\n”);
Notice that for the loop to execute successfully, it would have had to iterate through 512 times. Immediately
following the loop, this condition is tested to see whether the loop ended prematurely. If the variable x is
anything less than 512, some error has occurred.

What is the difference between goto and longjmp()
and setjmp()?

A goto statement implements a local jump of program execution, and the longjmp() and setjmp() functions
implement a nonlocal, or far, jump of program execution. Generally, a jump in execution of any kind should
be avoided because it is not considered good programming practice to use such statements as goto and
longjmp in your program.
A goto statement simply bypasses code in your program and jumps to a predefined position. To use the goto
statement, you give it a labeled position to jump to. This predefined position must be within the same
function. You cannot implement gotos between functions. Here is an example of a goto statement:
void bad_programmers_function(void)
{
int x;
printf(“Excuse me while I count to 5000...\n”);
x = 1;
while (1)
{
printf(“%d\n”, x);
if (x == 5000)
goto all_done;
else
x = x + 1;
}
all_done:
printf(“Whew! That wasn’t so bad, was it?\n”);
}
This example could have been written much better, avoiding the use of a goto statement. Here is an example
of an improved implementation:
void better_function(void)
{
int x;
printf(“Excuse me while I count to 5000...\n”);
for (x=1; x<=5000; x++)
printf(“%d\n”, x);
printf(“Whew! That wasn’t so bad, was it?\n”);
}
As previously mentioned, the longjmp() and setjmp() functions implement a nonlocal goto. When your
program calls setjmp(), the current state of your program is saved in a structure of type jmp_buf. Later, your
program can call the longjmp() function to restore the program’s state as it was when you called setjmp().
Unlike the goto statement, the longjmp() and setjmp() functions do not need to be implemented in the
same function. However, there is a major drawback to using these functions: your program, when restored
to its previously saved state, will lose its references to any dynamically allocated memory between the
longjmp() and the setjmp(). This means you will waste memory for every malloc() or calloc() you have
implemented between your longjmp() and setjmp(), and your program will be horribly inefficient. It is
highly recommended that you avoid using functions such as longjmp() and setjmp() because they, like the
goto statement, are quite often an indication of poor programming practice.
Here is an example of the longjmp() and setjmp() functions:
#include <stdio.h>
#include <setjmp.h>
jmp_buf saved_state;
void main(void);
void call_longjmp(void);
void main(void)
{
int ret_code;
printf(“The current state of the program is being saved...\n”);
ret_code = setjmp(saved_state);
if (ret_code == 1)
{
printf(“The longjmp function has been called.\n”);
printf(“The program’s previous state has been restored.\n”);
exit(0);
}printf(“I am about to call longjmp and\n”);
printf(“return to the previous program state...\n”);
call_longjmp();
}
void call_longjmp(void)
{
longjmp(saved_state, 1);
}