0

Other C Dynamic Memory Functions

The calloc function returns a memory area that is initialized to 0. There are two parameters available in the function:

  • The number of items required
  • The size of each required items

The format of the function is similar to malloc:

ptr = calloc(25, sizeof(int));

The only difference between malloc and calloc is that calloc will be initialized the memory area to 0, while malloc will not be initialized the specified memory area.

The realloc function modifies the memory size declared by malloc/calloc function. The format as follows:

ptr = realloc(ptr, newsize);

Note that the new/modified memory address created by realloc function is usually different from the original address.

The strdup function takes one string parameter and does the following to duplicate string:

  • Allocate a memory area large enough to load the string
  • Copy the string to a new memory

Below is the format of strdup function:

str2 = strdup(str1);

It’s the same as:

str2 = malloc(strlen(str1) + 1);
strcpy(str2, str1);

Note that str2 is a pointer to a character, and str1 is a pointer/array.

0

The C free Function

All memory allocated with malloc should be freed using free function. The usage looks like this:

ptr = malloc(100);
...
free(ptr);

As stated in the malloc post, the memory will be automatically freed at the end of the program execution. However, the system will run out of memory during the program execution if the unused memory was not freed. The program will also crash if the pointer which will be freed has not been used.

Here is the sample code for the free function:

/*
 *
 * free.c
 *
 * Program to demonstrate the use of the free library function
 *
 * by Mark Virtue, 2001.
 *
 */

#include <stdio.h>
#include <stdlib.h>

#define REQUIRED 3

int *allocate_the_memory() {
 int *ptr;

 ptr = malloc(REQUIRED * sizeof(int));
 if (ptr == NULL) {
 printf("malloc failedn");
 exit(1);
 }
 return ptr;
}

use_the_memory(int *integers) {
 int i;

 for (i = 0; i < REQUIRED; i++) {
 printf("Please enter number #%d: ", i + 1);
 scanf("%d", &integers[i]);
 }

 for (i = 0; i < REQUIRED; i++) {
 printf("Number #%d was %dn", i + 1, integers[i]);
 }
}

free_the_memory(int *ptr) {
 free(ptr);
}

main() {
 int *integers = allocate_the_memory();

 use_the_memory(integers);
 free_the_memory(integers);

 fflush(stdin);
 getchar();
}
1

The C malloc Function

The malloc function stands for memory allocate. It is a standard C library function and is used to get dynamic memory from the operating system.

Below shows how it works:

#include <stdlib.h>
int *ptr;
ptr = malloc(100);

The stdlib.h file contains function prototype for malloc and other dynamic memory functions. The number 100 inside the function means to get 100 bytes memory space. Note that the function will return a NULL value if the system is out of memory. It means that malloc cannot find enough memory size. In order to prevent this, the NULL value must be checked before using the function. Otherwise, the program will crash.

Here is the sample code for the malloc function:

/*
 *
 * malloc.c
 *
 * Program to demonstrate the use of the malloc library function
 *
 * by Mark Virtue, 2001.
 *
 */

#include <stdio.h>
#include <stdlib.h>

main() {
 int *integers;
 int required = 3;
 int i;

 integers = malloc(required * sizeof(int));
 if (integers == NULL) {     
  printf("malloc failedn");                   
  exit(1);
 }

 for (i = 0; i < required; i++) {
  printf("Please enter number #%d: ", i + 1);
  scanf("%d", &integers[i]);
 }

 for (i = 0; i < required; i++) {   
  printf("Number #%d was %dn", i + 1, integers[i]);
 }

 fflush(stdin);
 getchar();
}

Note that the above code contains sizeof(int) statement. It’s used to calculate the size of one integer which is 4 bytes. Also note that the pointers and the arrays can be interchangeable.

0

The C Dynamic Memory

Memory consists of:

  • Static Memory
  • Stack Memory
  • Dynamic Memory
  • Program Memory

Static memory contains all of the global and static variables created in the program. It is created when the program starts and initialized to 0 by default.

The variables in stack memory are created when a function/block which they are declared in is run. The value of these variable are not initialized, which means they contain random values by default.

Dynamic memory is allocated only when the program requested it. This type of memory should be assigned to a pointer and it’s not initialized by default. After the program finishes using a piece of dynamic memory, the programmer needs to clear this memory out during the execution of the program, otherwise, the OS will free all the dynamic memory at the end of the program.

