Home Other Languages C Basic C Questions - 5

Login Form




Basic C Questions - 5 Print E-mail

1. How do you use a pointer to a function?

The hardest part about using a pointer-to-function is declaring it.

Consider an example. You want to create a pointer, pf, that points to the strcmp() function.
The strcmp() function is declared in this way:
int strcmp(const char *, const char * )

To set up pf to point to the strcmp() function, you want a declaration that looks just like the strcmp() function’s declaration, but that has *pf rather than strcmp:
int (*pf)( const char *, const char * );

After you’ve gotten the declaration of pf, you can #include and assign the address of strcmp() to pf: pf = strcmp;

 

2. Can math operations be performed on a void pointer?

No. Pointer addition and subtraction are based on advancing the pointer by a number of elements. By definition, if you have a void pointer, you don’t know what it’s pointing to, so you don’t know the size of what it’s pointing to. If you want pointer arithmetic to work on raw addresses, use character pointers.

 

3. What is the difference between a string and an array?

An array is an array of anything. A string is a specific kind of an array with a well-known convention to determine its length.

There are two kinds of programming languages: those in which a string is just an array of characters, and those in which it’s a special type. In C, a string is just an array of characters (type char), with one wrinkle: a C string always ends with a NUL character. The “value” of an array is the same as the address of (or a pointer to) the first element; so, frequently, a C string and a pointer to char are used to mean the same thing.

An array can be any length. If it’s passed to a function, there’s no way the function can tell how long the array is supposed to be, unless some convention is used. The convention for strings is NUL termination; the last character is an ASCII NUL (‘’) character.

 

4. Sample Code
struct customer *ptr = malloc( sizeof( struct customer ) );

Given the sample allocation for the pointer "ptr" found above, which one of the following statements is used to reallocate ptr to be an array of 10 elements?

  •  ptr = realloc( ptr, 10 * sizeof( struct customer ) );
  •  realloc( ptr, 10 * sizeof( struct customer ) );
  •  realloc( ptr, 9 * sizeof( struct customer ) );
  •  ptr += malloc( 9 * sizeof( struct customer ) );
  •  ptr = realloc( ptr, 9 * sizeof( struct customer ) );

 

5. 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).


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.

 

6. Which one of the following correctly declares a pointer to an array of 12 characters?

  •  char (* a) [12];
  •  char (* a) [11];
  •  char * a [11];
  •  char * (a [12]);
  •  char * (a [11]);

 

7. When should a type cast be used?

There are two situations in which to use a type cast. The first use is to change the type of an operand to an arithmetic operation so that the operation will be performed properly.

The second case is to cast pointer types to and from void * in order to interface with functions that expect or return void pointers. For example, the following line type casts the return value of the call to malloc() to be a pointer to a foo structure.
struct foo *p = (struct foo *) malloc(sizeof(struct foo));

 

8. Sample Code
#include
int main(void) {
{int i=10; goto lbl;}
{int i=20; {int i=30; lbl:;}
printf("%i", ++i);}
}

Refer to the above sample code. What does this program print?

  •  10
  •  11
  •  21
  •  31
  •  An undefinedvalue

 

9. Which one of the following describes a C character string?

  •  A sequence of char objects in EBCDIC format
  •  A sequence of printable ASCII characters
  •  Any pointer to type char
  •  An array of bytes terminated by NUL
  •  A sequence of char objects in ASCII format

 

10. What is an lvalue?

An lvalue is an expression to which a value can be assigned. The lvalue expression is located on the left side of an assignment statement, whereas an rvalue is located on the right side of an assignment statement. Each assignment statement must have an lvalue and an rvalue. The lvalue expression must reference a storable variable in memory. It cannot be a constant.