Some basics

July 25, 2006

Learned and refreshed many interesting things:

  • int a(2); can be used to initialize the variable a to 2, just like int a = 2;
  • A String is not a fundamental data type in C++, but a part of the standard C++ library. We have to include <string> to use this class.
  • This is how we create a string consisting of wide chars. string s = L”Hello”;
  • In C++ we can do typecasting using a functional notation, so that int i =(int)f; is the same as int i = int(f); I think this is possible because C++ contains functions like int, float, etc, that are overloaded with the appropriate types and return an int, float, respectively. Must verify this fact. Will this work with user defined types as well?
  • cout does not add a newline by default. We must add it explicitly by using “\n” or the constant endl. endl will also flush the stream, however since cout because it is not buffered, we can use them interchangeably.
  • In the following line of code int i; cin >> i; cin will process bytes from the input stream based on what we expect from the stream. In this case it will process 4 bytes and store the int value in the variable i. cin will not process the input stream unless we explicitly “RETURN”. The code cin >> a >> b; will process 2 values entered by the user. These values must be seperated by a space, tab, or a newline character.
  • cin does not verify the values entered. It also has problems with accepting strings with a space in them, since it will treat multiple words as seperate data values. To resolve these issues we use the function getline(cin, variableName); to accept a line of input from the user into a string. We then use the string as a stream and extract the data we need, using stringstream(str) >> variable;

Things that I am bit embarrased to include, but will include them anyways 🙂

  • Any character can be written with a \ followed by it’s ACII code. char c = \97;
  • #define does not need a ; at the end of the statement. It is optional.
  • int i += 3; The operator that would otherwise have been after the = and between the operators is now before the = sign. I wonder why.
  • A string consists of const char*.

Learning C++

July 25, 2006

Now that the basics (C programming) are covered, I will move on to C++.

The study plan is to read the basic online tutorial at http://www.cplusplus.com/doc/tutorial/ and then follow up with Bruce Eckel’s “Thinking in C++”. I might complement it with ACM’s online C++ course.


Thinking in C: Chapt 8b – Pointers 102

July 24, 2006

This was a nice advanced chapter. I remembered as well as learned many things.

Some basic stuff:

When a signed number is bit shifted right, the sign bit is propogated.

typedef declares synonyms. For eg:

typedef struct Student Student;

says that Student is a synonym for struct Student.

We can have nested pointers, such as pointers to pointers and pointers to pointers to pointers… uptil 12 levels. However 2 levels is what is practically used.

When sizeof is applied to a pointer to an array, the value it returns is the size of the array. An interesting idiom to find out the number of elements in an array is:

int a[10];

int num_ele = sizeof a/sizeof a[0];

Generic Pointers:

Void pointers are generic pointers. They are used when we do not know what type of pointer to accept or send. In C any pointer type can be assigned to void and the other way round.

Constant Pointers:

Pointers can be constant, which means that the pointer cannot point to another location, and the pointer’s referent can also be constant, which means that the value held in the location pointed by the pointer cannot be changed. Here is how we use them.

int* const i; Here i is a constant pointer. The value of the referent can be changed, but i cannot be changed.

const int* i; Here the referent is constant. The value of the pointer can be changed but the value of what it is pointing to cannot be changed.

Pointer Arithmatic:

When doing pointer arithmatic, when we add to or subtract from a pointer, the pointer is incremented or decremented by the number of elements and not the number of bytes. For eg:

int a[10];

a is a pointer to the begining of the array of integers. a++, a will not point to the next address, but to the next int in the array. So if an int is 4 bytes on your machine, a will be incremented by 4 bytes.

Similarly subtracting 2 pointers yeilds the number of elements between them. It follows that we cannot do arithmatic with pointers of different types.

Function pointers:

We can also have pointers to functions. Here is how we can get a pointer to printf.

int (*fp) (const char*,…) = printf;

This means that fp is a pointer to a function called printf which takes a const char* and an unknown number of parameters after that.

Incomplete types:

Incomplete types are used when we do not have the information in advance or we want to hide it from clients.

They are used with arrays and structures. For eg:

extern int a[]; Struct Employee;

Further Research

  • What happens when a signed number is bit shifted left? Is the sign bit maintained, or is it shifted out?
  • What happens when we have pointers of two different types and we cast them into void pointers to do arithmatic with them?
  • When a variable is declared extern, does the compiler try to verify it?

Thinking in C: Chapt 7 – Pointers 101

July 21, 2006

This was a very interesting chapter. I had forgotten some basic concepts related to pointers and it was nice to refresh them.