And program memory is a memory copy of the object code of the program. It cannot have variables declared and cannot modify its content in this memory. If the memory was modified, the program will crash.

Dynamic memory is a method to obtain a piece of memory dynamically which the lifetime of this memory is defined by the programmer. The dynamic memory cannot be declared. Instead, this type of memory can be assign to a pointer. After the memory is allocated, it can be assigned to any type of data (int, float, struct, array, etc).

0

The C static Keyword

The static keyword can only be applied to the global variables and functions. For example,

static int x;
static int add(int a, int b)) {
 ...
}

Note that if the static keyword is applied, the scope of the variables/functions decreases from the entire project to the current source file.

If the static keyword is applied to a local variable, it has different effect. For example,

accumulate(int x) {
 static int total;
 total += x;
}

In the above example, the static is applied to the variable total. Therefore, the value of total will remain in the memory. This means that total will increase on each function call based on the statements inside the function instead of destroy the variable total when the function call ended. By adding static before a variable, the lifetime of the variable is changed to the lifetime of the global variable. However the visibility is not changed, it can only be accessed through the function/block where it is declared in.

As you can see above, the integer variable total was not initialized. The default variable value is 0 if the variable was not initialized.

Here is the sample code for the static variable/function:

/*
 *
 * static1.c
 *
 * The first of two files used to demonstrate the
 * concept of static variables and functions
 *
 * by Mark Virtue, 2001.
 *
 */

#include <stdio.h>

int count;

func1() {
 count = 1;
}

main() {
 func1();
 func2();

 printf("The value of count is %dn", count);

 fflush(stdin);
 getchar();
}
/*
 *
 * static2.c
 *
 * The second of two files used to demonstrate the concept
 * of static variables and functions
 *
 * by Mark Virtue, 2001.
 *
 */

static int count;

func2() {
 count = count + 1;
}

Note that to compile these two files together using gcc, use the following command:

gcc static1.c static2.c -o static

Here is another sample code:

/*
 *
 * static3.c
 *
 * Program to demonstrate the use of local static variable
 *
 * by Mark Virtue, 2001.
 *
 */

#include <stdio.h>

func() {
 static int called_already = 0;

 if (!called_already) {
 printf("This is the first (and hopefully only) time func is calledn");
 }
 called_already = 1;
}

main() {
 func();
 func();
 func();
 func();
 func();

 fflush(stdin);
 getchar();
}

The above code will only print the message one time despite of calling func() multiple times. That’s because the integer variable called_already was set to static.

0

The C Scope

Scope is used to describe the visibility and lifetime of a defined variable/function. Visibility of the variable/function is referring to the availability of the parts of the source code where the variable/function can be accessed. It means that the defined variable only can be accessed inside the function which defined the variable and can’t be accessed through other functions. Lifetime of the variable means that how long the variable will be declared while running the program. Note that functions don’t have lifetime.

There are three types of scope:

  • Variable Scope
  • Function Scope
  • Preprocessor Directive Scope

The following describes the variable scope. The variables can only be defined at the beginning of the block and only can be accessed within the block and its sub-blocks. The declared variables will be destroyed when the block is completed. The global variables scope is all blocks, meaning that the global variables can be accessed from all of the parts of the source code. Note that two or more variables with the same name can be declared inside different blocks. If two or more variables with the same name can be accessed inside a block, the closest one is used. For example, the local variable is used first then the global variable.

The following describes the function scope. All functions can be called from other functions, therefore all the functions are global functions.

The following describes the preprocessor directive scope. Most preprocessor directives don’t have scope, such as #include, #undef, and #ifdef…#endif, etc. However, the #define directive is in the scope between where the #define line is and the end of the source code. Any occurrences above the #define line cannot be accessed by the #define directive. If the #define lines are in the header file which is included in C file using #include directive, then the scope of the #define directive is between the #include line and the end of the source code.

Here is the sample code for scope:

/*
 *
 * scope.c
 *
 * Program to illustrate the concept of variable scope
 *
 * by Mark Virtue, 2001.
 *
 */

int a = 1; // Global Variable

func() {
 int b = 2; // Function-wide variable

 a = b;

 {
  // Begin an arbitrary block
  int c = 3; // block-wide variable

  a = b + c;
 }

 a = b;

 {
  // Begin another arbitrary block
  int d = 4; // this variable only accessible within this block

  a = b + d;
 }

 a = b;
}

