*4 Assignment & Logical compares*

*4.1 Integer Assignment Statements*

Load the file intasign.c and display it for an example of assignment statements.

**/* This program will illustrate the assignment statements */**

**main( )**

**{**

**int a,b,c; /* Interger variables for examples */**

**a = 12;**

**b = 3;**

**c = a + b; /* simple addition */**

**c = a - b; /* simple subtraction */**

**c = a * b; /* simple multiplication */**

**c = a / b; /* simple addition */**

**c = a % b; /* simple modulo (remainder) */**

**c = 12*a + b/2 - a*b*2/(a*c + b*2);**

**c = c/4+13*(a + b)/3 - a*b + 2*a*a;**

**a = a + 1; /* incrementing a variable */**

**b = b * 5;**

**a = b = c = 20; /* multiple assignment */**

**a = b = c = 12*13/4;**

**}**

Three variables are defined for use in the program and the rest of the program is merely a series

of illustrations of various assignments. The first two lines of the assignment statements assign

numerical values to "a" and "b", and the next four lines illustrate the five basic arithmetic

functions and how to use them. The fifth is the modulo operator and gives the remainder if the

two variables were divided. It can only be applied to "int" or "char" type variables, and of course

"int" extensions such as "long", "short", etc. Following these, there are two lines illustrating

how to combine some of the variables in some complex math expressions. All of the above

examples should require no comment except to say that none of the equations are meant to be

particularly useful except as illustrations.

The next two expressions are perfectly acceptable as given, but we will see later in this chapter

that there is another way to write these for more compact code.

This leaves us with the last two lines which may appear to you as being very strange. The C

compiler scans the assignment statement from right to left, (which may seem a bit odd since we

do not read that way), resulting in a very useful construct, namely the one given here. The

compiler finds the value 20, assigns it to "c", then continues to the left finding that the latest

result of a calculation should be assigned to "b". Thinking that the latest calculation resulted in

a 20, it assigns it to "b" also, and continues the leftward scan assigning the value 20 to "a" also.

This is a very useful construct when you are initializing a group of variables. The last statement

illustrates that it is possible to actually do some calculations to arrive at the value which will be

assigned to all three variables.

The program has no output, so compiling and executing this program will be very uninteresting.

Since you have already learned how to display some integer results using the "printf" function,

it would be to your advantage to add some output statements to this program to see if the various

statements do what you think they should do.

This would be a good time for a preliminary definition of a rule to be followed in C. The data

definitions are always given before any executable statements in any program block. This is

why the variables are defined first in this program and in any C program. If you try to define

a new variable after executing some statements, the compiler will issue an error.

*4.2 Additional Data Types*

Loading and editing mortypes.c will illustrate how some additional data types can be used.

**/* The purpose of the file is to introduce additional data types */**

**main( )**

**{**

**int a,b,c; /* -32768 to 32767 with no decimal point */**

**char x,y,z; /* 0 to 255 with no decimal point */**

**float num,toy,thing; /* 10E-38 to 10E+38 with decimal point */**

**a = b = c = -27;**

**x = y = z = ’A’;**

**num = toy = thing = 3.6792;**

**a = y; /* a is now 65 (character A) */**

**x = b; /* x will now be a funny number */**

**num = b; /* num will now be -27.00 */**

**a = toy; /* a will now be 3 */**

**}**

Once again we have defined a few integer type variables which you should be fairly familiar

with by now, but we have added two new types, the "char", and the "float".

The "char" type of data is nearly the same as the integer except that it can only be assigned

values between zero and 255, since it is stored in only one byte of memory. The "char" type of

data is usually used for ASCII data, more commonly known as text. The text you are reading

was originally written on a computer with a word processor that stored the words in the computer

one character per byte. In contrast, the integer data type is stored in two bytes of computer

memory on most 8 bit and MS-DOS based microcomputers.

The Applix 1616 uses a 68000 chip with true 32 bit registers, so integers are 32 bits. This means

the range of an integer is not ±32767, but ±2147483648, or over two billion! On the Applix, a

short int may be more appropriate in some places.

*4.3 Data Type Mixing*
It would be profitable at this time to discuss the way C handles the two types "char" and "int".

Most functions in C that are designed to operate with integer type variables will work equally

