Chapter P2. The C Language

Goals for this chapter:
  • sh (bash)
  • make (make)
  • cpp (cpp)
  • gcc (cc)
  • gcc-c++ (g++)
  • strip (binutils)
  • touch (fileutils)
  • glibc (ldconfig)
DThose type are not "abstract";
they are as read as int and float
-Doug McIlroy.

 
 

Data types

The C language offers different types of data: int for integers, double and float for real numbers and char for characters.

For example, the following declaration

    int i,j;
    char str[24];
    float degc, degf;

are valid C data declaration.

For integers C offers differents containers of data

long pencil;

short pen;

The difference between these types

The previous definitions are variable. To set constants there are two modes:


While define are const are equivalent for non-strings definitions, only the using const is possible to define constants.

We note in the previous example that define may works like functions. We also note the Operator "? :"

This operator is equivalent to a if-then-else statement.

Suppose that you write

(A> B) ? C : D

This is equivalent to the following code:

if (A > B) {
    C
} else {
    D
}

For example is usefull also in return.

For example return (a>0) ? a ? b;

Now, we will resume all this data in a simgle program, printing regular data, maximum and minimum values for each variable. The limits of the C are listed in the include file, <limits.h> .

In C is also possible to use the enum, for example

enum colors {Green, Red, Yellow }

enum days { MON = 1, TUE, WED, THU, FRI, SAT, SUN }

Of course, TUE will be 2, WED will be 3, etc.

Other more complex enum definitions are:

enum { XmSTRING_DIRECTION_L_TO_R,
       XmSTRING_DIRECTION_R_TO_L,
       XmSTRING_DIRECTION_UNSET = 3,
       XmSTRING_DIRECTION_DEFAULT = XmDEFAULT_DIRECTION
       };

Of course, is possible to built its own types using structures and unions, See the section: Structures in this chapter.

Some examples are:

typedef enum{ XmFONT_IS_FONT, XmFONT_IS_FONTSET
              } XmFontType;

typedef unsigned char   XmStringDirection;
typedef union __XmStringRec     *XmString;              /* opaque to outside */
typedef XmString *      XmStringTable;          /* opaque to outside */
typedef char *          XmStringCharSet;        /* Null term string */
typedef char *          XmStringTag;            /* Null term string */
typedef unsigned char   XmStringComponentType;  /* component tags */
 

Formatting data

C offers the possibility to print data in formated mode.
 
 
Printf Argument Description
%d %i Print a decimal number
%6d Print a decimal number with up to 6 digits
%f Print a float
%.4f Print a float with 4 decimals
%6.4f Prints a float 6 digit float and 4 decimals
%u Prints int without sign
%o Prints octal numbers
%x, %X Prints hexadecimal
%c Prints a character
%s Prints a string
%20s Prints a string 20 characters long
%-20s Prints a string 20 characters long alignment to left.

In C are also used the following C escape sequence:

ASCII Name               Description                             C Escape Sequence
 nul                      null byte                                     \0
 bel                      bell character                                \a
 bs                       backspace                                     \b
 ht                       horizontal tab                                \t
 np                       formfeed                                      \f
 nl                       newline                                       \n
 cr                       carriage return                               \r

In the section C Operators we will offer a complete introduction to these operators, however now we will introduce the cycle for, to print sin and cos, from 0 until 64 degree.

My first serious project when I enter in UCV (Caracas - Venezuela), in 1980, was to use the faculty computer a Burroghs system which covers a big surface (about 4 normal rooms), to print a similar table.

Starting from this table and using the sin (64) and the formulae for six(x/2), I offers a proof that is possible to built the same table with a simple desk calculator, with four five operations: '+', '-', 'x', '/' and 'sqrt'. In Chapter 1, I introduce an algorithm to get the cubic root from the squared root.

#include <math.h>

main ()
{
        int i;

        for (i=0; i <= 64; i++) {
            printf ("%d   %.4f    %.4f\n", i, sin(i), cos(i));
        }
}

Because we use a function sin(x) that belong to the mathematical library we need to add it to the compilation line.

[root@ftosx1 Chap2]# cc sin64.c -o sin64 -lm

Then, we will have the table