Pointers are used to support reference semantics in C. When we pass an array to a function in C, we are in reality passing a pointer to it. Arrays CANNOT be passed by value in C.

Pointers allow us to create dynamic objects whose size we do not know at compile time. Dynamic objects are created with malloc or calloc, and live on the heap. When an object is no longer needed, it’s memory must be returned to the heap by using ‘free’. Another function that C gives us is realloc() which updates the size of memory alloctaed using malloc. We might want to use the sizeof operator when allocating memory. To use these functions be sure to include <stdlib.h>

C has a NULL pointer which does not point to any valid memory location. Since it does not point to a valid memory location, it cannot be dereferenced. A NULL pointer is usually used for comparisons, with pointers returned from a method (where a NULL pointer denotes an error).

C supports two operators for working with pointers to structs. The . operator and the -> operator. When we use the -> operator, we do not need to dereference the pointer to struct.

An interesting note: Most operating systems will free memory used by a program when it exits, however it is usually a good idea to explicitly free memory because if our program takes huge amounts of memory then it might exhaust all the memory available on the system.

Did the assignment. Learned something interesting. If I have a structure Employee

struct Employee {

char name[16] ;

}

struct Employee emp = malloc(sizeof(struct Employee));

emp->name = someCharPointer; //does not compile

strcpy(emp->name, someCharPointer); //works just fine

Why does the first line not work? I think it is because name is initialized as an array of 16 chars, while someCharPointer is also a char pointer, but we do not know it’s size. I think the compiler senses that things could go wrong and disallows the assignment.

Research:

  • Does realloc work if the memory was allocated using calloc()?

Chapt 6 – Thinking in C: Programming with functions

July 21, 2006

A function must be either declared or defined before it’s use. To declare a function we need to specify the function prototype like this:

float avg(int, int);

A void is used to signify no parameters. If a function sayHello() takes no parameters, it can be defined like this:
void sayHello(void) {}
or like this
void sayHello() {}
In this case we may pass parameters to the function, but they will be ignored by the compiler as well as the runtime.

This section goes beyond functions and also mentions different variable types:

  • local variables are those that are declared in methods. They exist on the stack.
  • constant variables declared at the file level, reside in the data segment, and cannot be accessed from other files
  • variables declared at the file level also reside on the data segment, but can be accessed from other files

Research:

  • What is the data segment?

Thinking in C – Chapt 5: Compound data types

July 10, 2006

This chapter was a good refresher on structures in C. Anyways a little introduction to compound data types in C.There are three types of compund data types in C: array,strings, and structures. Strings are just a special type of character array where the last element is a null character.

We can read as well as write data incore instead of the regular console by using sscanf and sprintf.

eg: sscanf(str, “%d %f”, &num, &flo); In this example the data will be read from the buffer reffered to by “str” and not standard input.

eg: sprintf(str, “%d %f”, num, flo); In this example the data will be written to a buffer reffered to by “str” instead of standard output.

A structure is a data type that consists of primitive as well as other compund (including structures) data types. For eg: this is how we will represent an Employee record using structures.

Exercise: Make an Employee structure which will contain last_name, first_name, title, and salary. Accept details from the user and populate an array of Employees till the user submits “enter” for the last_name. The program then prints the list of employees.

Did the exercise.

When the program accepts a decimal, the newline that the user presses to submit the number lingers in the input stream and must be flushed or eaten. Otherwise it will be accepted in the next scanf.

Further Research:

  • What happens if the number of characters we enter are more than what the character array accepts.
  • What is the difference between gets() and scanf().

Thinking in C – Chapt 4: Controlling Program Flow

July 10, 2006

An interesting thing I learned here, is that way back in the sixties some scientists had proved that an alogorithm can be expressed using a :

  • Sequence of statements
  • Decision making constructs
  • Looping constructs
  • An arbitrary number of boolean flags

That was interesting…

A case statement can be used only with integers.

A scan with leading spaces before %c will ignore any number of whitespaces. If we do not include the space, then a space entered by mistake by the user will be read by scanf, ignoring the actual character value the user might have entered.

eg: scanf(” %c”, &c); //note the whitespace before %c

Chuck says that we should not declare variables within a switch clause. He did not explain the reason. Perhaps it is complicated and beyond the scope of this tutorial.

Excercise: Did the exercise. It was similar to the one in chapt 3, except that this time the user could enter an arbitrary number of integers (0 for quit).

Further Research:

  • Why should we not declare variables inside a swicth clause?