wellwith character type variables because they are a form of an integer variable. Those functions,

when called on to use a "char" type variable, will actually promote the "char" data into integer

data before using it. For this reason, it is possible to mix "char" and "int" type variables in nearly

any way you desire. The compiler will not get confused, but you might. It is good not to rely

on this too much, but to carefully use only the proper types of data where they should be used.

The second new data type is the "float" type of data, commonly called floating point data. This

is a data type which usually has a very large range, a large number of significant digits, and a

large number of computer words are required to store it. The "float" data type has a decimal

point associated with it and, on most computers, has an allowable range of from 10

-38

to 10

+38

.

Not all compilers have the same available range, so check your reference manual for the limits

on your compiler.

*4.4 How To Use The New Data Types*
The first three lines of the program assign values to all nine of the defined variables so we can

manipulate some of the data between the different types.

Since, as mentioned above, a "char" data type is in reality an "integer" data type, no special

considerations need be taken to promote a "char" to an "int" variable. When going the other

way, there is no standard, so you may simply get garbage if the value is within the range of zero

to 255. In the second line therefore, when attempting to set x (a char) to -27, you may or may

not get a well defined answer, it depends on your particular implementation of C.

The third line illustrates the simplicity of translating an integer into a "float", simply assign it

the new value and the system will do the proper conversion. When going the other way however,

there is an added complication. Since there may be a fractional part of the floating point number,

the system must decide what to do with it. By definition, it will truncate it.

This program produces no output, and we haven’t covered a way to print out "char" and "float"

type variables, so you can’t really get in to this program and play with the results, but the next

program will cover this for you.

*4.5 Characteristics of Variable Types*
One unfortunate problem with C (and some other languages) is that the actual size of variables

is somewhat dependant upon the machine (and compiler) being used. Difficulties are sometimes

experienced when moving code from one machine to another due to this.

A general rule of thumb for modern compilers is that char is at least 8 bits, short is at least

16 bits, long is at least 32 bits, int is the same as either short or long (which causes lots of

code conversions come unstuck), float is at least 32 bits, and double is at least as wide as

float. As a consequence, you should use either short or long in preference to int (despite

its heavy use in this tutorial), and should avoid double where possible. Note that using short

instead of int may save an extra memory access, and help speed up code, especially in large

loops.

integer 32 bit (assembles as .l, or ±2147483648)

character 8 bit (0 to 255)

float 32 bit (about 10

38

)

double 64 bit (10

308

maximum)

short 16 bit (assembles as .w, or ±32767)

long 32 bit (assembles as .l, or ±2147483648)

Byte ordering is another problem encountered when converting programs from one machine to

another. In the 68000, the low byte of a 16 bit word is the second, odd numbered, byte. The

bytes in a 32 bit long are laid out most significant byte at the address, with the least significant

byte below it. Intel chips use the opposite order. This byte sex problem leads to arguments akin

to those in religion and politics, and just as likely to lead to real solutions.

*4.6 Lots Of Variable Types*
Load the file lottypes.c and display it your screen.

**main( )**

**{**

**int a; /* simple integer type */**

**long int b; /* long integer type */**

**short int c; /* short integer type */**

**unsigned int d; /* unsigned integer type */**

**char e; /* character type */**

**float f; /* floating point type */**

**double g; /* double precision floating point */**

**a = 1023;**

**b = 2222;**

**c = 123;**

**d = 1234;**

**e = ’X’;**

**f = 3.14159;**

**g = 3.1415926535898;**

**printf("a = %d\n",a); /* decimal output */**

**printf("a = %o\n",a); /* octal output */**

**printf("a = %x\n",a); /* hexadecimal output */**

**printf("b = %1d\n",b); /* decimal long output */**

**printf("c = %d\n",c); /* decimal short output */**

**printf("d = %u\n",d); /* unsigned output */**

**printf("e = %c\n",e); /* character output */**

**printf("f = %f\n",f); /* floating output */**

**printf("g = %f\n",g); /* double float output */**

**printf("\n");**

**printf("a = %d\n",a); /* simple int output */**

**printf("a = %7d\n",a); /* use a field width of 7 */**

**printf("a = %-7d\n",a); /* left justify in field of 7 */**

**printf("\n");**

**printf("f = %f\n",f); /* simple float output */**

**printf("f = %12f\n",f); /* use field width of 12 */**

**printf("f = %12.3f\n",f); /* use 3 decimal places */**

**printf("f = %12.5f\n",f); /* use 5 decimal places */**

**printf("f = %-12.5f\n",f); /* left justify in field */**

**}**