main() {
 int e = 5;

 a = e;

 {
  // Begin an arbitrary block
  int f = 6;

  a = e + f;

 {
  // Begin an arbitrary sub-block
  int g = 7;

  a = e + f + g;
 }

 a = e + f;
 }

 a = e;
}

As you can see, the addition of the variables is according to the visibility of each variable.

Here is another sample code for the preprocessor directive scope:

/*
 *
 * scope2.c
 *
 * Program to demonstrate the concept of preprocessor directive scope
 *
 * by Mark Virtue, 2001.
 *
 */

func() {
 return MAX;
}

#define MAX 10

main() {
 int x = MAX;
}

Note the above code will not compile because the variable MAX in the func() function is not defined. As stated above, the #define directive only affects the source code below the #define line. It does not affect above the #define line. Thus the compiler would generate an error regarding the MAX returned variable.

0

The C Basic Pointers

Pointers are the most important and difficult part of C programming language. Most of the bugs and crashes in C programs are caused by pointers.

A pointer is a variable that contains a memory address instead of integers and characters. It often contains the memory address of another variable. For example, an integer variable “x” would corresponce to a pointer variable that contain the memory address of variable “x”.

The memory address of a variable is obtained by the & (and) operator. For example, &x. By using the * (asterisk) operator, the program can indirectly access a variable value through a pointer. It means that the content of a pointer is the variable value. For example, *pointer.

This operator (*) is also used to define a pointer. For example,

int *ptr;

Note that the pointers are declared as integers since memory addresses are formed by several integers.

Here are some interpretation on how to read the C code:

int x; // "x is an integer"
int *ptr; // "ptr is a pointer to an integer"
ptr = &x; // "set ptr to the memory address of x"
*ptr = 5; //"set the contents of ptr to 5"
            or "set the variable name that ptr points to to 5"

The third line is the pointer initialization. The resulting program would produce incorrect behavior if the pointer was declared but not initialized. An uninitialized pointer produces a random memory address rather than a random number for the uninitialized integer.

In the last line, *ptr represents x. It means to set the value of variable x to 5.

The pointers are used for:

  • modify the function parameters
  • pass of structures as function parameters
  • dynamic memory allocation
  • Here is the sample code for pointers:
/*
 *
 * pointer.c
 *
 * Program to demonstrate the correct use of pointers
 *
 * by Mark Virtue, 2001.
 *
 */

main() {
 int x;
 int *ptr;

 /*
 * Which of the following statements is a legal and meaningful
 * first step that this program could carry out?
 */

 *ptr = x; // LEGAL, but not meaningful - ptr is not initialized
 &ptr = x; // ILLEGAL - attempting to move ptr in memory
 ptr = &x; // LEGAL and MEANINGFUL - initialize ptr
 ptr = *x; // ILLEGAL and not meaningful - x is not a pointer and it can't point to anything

}

Here is another sample code:

/*
 *
 * pointer2.c
 *
 * Program to demonstrate the correct use of pointers
 *
 * by Mark Virtue, 2001.
 *
 */

#include <stdio.h>

main() {
 float f;
 float *ptr;

 // Assign the value of 3.5 to f without using a statement that begins with "f = "
 ptr = &f;
 *ptr = 3.5;

 printf("The value of f is %fn", f);
}

Here is another example:

/*
 *
 * pointer3.c
 *
 * Program to demonstrate the correct use of pointers
 *
 * by Mark Virtue, 2001.
 *
 */

#include <stdio.h>

main() {
 int x;
 int y;
 char *ptr;

 /*
 * Find out the current memory address of x and y.
 * Note: Do not need to use the pointer "ptr" to do this.
 * Hint: Memory addresses are 32 bit values, so are integers (probably)
 */
 printf("The memory address of x is %pn", &x);
 printf("The memory address of y is %pn", &y);

 /*
 * "ptr" is currently uninitialized
 * Find out the current random character it is pointing to
 * (and the address of this character)
 * Note: This could possibly crash the program
 */
 printf("The current random address in ptr is %pn", ptr);
 printf("The random character ptr is pointing to is %cn", *ptr);

 fflush(stdin);
 getchar();
}

As stated above, the memory addresses are formed by several integers. However, when %d (integer) is placed in the printf() statement, gcc always gave me warning stated that &x and &y, which are referred to as pointers, are “int *” data type. After some research, I concluded that %p is used for output pointers. Also, the random character outputted was unreadable during my compilation test.