[root@ftosx1 Chap2]# ./sin64
0   0.0000    1.0000
1   0.8415    0.5403
2   0.9093    -0.4161
3   0.1411    -0.9900
4   -0.7568    -0.6536
...

In C is also possible to align strings to right or left.

[root@ftosx1 Chap2]# more align.c

main()

{
        char ruler [] = "012345678901234567890123456789";
        char str1 [] = "Brian Kernimgham";
        char str2 [] = "C is cool language";
 

        printf ("%s\n", ruler);
        printf ("%20s\n", str1);
        printf ("%-20s\n", str2);
}
[root@ftosx1 Chap2]#

Vectors and Pointers

There are also other importants data objects like array of characters and pointers.

char * string;
char string[];

The first declaration is a pointer to char, while the second is a vector of char.

We can define for example:

char mystr[] = "Hello!"

We don't need to alloc memory for this because this happens automatically.

A simple C source explains this:

[root@ftosx1 Chap2]# more array.c
main()
{
        char mystr[] = "Hello!";

        puts (mystr);

        printf ("%c %c\n", mystr[0], mystr[3]);
}

[root@ftosx1 Chap2]# make array
[root@ftosx1 Chap2]# ./array
Hello!
H l
[root@ftosx1 Chap2]#

The Pointer is a variable that contains the address of another variable. Now, we will write two simple examples that generate correct situation that can create bad situations and also clear bad situations.

We can use also the pointer concept like we did in the previous example.

[root@ftosx1 Chap2]# more array2.c

main()
{
        char * mystr = "Hello!";

        puts (mystr);

        printf ("%c %c\n", mystr[0], mystr[3]);

}
[root@ftosx1 Chap2]#

If we don't change the pointer, everything works!

[root@ftosx1 Chap2]# make array2
cc     array2.c   -o array2
[root@ftosx1 Chap2]# ./array2
Hello!
H l
[root@ftosx1 Chap2]#

But, if we change the pointer "everything" (for an indefinite situation) may happens.

[root@ftosx1 Chap2]# more array3.c

main()
{
        char * mystr = "Hello!";

        puts (mystr);

        printf ("%c %c\n", mystr[0], mystr[3]);

        strcpy (mystr, "We change now!");

        printf ("%c %c\n", mystr[0], mystr[3]);

}
[root@ftosx1 Chap2]# make array3
cc     array3.c   -o array3
[root@ftosx1 Chap2]# ./array3
Hello!
H l
Segmentation fault
[root@ftosx1 Chap2]#
 

The previous segmentation fault happens because we try to use an unallocated memory position.

Now, we will illustrate better this problems generating a segmentation fault!

[root@ftosx1 Chap2]# more array4.c

main()
{
        // Allocated variable;
        char mystr[14];

        strcpy (mystr, "We change now!");
        puts (mystr);

        printf ("%c %c\n", mystr[0], mystr[3]);
 

        strcpy (mystr, "We change now with a very very long string!");
        puts (mystr);

}
[root@ftosx1 Chap2]#

[root@ftosx1 Chap2]# make array4
cc     array4.c   -o array4
[root@ftosx1 Chap2]# ./array4
We change now!
W c
We change now with a very very long string!
Segmentation fault
[root@ftosx1 Chap2]#

Therefore is clear that when we use pointers, pointers must point to allocated variable with the sufficient ammount of memory.

Now, we will cover an example using point to integers, and using pointers to print the information where the pointer points.

[root@ftosx1 Chap2]# more array5.c

main()
{
        // Allocated variable;
        int a[10];

        a[0] = 0;
        a[1] = 1;
        a[2] = 2;
        a[3] = 3;
        a[4] = 4;
        a[5] = 5;
        a[6] = 6;
        a[7] = 7;
        a[8] = 8;
        a[9] = 9;

        printf ("%d, %d, %d\n", a[0], a[1], a[9]);
}
[root@ftosx1 Chap2]#

Therefore, a is a simple vector where each position includes an integer that represent its position.

Now, we use a point and print the information that this pointer points!

[root@ftosx1 Chap2]# more array6.c