This file contains every standard simple data type available in the programming language C.

There are other types, but they are the compound types that we will cover in due time.

There are other types, but they are the compound types that we will cover in due time.

Observe the file. First we define a simple "int" followed by a "long int" and a "short int". Consult

your reference manual for an exact definition of these for your compiler, because they are not

consistent from implementation to implementation. The "unsigned" is next and is defined as

the same size as the "int" but with no sign. The "unsigned" then will cover a range of 0 to 65535

on MS-DOS microcomputers, but as 0 to 4294967296 in HiTech. It should be pointed out that

when "long", "short", or "unsigned" is desired, the "int" is optional and left out by most

experienced programmers. We have already covered the "char" and the "float", which leaves

only the "double". The "double" usually covers a greater range than the "float" and has more

significant digits for more precise calculations. It also requires more memory to store a value

than the simple "float". Consultyour reference manualfor the range and accuracy of the "double".

Another diversion is in order at this point. Most compilers have provisions for floating point

math, but only double floating math. They will promote a "float" to a "double" before doing

calculations and therefore only one math library will be needed. Of course, this is totally

transparent to you, so you don’t need to worry about it. You may think that it would be best to

simply define every floating point variable as double, since they are promoted before use in any

calculations, but that may not be a good idea. A "float" variable requires 4 bytes of storage and

a "double" requires 8 bytes of storage, so if you have a large volume of floating point data to

store, the "double" will obviously require much more memory. Your compiler may require a

different number of bytes than 4 or 8. Consult your reference manual for the correct number of

bytes used by your compiler.

After defining the data types, a numerical value is assigned to each of the defined variables in

order to demonstrate the means of outputting each to the monitor.

*4.7 The Conversion Characters*
Following is a listof the conversion characters and the way they are used in the "printf" statement.

d decimal notation

o octal notation

x hexadecimal notation

u unsigned notation

c character notation

s string notation

f floating point notation

(the inbuilt Applix printf function has a %e conversion character, that prints the internal error

message corresponding to an error number - this is not standard in C.)

Each of these is used following a percent sign to indicate the type of output conversion, and

between those two characters, the following fields may be added.

- left justification in its field

(n) a number specifying minimum field width

. to separate n from m

(m) significant fractional digits for a float

l to indicate a "long"

These are all used in the examples which are included in the program presently displayed on

your monitor, with the exception of the string notation which will be covered later in this tutorial.

Compile and run this program to see what effect the various fields have on the output.

You now have the ability to display any of the data fields in the previous programs and it would

be to your advantage to go back and see if you can display any of the fields anyway you desire.

*4.8 Logical Compares*
Load and view the file named compares.c for many examples of compare statements in C.

**main( ) /* this file will illustrate logical compares */**