One of the reasons that pointers were created is to modify the function parameters during the runtime. A function can’t modify a parameter unless one of the parameters is a pointer. Here is the sample code for using pointer as a function parameter:

/*
 *
 * double.c
 *
 * Program to demonstrate the use of
 * function parameters that are memory addresses
 *
 * by Mark Virtue, 2001.
 *
 */

#include <stdio.h>

double_it(int *n1) {
 *n1 = *n1 * 2;
}

main() {
 int num1;

 printf("Please enter the number: ");
 scanf("%d", &num1);

 double_it(&num1);

 printf("The doubled value is %dn", num1);

 fflush(stdin);
 getchar();

}

Second reason is to convert pointers to structures to make the development process much faster and use less memory. Convert pointers to structures is the same as convert pointers to normal variables. However, to access the fields of a pointer to a structure is different. For example:

struct employee *emp_p;
emp_p.age = 34;

The above lines cannot compile since emp_p is a pointer, not a structure. Below is the correct statements:

struct employee *emp_p;
emp_p->age = 34;

Note that the second line looks like the PHP OOP (Object Oriented Programming) syntax, but it actually is the shorthand version of

(*emp_p).age = 34;

Since there are two operators (* and .), the . (dot) operator comes first, therefore the pointer needs to convert to structure first.

Here is the sample code for the pointers to structures:

/*
 *
 * struct.c
 *
 * Program to demonstrate the use of pointers to structures
 *
 * by Mark Virtue, 2001.
 *
 */

#include <stdio.h>

struct employee {
 char name[31];
 char address[101];
 int age;
 float salary;
};

typedef struct employee emp;

emp read_emp(emp *e) {

 printf("Please enter the age: ");
 scanf("%d", &(e->age));
}

print_emp(emp *e) {
 printf("Age is %dn", e->age);
}

main() {
 emp emp1, emp2;

 read_emp(&emp1);
 emp2 = emp1;
 print_emp(&emp2);

 fflush(stdin);
 getchar();
}
0

The C Compilation Process

Layout of a C file

The layout of a C file from top to bottom consists of:

  1. #includes
  2. local #defines
    1. constants
    2. macros
  3. local type definitions
    1. structs
    2. typedefs
  4. global static variables
  5. global public variables
  6. local prototype (if necessary)
  7. Static functions
  8. Public functions
  9. main (if there is one)

Structure of a C Program

One C project is comprised of:

  • some C files
  • one main C file
  • different C libraries

The Compilation Process

Here are the steps involved during the compilation process:

  1. Start with several C files.
  2. Preprocessing phase: copy the C files to temp location and do the text substitution.
  3. Compiling phase: Compile the preprocessed temp fils into object files(.o). The object files are the machine code of the C source code.
  4. Linking phase: Link together the object files and compile into a single executable program.
0

US Government uses FOSS

US Department of DefenseThis page lists few of the companies/governments that use FOSS. One of which is the US Department of Defense. According t0 its profile, the reason for using FOSS is to defend software freedom. It reminds me that President Obama wanted to use open source software in the White House during the 2008 election.

0

The C typedef Keyword

The typedef keyword is often used with structures, but it’s also used with regular data types. It can create shorthand version of the variable (including structure) names. For example,

typedef struct employee emp;

For the above example, “emp” is the shorthand version of “struct employee”. Here is the comparison between shorthand version and original declaration:

emp        emp1;    // Shorthand version
struct employee emp1;    // Original

Here is the sample code for the typedef keyword:

/*
 *
 * struct3.c
 *
 * Program to demonstrate the use of typedefs
 *
 * by Mark Virtue, 2001.
 *
 */

#include <stdio.h>

struct employee {
 char name[31];
 char address[101];
 int age;
 float salary;
};

typedef struct employee emp;

emp read_emp() {
 emp e;

 printf("Please enter the age: ");
 scanf("%d", &e.age);

 return e;
};

print_emp(emp e) {
 printf("Age is %dn", e.age);
}

main() {
 emp emp1, emp2;

 emp1 = read_emp();
 emp2 = emp1;
 print_emp(emp2);

 fflush(stdin);
 getchar();
}

As stated above, the typedef keyword can be used with other data types, not just with structures.

Pages ... 1 2 3