main()
{
        // Allocated variable;
        int a[10];
        int *pa;

        a[0] = 0;
        a[1] = 1;
        a[2] = 2;
        a[3] = 3;
        a[4] = 4;
        a[5] = 5;
        a[6] = 6;
        a[7] = 7;
        a[8] = 8;
        a[9] = 9;

        // Now 'pa' points to the element 0 of the array a.
        pa = &a[0];

        // ... and we print its contents
        printf ("%d\n", *pa);
 

        // Now 'pa' points to the element 0 of the array a.
        pa = &a[4];

        // ... and we print its contents
        printf ("%d\n", *pa);
 

}

[root@ftosx1 Chap2]# make array6
cc     array6.c   -o array6
[root@ftosx1 Chap2]# ./array6
0
4
[root@ftosx1 Chap2]#

The line

pa = &a[0];

is equivalent to:

pa = a;

because a is equivalent to &a[0].

We can also prints the next position where points the pointer and also the n-position, where n must be a valid position.

We clean the previous example and transform it a more classical code.

[root@ftosx1 Chap2]# more array7.c

main()
{
        // Allocated variable;
        int a[10], i;
        int *pa;

        for (i=0; i<=9; i++)
                a[i] = i;

        // Now 'pa' points to the element 0 of the array a.
        pa = a;

        // ... and we print its contents
        printf ("%d\n", *pa+6);
 

}
[root@ftosx1 Chap2]#

[root@ftosx1 Chap2]# make array7
cc     array7.c   -o array7
[root@ftosx1 Chap2]# ./array7
6

The next step on Pointers is a vector of pointers:

We can also  create a vector of Pointers, for example the declaration:

static char * myweek [] = { "Linux", "StarOffice", "KDE", "Java", "PHP", "Netscape", "Number Theory", "Relativity" };

create an array of six pointers.

These pointers automically allocated from the previous declaration.

[root@ftosx1 Chap2]# more vector_pointer.c

main(int argc, char ** argv[])
{
        int i;

        static char * myweek [] = {"Linux", "StarOffice", "KDE", "Java", "PHP", "Number Theory", "Relativity" };
 

        for (i = 0; i <= 6; i++) {
                printf ("%s\n", myweek[i]);
        }
        return 0;
}
[root@ftosx1 Chap2]#

[root@ftosx1 Chap2]# make vector_pointer
cc     vector_pointer.c   -o vector_pointer
[root@ftosx1 Chap2]# ./vector_pointer
Linux
StarOffice
KDE
Java
PHP
Number Theory
Relativity
[root@ftosx1 Chap2]#
 

Pointers may be passed as functions parameters, pointers may be entire structures and are used anywhere. This argument is covered in C Functions

Structures, union and typedef

In C programing for X11, or Motif (See X Windows Course), or Networking programming covered in this course we can find real structures declaration as follows:

struct arphdr
  {
    unsigned short int ar_hrd;          /* Format of hardware address.  */
    unsigned short int ar_pro;          /* Format of protocol address.  */
    unsigned char ar_hln;               /* Length of hardware address.  */
    unsigned char ar_pln;               /* Length of protocol address.  */
    unsigned short int ar_op;           /* ARP opcode (command).  */
#if 0
    /* Ethernet looks like this : This bit is variable sized
       however...  */
    unsigned char __ar_sha[ETH_ALEN];   /* Sender hardware address.  */
    unsigned char __ar_sip[4];          /* Sender IP address.  */
    unsigned char __ar_tha[ETH_ALEN];   /* Target hardware address.  */
    unsigned char __ar_tip[4];          /* Target IP address.  */
#endif
  };
 

In X11.h we can find:
 

typedef union _XEvent {
        int type;               /* must not be changed; first element */
        XAnyEvent xany;
        XKeyEvent xkey;
        XButtonEvent xbutton;
        XMotionEvent xmotion;
        XCrossingEvent xcrossing;
        XFocusChangeEvent xfocus;
        XExposeEvent xexpose;
        XGraphicsExposeEvent xgraphicsexpose;
        XNoExposeEvent xnoexpose;
        XVisibilityEvent xvisibility;
        XCreateWindowEvent xcreatewindow;
        XDestroyWindowEvent xdestroywindow;
        XUnmapEvent xunmap;
        XMapEvent xmap;
        XMapRequestEvent xmaprequest;
        XReparentEvent xreparent;
        XConfigureEvent xconfigure;
        XGravityEvent xgravity;
        XResizeRequestEvent xresizerequest;
        XConfigureRequestEvent xconfigurerequest;
        XCirculateEvent xcirculate;
        XCirculateRequestEvent xcirculaterequest;
        XPropertyEvent xproperty;
        XSelectionClearEvent xselectionclear;
        XSelectionRequestEvent xselectionrequest;
        XSelectionEvent xselection;
        XColormapEvent xcolormap;
        XClientMessageEvent xclient;
        XMappingEvent xmapping;
        XErrorEvent xerror;
        XKeymapEvent xkeymap;
        long pad[24];
} XEvent;
 