**{**

**int x = 11,y = 11,z = 11;**

**char a = 40,b = 40,c = 40;**

**float r = 12.987,s = 12.987,t = 12.987;**

**/* First group of compare statements */**

**if (x == y) z = -13; /* This will set z = -13 */**

**if (x > z) a = ‘A’; /* This will set a = 65 */**

**if (!(x > z)) a = ‘B’; /* This will change nothing */**

**if (b <= c) r = 0.0; /* This will set r = 0.0 */**

**if (r != s) t = c/2; /* This will set t = 20 */**

**/* Second group of compare statements */**

**if (x = (r != s)) z = 1000; /* This will set x = some positive**

**number and z = 1000 */**

**if (x = y) z = 222; /* This sets x = y, and z = 222 */**

**if (x != 0) z = 333; /* This sets z = 333 */**

**if (x) z = 444; /* This sets z = 444 */**

**/* Third group of compare statements */**

**x = y = z = 77;**

**if ((x == y) && (x == 77)) z = 33; /* This sets z = 33 */**

**if ((x >y) || (z > 12)) z = 22; /* This sets z = 22 */**

**if ((x && y && z) z = 11; /* This sets z = 11 */**

**if ((x = 1) && (y = 2) && (z = 3)) r = 12.00; /* This sets**

**x = 1, y = 2, z = 3, r = 12 .00 */**

**if ((x == 2) && (y = 3) && (z = 4)) r = 14.56; /* This doesn’t**

**change anything */**

**/* Fourth group of compares */**

**if (x == x); z = 27.345; /* z always gets changed */**

**if (x != x) z = 27.345; /* Nothing gets changed */**

**if (x = 0) z = 27.345; /* This sets x = 0, z is unchanged */**

**}**

We begin by defining and initializing nine variables to use in the following compare statements.

This initialization is new to you and can be used to initialize variables while they are defined.

The first group of compare statements represents the simplest kinds of compares since they

simply compare two variables. Either variable could be replaced with a constant and still be

valid compare, but two variables is the general case. The first compare checks to see if "x" is

equal to "y" and it uses the double equal sign for the comparison. A single equal sign could be

used here but it would have a different meaning as we will see shortly. The second comparison

checks to see if "x" is greater than "z".

The third introduces the "NOT" operator, the exclamation, which can be used to invert the result

of any logical compare. The fourth checks for "b" less than or equal to "c", and the last checks

for "r" not equal to "s". As we learned in the last chapter, if the result of the compare is true,

the statement following the "if" clause will be executed and the results are given in the comments.

Note that "less than" and "greater than or equal to" are also available, but are not illustrated here.

It would be well to mention the different format used for the "if" statement in this example

program. A carriage return is not required as a statement separator and by putting the conditional

readability of the overall program.

*4.9 More Compares*
The compares in the second group are a bit more involved. Starting with the first compare, we

find a rather strange looking set of conditions in the parentheses. To understand this we must

understand just what a "true" or "false" is in the C language. A "false" is defined as a value of

zero, and "true" is defined as a non-zero value. Any integer or char type of variable can be used

for the result of a true/false test, or the result can be an implied integer or char.

Look at the first compare of the second group of compare statements. The expression "r is !=

s" will evaluate as a "true" since "r" was set to 0.0 above, so the result will be a non-zero value,

probably 1. Even though the two variables that are compared are "float" variables, the result

will be of type "integer". There is no explicit variable to which it will be assigned so the result

of the compare is an implied integer. Finally the resulting number, 1 in this case, is assigned

to the integer variable "x". If double equal signs were used, the phantom value, namely 1, would

be compared to the value of "x", but since the single equal sign is used, the value 1 is simply

assigned to "x", as though the statement were not in parentheses. Finally, since the result of the

assignment in the parentheses was non-zero, the entire expression is evaluated as "true", and

"z" is assigned the value of 1000. Thus we accomplished two things in this statement, we

assigned "x" a new value, probably 1, and we assigned "z" the value 1000. We covered a lot in

this statement so you may wish to review it before going on. The important things to remember

are the values that define "true" and "false", and the fact that several things can be assigned in

a conditional statement. The value assigned to "x" was probably a 1 but different compilers

may assign a different value as long as it is non-zero.

The next example should help clear up some of the above in your mind. In this example, "x"

is assigned the value of "y", and since the result is 11, the condition is non-zero, which is true,

and the variable "z" is therefore assigned 222.

The third example, in the second group, compares "x" to zero. If the result is true, meaning that

if "x" is not zero, then "z" is assigned the value of 333, which it will be. The last example in

this group illustrates the same concept, since the result will be true if "x" is non-zero. The

compare to zero is not actually needed and the result of the compare is true. The third and fourth

examples of this group are therefore identical.

*4.10 Additional Compare Concepts*
The third group of compares will introduce some additional concepts, namely the logical "AND"

and the logical "OR". We assign the value of 77 to the three integer variables simply to get

started again with some defined values. The first compare of the third group contains the new

control "&&", which is the logical "AND". The entire statement reads, if "x’ equals "y" AND

if "x" equal 77 then the result is "true". Since this is true, the variable z is set equal to 33.

The next compare in this group introduces the "||" operator which is the "OR". The statement

reads, if "x" is greater than "y" OR if "z" is greater than 12 then the result is true. Since "z" is

greater than 12, it doesn’t matter if "x" is greater than "y" or not, because only one of the two

conditions must be true for the result to be true. The result is true, so therefore "z" will be

assigned the value of 22.

*4.11 Logical Evaluation*
When a compound expression is evaluated, the evaluation proceeds from left to right and as

soon as the result of the outcome is assured, evaluation stops. Namely, in the case of an "AND"

evaluation, when one of the terms evaluates to "false", evaluation is discontinued because

additional true terms cannot make the result ever become "true". In the case of an "OR"

evaluation, if any of the terms is found to be "true", evaluation stops because it will be impossible

for additional terms to cause the result to be "false". In the case of additionally nested terms,

the above rules will be applied to each of the nested levels.

*4.12 Precedence Of Operators*
The question will come up concerning the precedence of operators. Which operators are

evaluated first and which last? There are many rules about this topic, which your compiler will

define completely, but I would suggest that you don’t worry about it at this point. Instead, use

lots of parentheses to group variables, constants, and operators in a way meaningful to you.

Parentheses always have the highest priority and will remove any question of which operations

will be done first in any particular statements.

Going on to the nextexample in group three, we find three simple variables used in the conditional

part of the compare. Since all three are non-zero, all three are "true", and therefore the "AND"

of the three variables are true, leading to the result being "true", and "z" being assigned the value

of 11. Note the since the variables, "r", "s", and "t" are "float" type variables, they could not be

used this way, but they could each be compared to zero and the same type of expression could

be used.

Continuing on to the fourth example of the third group we find three assignment statements in

the compare part of the "if" statement. If you understood the above discussion, you should have

no difficulty understanding that the three variables are assigned their respective new values, and

the result of all three are non-zero, leading to a resulting value of "TRUE".

*4.13 This Is A Trick, Be Careful*
The last example of the third group contains a bit of a trick, but since we have covered it above,

it is nothing new to you. Notice that the first part of the compare evaluates to "FALSE". The

remaining parts of the compare are not evaluated, because it is an "AND" and it will definitely

be resolved as a "FALSE" because the first term is false. If the program was dependent on the

value of "y" being set to 3 in the next part of the compare, it will fail because evaluation will

cease following the "FALSE" found in the first term. Likewise, "z" will not be set to 4, and the

variable "r" will not be changed.

*4.14 Potential Problem Areas*
The last group of compares illustrate three possibilities for getting into a bit of trouble. All three

have the common result that "z" will not get set to the desired value, but for different reasons.

In the case of the first one, the compare evaluates as "true", but the semicolon following the

second parentheses terminates the "if" clause, and the assignment statement involving "z" is

always executed as the next statement. The "if" therefore has no effect because of the misplaced

semicolon. The second statement is much more straight forward because "x" will always be

equal to itself, therefore the inequality will never be true, and the entire statement will never do

a thing, but is wasted effort. The last statement will always assign 0 to "x" and the compare

will therefore always be "false", never executing the conditional part of the "if" statement.

The conditional statement is extremely important and must be thoroughly understood to write

efficient C programs. If any part of this discussion is unclear in your mind, restudy it until you

are confident that you understand it thoroughly before proceeding onward.

*4.15 The Cryptic Part Of C*
There are three constructs used in C that make no sense at all when first encountered because

they are not intuitive, but they greatly increase the efficiency of the compiled code and are used

extensively by experienced C programmers. You should therefore be exposed to them and learn

to use them because they willappear in most, if not all, of the programs you see in the publications.

Load and examine the file named cryptic.c for examples of the three new constructs.

**main( )**

**{**

**int x = 0,y = 2,z = 1025;**

**float a = 0.0,b = 3.14159,c = -37.234;**

**/* incrementing */**

**x = x + 1; /* This increments x */**

**x++; /* This increments x */**

**++x; /* This increments x */**

**z = y++; /* z = 2, y = 3 */**

**z = ++y; /* z = 4, y = 4 */**

**/* decrementing */**

**y = y - 1; /* This decrements y */**

**y--; /* This decrements y */**

**--y; /* This decrements y */**

**y = 3;**

**z = y--; /* z = 3, y = 2 */**

**z = --y; /* z = 1, y = 1 */**

**/* arithmetic op */**

**a = a + 12; /* This adds 12 to a */**

**a += 12; /* This adds 12 more to a */**

**a *= 3.2; /* This multiplies a by 3.2 */**

**a -= b; /* This subtracts b from a */**

**a /= 10.0; /* This divides a by 10.0 */**

**/* conditional expression */**

**a = (b >= 3.0 ? 2.0 ; 10.5 ); /*This expression */**

**if (b >= 3.0) /* And this expression */**

**a = 2.0; /* are identical, both */**

**else /* will cause the same */**

**a = 10.5; /* result. */**

**c = (a > b?a:b); /* c will have the max of a or b */**

**c = (a > b?b:b); /* c will have the min of a or b */**

**}**

In this program, some variables are defined and initialized in the same statements for use below.

The first should come as no surprise to you. The next two statements also add one to the value

of "x", but it is not intuitive that this is what happens. It is simply be definition that this is true.

Therefore, by definition of the C language, a double plus sign either before or after a variable

increments that variable by 1. Additionally, if the plus signs are before the variable, the variable

is incremented before it is used, and if the plus signs are after the variable, the variable is used,

then incremented. In the next statement, the value of "y" is assigned to the variable "z", then

"y" is incremented because the plus signs are after the variable "y". In the last statement of the

incrementing group of example statements, the value of "y" is incremented then its value is

assigned to the variable "z".

The next group of statements illustrate decrementing a variable by one. The definition works

exactly the same way for decrementing as it does for incrementing. If the minus signs are before

the variable, the variable is decremented, then used, and if the minus signs are after the variable,

the variable is used, then decremented.

*4.16 The Cryptic Arithmetic Operator*
Another useful but cryptic operator is the arithmetic operator. This operator is used to modify

any variable by some constant value. The first statement of the "arithmetic operator" group of

statements simply adds 12 to the value of the variable "a". The second statement does the same,

but once again, it is not intuitive that they are the same. Any of the four basic functions of

arithmetic, "+", "-", "x", or "/", can be handled in this way, by putting the function desired in

front of the equal sign and eliminating the second reference to the variable name. It should be

noted that the expression on the right side of the arithmetic operator can be any valid expression,

the examples are kept simple for your introduction to this new operator.

Justlike the incrementing and decrementing operators, the arithmetic operator is used extensively

by experienced C programmers and it would pay you well to understand it.

*4.17 The Conditional Expression*
The conditional expression is just as cryptic as the last two, but once again it can be very useful

so it would pay you to understand it. It consists of three expressions within parentheses separated

by a question mark and a colon. The expression prior to the question mark is evaluated to

determine if it is not true, the expression following the colon is evaluated. The result of the

evaluation is used for the assignment. The final result is identical to that of an "if" statement

with an "else" clause. This is illustrated by the second example in this group. The conditional

expression has the added advantage of more compact code that will compile to fewer machine

instructions in the final program.

The final two lines of this example program are given to illustrate a very compact way to assign

the greater of two variables "a" or "b" to "c", and to assign the lessor of the same two variables

to "c". Notice how efficient the code is in these two example.

*4.18 To Be Cryptic Or Not To Be Cryptic*
Several students of C have stated that they didn’t like these three cryptic constructs and that

they would simply never use them. This would be fine if they never have to read anybody else’s

program, or use any other programs within their own. I have found many functions that I wished

to use within a program but needed a small modification to use it, requiring me to understand

another person’s code. It would therefore be to your advantage to learn these new constructs,

and use them. They will be used in the remainder of this tutorial, so you will be constantly

exposed to them.

This has been a long chapter but it contained important material to get you started is using C.

In the next chapter, we will go on to the building blocks of C, the functions. At that point, you

will have enough of the basic materials to allow you to begin writing meaningful programs.

*4.19 Programming Exercises*
1. Write a program that will count from 1 to 12 and print the count, and its square, for each

count.

1 1

2 4

3 9

etc..

2. Write a program that counts from 1 to 12 and prints the count and its inversion to 5 decimal

places for each count. This will require a floating point number.

1 1.00000

2 .50000

3 .33333

4 .25000

etc.

3. Write a program that will count from 1 to 100 and print only those values between 32 and

39, one to a line.

## No comments:

## Post a Comment