In Xm.h we can find:
 

typedef struct
{
    int     reason;
    XEvent  *event;
} XmAnyCallbackStruct;

Note how structures may includes others that may be installed or not. Generally very few systems install Motif today (RedHat continues to use LessTif a Motif clone). FTOSX install OpenMotif, the original.

Now, we present an example about how we can setup our own typedefs.

Suppose that you want write a program to list your friends at college:

C offers structures and union for this kind of data, however C offers also the typedef to create our own types.

[root@ftosx1 Chap2]# more structures.c

typedef struct _student {
        char name[20];
        char address [50];
        int  id;
        int  age;
        char sex;
} student;
 

main ()
{
        student john;

        strcpy(john.name, "John Smith");
        strcpy(john.address, "1620 26th Street - Santa Monica");
        john.id = 42571;
        john.age = 18;
        john.sex = 'M';

        printf ("The data request is the following:\n\t%s\n\t%s\n\t%d\n\t%d\n\t%c\n", john.name, john.address, john.id, john.age, john.sex);

}
[root@ftosx1 Chap2]#

[root@ftosx1 Chap2]# make structures
cc     structures.c   -o structures
[root@ftosx1 Chap2]# ./structures
The data request is the following:
        John Smith
        1620 26th Street - Santa Monica
        42571
        18
        M
[root@ftosx1 Chap2]#

A union is similar to a structure but only one of its member is in use.

For example, we can define:

union {
    /* prime number */
    short is_prime;

    /* composite */
    short is_not_prime;

} is_prime

or for example:

union {
           char single_name[40];
           char marital_lastname[40];
           char complete_divorcedname[60];
} marital_info;

Yo access members we use the classic mode: marital_info.single_name
 

Conversion between types

Any data type is a set of bits. Therefore a number may be a string and a string may be a number.

These conversions are possible. For example we can covert a string (like "3098" to its relative integer 3098, a number).
 

main ()
{
        char string [] = "3098";
        int myint;

        printf ("%d\n", myint = atoi(string));

        printf ("like a test %d\n", myint + 1);
}

[root@ftosx1 Chap2]# make atoi
cc     atoi.c   -o atoi
[root@ftosx1 Chap2]# ./atoi
3098
like a test 3099

The same is valid for double or float

[root@ftosx1 Chap2]# more strtod.c

#include <stdlib.h>

main ()
{
        char string [] = "-3.141516098";
        double mydouble;

        printf ("%f\n", mydouble = strtod(string, NULL));

        printf ("like a test %f\n", mydouble + 1);
}ec
[root@ftosx1 Chap2]#
 
 

[root@ftosx1 Chap2]# make strtod
cc     strtod.c   -o strtod
[root@ftosx1 Chap2]# ./strtod
-3.141516
like a test -2.141516
[root@ftosx1 Chap2]#

Is possible make also reverse operations, for example a number that become a string, but this is inmmediate.

[root@ftosx1 Chap2]# more number2string.c
#include <stdio.h>
main()
{
        double mydouble = 3.141516;
        char  mystr[14];
 
 

        sprintf (mystr, "%f\n", mydouble);

        printf ("%s and its fifth character is: %c\n", mystr, mystr[4]);

}
[root@ftosx1 Chap2]#

[root@ftosx1 Chap2]# make number2string
cc     number2string.c   -o number2string
[root@ftosx1 Chap2]# ./number2string
3.141516
 and its fifth character is: 1
[root@ftosx1 Chap2]#
 

Of course an analog conversion may be made from any type to any string.

Generally the reciprocal fprintf functions are the scanf function, used to join in a single string, different types.

This is normally the mode things works.


Press the button to go to the next section.