Ans. Pointers are used to manipulate data using the address. Pointers use * operator to
access the data pointed to by them
Arrays use subscripted variables to access and manipulate data. Array variables can be
Equivalently written using pointer expression.
Q) Are pointers integers
Ans pointers are not integers. A pointer is an address. It is merely a positive number and not an integer.
Q. How are pointer variables initialised?
Ans Pointer variable are initialized by one of the following two ways
Static memory allocation
Dynamic memory allocation
Q. What are the advantages of the debugging?
Ans Debugging is easier
It is easier to understand the logic involved in the program
Testing is easier
Recursive call is possible
Irrelevant details in the user point of view are hidden in functions
Functions are helpful in generalizing the Program
Q) What is a pointer value and Address ?
Ans A pointer value is a data object that refers to a memory location. Each memory location is numbered in the memory. The number attached to a memory location is called the address of the location.
Q) What is a pointer variable?
Ans A pointer variable is a variable that may contain the address of another variable or any valid address in the memory.
Question What is static memory allocation and dynamic memory allocation?
Ans Static memory allocation: The compiler allocates the required memory space for a declared variable. By using the address of operator, the reserved address is obtained and
this address may be assigned to a pointer variable. Since most of the declared variable
have static memory, this way of assigning pointer value to a pointer variable is known as static memory allocation. Memory is assigned during compilation time.
Dynamic memory allocation: It uses functions such as malloc( ) or calloc( ) to get memory dynamically. If these functions are used to get memory dynamically and the values returned by these functions are assigned to pointer variables, such assignments are known as dynamic memory allocation. Memory is assigned during run time.
Q) What is the purpose of main( )
Ans The function main( ) invokes other functions within it. It is the first function to
be called when the program starts execution.
It is the starting function
It returns an int value to the environment that called the program
Recursive call is allowed for main( ) also.
It is a user-defined function
Program execution ends when the closing brace of the function main( ) is reached.
It has two arguments 1)argument count and 2) argument vector (represents strings passed).
Any user-defined name can also be used as parameters for main( ) instead of argc and argv
Q. What is the purpose of realloc( )?
Ans The function realloc(ptr,n) uses two arguments. the first argument ptr is a pointer to a block of memory for which the size is to be altered. The second argument n specifies the new size. The size may be increased or decreased. If n is greater than the old size and
if sufficient space is not available subsequent to the old region, the function realloc( )
may create a new region and all the old data are moved to the new region.
What is an argument? Differentiate between formal arguments and actual arguments Ans An argument is an entity used to pass the data from calling funtion to the called funtion. Formal arguments are the arguments available in
Q. Differentiate between an internal static and external static variable?
Ans An internal static variable is declared inside a block with static storage class whereas an external static variable is declared outside all the blocks in a file. An internal static variable has persistent storage, block scope and no linkage. An external static variable has permanent storage, file scope and internal linkage. the function definition. They are preceded by their own data types. Actual arguments are available in the function call.
Q. What are advantages and disadvantages of external storage class?
Ans Advantages of external storage class
1)Persistent storage of a variable retains the latest value
2)The value is globally available
Disadvantages of external storage class
1)The storage for an external variable exists even when the variable is not needed
2)The side effect may produce surprising output
Q. What are the characteristics of arrays in C?
Ans1) An array holds elements that have the same data type
2) Array elements are stored in subsequent memory locations
3) Two-dimensional array elements are stored row by row in subsequent memory locations.
4) Array name represents the address of the starting element
5) Array size should be mentioned in the declaration. Array size must be a constant
expression and not a variable.
Q. Differentiate between a linker and linkage?
Ans A linker converts an object code into an executable code by linking together the necessary build in functions. The form and place of declaration where the variable is declared in a program determine the linkage of variable
Q. When does the compiler not implicitly generate the address of the first element of an array?
Ans Whenever an array name appears in an expression such as
array as an operand of the sizeof operator
array as an operand of & operator
Q Is it better to use a pointer to navigate an array of values, or is it better to
use a subscripted array name?
Ans It’s easier for a C compiler to generate good code for pointers than for subscripts.
array as a string literal initializer for a character array Then the compiler does not implicitly generate the address of the address of the first element of an array.
Q .why n++ executes faster than n+1?
Ans The expression n++ requires a single machine instruction such as INR to carry out the increment operation whereas, n+1 requires more
Q. Is it possible to execute code even after the program exits the main()
function?
Ans The standard C library provides a function named atexit() that can be used to perform “cleanup” operations when your program terminates. You can set up a set of functions you want to perform automatically when your program exits by passing function pointers to the at exit() function.
Q. What is a static function?
Ans A static function is a function whose scope is limited to the current source file.
Scope refers to the visibility of a function or variable. If the function or variable is visible
outside of the current source file, it is said to have global, or external, scope. If the
function or variable is not visible outside of the current source file, it is said to have
local, or static, scope.
q. Write the equivalent expression for x%8?
Ans x&7
Q. What is the heap?
AnsThe heap is where malloc(), calloc(), and realloc() get memory. Getting memory from the heap is much slower than getting it from the stack. On the other hand, the heap is much more flexible than the stack. Memory can be allocated at any time and deallocated in any order. Such memory isn’t deallocated automatically; you have to call
free(). Recursive data structures are almost always implemented with memory from the heap. Strings often come from there too, especially strings that could be very long at runtime. If you can keep data in a local variable (and allocate it from the stack), your code will run faster than if you put the data on the heap. Sometimes you can use a better algorithm if you use the heap—faster, or more robust, or more flexible. It’s a tradeoff.
If memory is allocated from the heap, it’s available until the program ends. That’s great
if you remember to deallocate it when you’re done. If you forget, it’s a problem. A “memory leak” is some allocated memory that’s no longer needed but isn’t deallocated. If you have a memory leak inside a loop, you can use up all the memory on the heap and not be able to get any more. (When that happens, the allocation functions return a null pointer.) In some environments, if a program doesn’t deallocate everything it allocated, memory stays unavailable even after the program ends.
Q)When should a far pointer be used?
Ans Sometimes you can get away with using a small memory model in most of a given program. There might be just a few things that don’t fit in your small data and code segments. When that happens, you can use explicit far pointers and function declarations to get at the rest of memory. A far function can be outside the 64KB segment most functions are shoehorned into for a small-code model. (Often, libraries are declared
explicitly far, so they’ll work no matter what code model the program uses.)
A far pointer can refer to information outside the 64KB data segment. Typically, such pointers are used with farmalloc() and such, to manage a heap separate from where all the rest of the data lives. If you use a small-data, large-code model, you should explicitly make your function pointers far.
Q. What is the difference between NULL and NUL?
Ans NULL is a macro defined in for the null pointer. NUL is the name of the first character in the ASCII character set. It corresponds to a zero value. There’s no standard macro NUL in C, but some people like to define it. The digit 0 corresponds to a value of 80, decimal. Don’t confuse the digit 0 with the value of ‘’ (NUL)! NULL can be defined as ((void*)0), NUL as ‘’.
Q. Can math operations be performed on a void pointer?
Ans 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.
Q How can you determine the size of an allocated portion of memory?
Ans You can’t, really. free() can , but there’s no way for your program to know the
trick free() uses. Even if you disassemble the library and discover the trick, there’s no
guarantee the trick won’t change with the next release of the compiler.
Q What is a void pointer?
Ans A void pointer is a C convention for “a raw address.” The compiler has no idea what type of object a void Pointer “really points to.” If you write
int *ip; ip points to an int. If you write
void *p; p doesn’t point to a void!
In C and C++, any time you need a void pointer, you can use another pointer type. For example, if you have a char*, you can pass it to a function that expects a void*. You don’t even need to cast it. In C (but not in C++), you can use a void* any time you need any kind of pointer, without casting. (In C++, you need to cast it). A void pointer is used for working with raw memory or for passing a pointer to an unspecified type. Some C code operates on raw memory. When C was first invented, character pointers (char *) were used for that. Then people started getting confused about when a character pointer was a string, when it was a character array, and when it was raw memory.
Q What does it mean when a pointer is used in an if statement?
Ans Any time a pointer is used as a condition, it means “Is this a non-null pointer?” A pointer can be used in an if, while, for, or do/while statement, or in a conditional expression.
Question How do you use a pointer to a function?
Answer 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;
Q. Is it better to use malloc() or calloc()?
AnsBoth the malloc() and the calloc() functions are used to allocate dynamic memory. Each operates slightly different from the other. malloc() takes a size and returns a pointer to a chunk of memory at least that big: void *malloc( size_t size );
calloc() takes a number of elements, and the size of each, and returns a pointer to a chunk
of memory at least big enough to hold them all: void *calloc( size_t numElements, size_t
sizeOfElement ); There’s one major difference and one minor difference between the two functions. The major difference is that malloc() doesn’t initialize the allocated memory. The first time malloc() gives you a particular chunk of memory, the memory might be full of zeros. If memory has been allocated, freed, and reallocated, it probably has whatever junk was left in it. That means, unfortunately, that a program might run in simple cases (when memory is never reallocated) but break when used harder (and
when memory is reused). calloc() fills the allocated memory with all zero bits. That means that anything there you’re going to use as a char or an int of any length, signed or
unsigned, is guaranteed to be zero. Anything you’re going to use as a pointer is set to all
zero bits. That’s usually a null pointer, but it’s not guaranteed.Anything you’re going to use as a float or double is set to all zero bits; that’s a floating-point zero on some types of
machines, but not on all. The minor difference between the two is that calloc() returns an array of objects; malloc() returns one object. Some people use calloc() to make clear that they want an array.
Q What is the benefit of using an enum rather than a #define constant?
Ans The use of an enumeration constant (enum) has many advantages over using the traditional symbolic constant style of #define. These advantages include a lower maintenance requirement, improved program readability, and better debugging capability.
1) The first advantage is that enumerated constants are generated automatically by the
compiler. Conversely, symbolic constants must be manually assigned values by the programmer. For instance, if you had an enumerated constant type for error codes that could occur in your program, your enum definition could look something like this:
enum Error_Code
{
OUT_OF_MEMORY,
INSUFFICIENT_DISK_SPACE,
LOGIC_ERROR,
FILE_NOT_FOUND
};
In the preceding example, OUT_OF_MEMORY is automatically assigned the value of 0 (zero) by the compiler because it appears first in the definition. The compiler then continues to automatically assign numbers to the enumerated constants, making INSUFFICIENT_DISK_SPACE equal to 1, LOGIC_ERROR equal to 2, and FILE_NOT_FOUND equal to 3, so on. If you were to approach the same example by
using symbolic constants, your code would look something like this:
#define OUT_OF_MEMORY 0
#define INSUFFICIENT_DISK_SPACE 1
#define LOGIC_ERROR 2
#define FILE_NOT_FOUND 3
values by the programmer. Each of the two methods arrives at the same result: four
constants assigned numeric values to represent error codes. Consider the maintenance required, however, if you were to add two constants to represent the error codes DRIVE_NOT_READY and CORRUPT_FILE. Using the enumeration constant
method, you simply would put these two constants anywhere in the enum definition. The compiler would generate two unique values for these constants. Using the symbolic constant method, you would have to manually assign two new numbers to these constants. Additionally, you would want to ensure that the numbers you assign to these constants are unique.
2) Another advantage of using the enumeration constant method is that your programs are more readable and thus can be understood better by others who might have to update your program later.
3) A third advantage to using enumeration constants is that some symbolic debuggers can print the value of an enumeration constant. Conversely, most symbolic debuggers cannot print the value of a symbolic constant. This can be an enormous help in debugging your program, because if your program is stopped at a line that uses an enum, you can simply inspect that constant and instantly know its value. On the other hand, because most debuggers cannot print #define values, you would most likely have to search for
that value by manually looking it up in a header file.
Question How are portions of a program disabled in demo versions?
Answer If you are distributing a demo version of your program, the preprocessor can be used to enable or disable portions of your program. The following portion of code shows how this task is accomplished, using the preprocessor directives #if and #endif:
int save_document(char* doc_name)
{
#if DEMO_VERSION
printf(“Sorry! You can’t save documents using
the DEMO version of this program!n”);
return(0);
#endif
...
}
Q What is the difference between #include
Ans
INCLUDE=C:\COMPILER\INCLUDE;S:\SOURCE\HEADERS;
using the #include version of file inclusion, the compiler first checks the
C:\COMPILER\INCLUDE
directory for the specified file. If the file is not found there, the compiler then checks the
S:\SOURCE\HEADERS directory. If the file is still not found, the preprocessor checks the current directory. The second way to include files is to surround the file you want to include with double quotation marks. This method of inclusion tells the preprocessor to look for the file in the current directory first, then look for it in the predefined locations you have set up. Using the #include “file” version of file inclusion and applying it to the preceding example, the preprocessor first checks the current directory for the specified file. If the file is not found in the current directory, the C:COMPILERINCLUDE
directory is searched. If the file is still not found, the preprocessor checks the S:SOURCEHEADERS directory. The #include method of file inclusion is often used to include standard headers such as stdio.h or stdlib.h. This is because these headers are rarely (if ever) modified, and they should always be read from your compiler’s standard include file directory.
The #include “file” method of file inclusion is often used to include nonstandard header files that you have created for use in your program. This is because these headers are often modified in the current directory, and you will want the preprocessor to use your newly modified version of the header rather than the older, unmodified version.
Q How many levels of pointers can you have?
Ans The answer depends on what you mean by “levels of pointers.” If you mean “How many levels of indirection can you have in a single declaration?” the answer is “At least 12.”
int i = 0;
int *ip01 = & i;
int **ip02 = & ip01;
int ***ip03 = & ip02;
int ****ip04 = & ip03;
int *****ip05 = & ip04;
int ******ip06 = & ip05;
int *******ip07 = & ip06;
int ********ip08 = & ip07;
int *********ip09 = & ip08;
int **********ip10 = & ip09;
int ***********ip11 = & ip10;
int ************ip12 = & ip11;
************ip12 = 1; /* i = 1 */
The ANSI C standard says all compilers must handle at least 12 levels. Your compiler might support more.
Question How can I convert a string to a number?
Answer The standard C library provides several functions for converting strings to numbers of all formats (integers, longs, floats, and so on) and vice versa.
The following functions can be used to convert strings to numbers: Function Name Purpose atof() Converts a string to a double-precision floating-point value. atoi() Converts a string to an integer. atol() Converts a string to a long integer. strtod() Converts a string to a double-precision floating-point value and reports any “leftover” numbers that could not be converted. strtol() Converts a string to a long integer and reports any “leftover” numbers that could not be converted. strtoul() Converts a string to an unsigned long integer and reports any “leftover” numbers that
could not be converted.
Question What is the difference between a string copy (strcpy) and a memory copy (memcpy)? When should each be us
Answer The strcpy() function is designed to work exclusively with strings. It copies each byte of the source string to the destination string and stops when the terminating null character () has been moved. On the other hand, the memcpy() function is designed to work with any type of data. Because not all data ends with a null character, you must provide the memcpy() function with the number of bytes you want to copy from the source to the destination.
Question What is a pragma?
Answer The #pragma preprocessor directive allows each compiler to implement compiler-specific features that can be turned on and off with the #pragma statement. For instance, your compiler might support a feature called loop optimization. This feature can be invoked as a command-line option or as a #pragma directive. To implement this option using the #pragma directive, you would put the following line into your code:
#pragma loop_opt(on)
Conversely, you can turn off loop optimization by inserting the following line into your code:
#pragma loop_opt(off)
Question How do you override a defined macro?
Ans You can use the #undef preprocessor directive to undefine (override) a previously defined macro.
Q What are the standard predefined macros?
Ans The ANSI C standard defines six predefined macros for use in the C language:
Macro Name Purpose
_ _LINE_ _ Inserts the current source code line number in your code.
_ _FILE_ _ Inserts the current source code filename in your code.
_ _DATE_ _ Inserts the current date of compilation in your code.
_ _TIME_ _ Inserts the current time of compilation in your code.
_ _STDC_ _ Is set to 1 if you are enforcing strict ANSI C conformity.
_ _cplusplus Is defined if you are compiling a C++ program.
Question How can you avoid including a header more than once?
Answer One easy technique to avoid multiple inclusions of the same header is to use the
#ifndef and #define preprocessor directives. When you create a header for your program, you can #define a symbolic name that is unique to that header. You can use the conditional preprocessor directive named #ifndef to check whether that symbolic name has already been assigned. If it is assigned, you should not include the header, because it has already been preprocessed. If it is not defined, you should define it to avoid any further inclusions of the header. The following header illustrates this technique:
#ifndef _FILENAME_H
#define _FILENAME_H
#define VER_NUM “1.00.00”
#define REL_DATE “08/01/94”
#if _ _WINDOWS_ _
#define OS_VER “WINDOWS”
#else
#define OS_VER “DOS”
#endif
#endif
When the preprocessor encounters this header, it first checks to see whether _FILENAME_H has been defined. If it hasn’t been defined, the header has not been included yet, and the _FILENAME_H symbolic name is defined. Then, the rest of the
header is parsed until the last #endif is encountered, signaling the end of the conditional #ifndef _FILENAME_H statement. Substitute the actual name of the header file
for “FILENAME” in the preceding example to make it applicable for your programs.
Question What is the quickest searching method to use?
Answer A binary search, such as bsearch() performs, is much faster than a linear search. A hashing algorithm can provide even faster searching. One particularly interesting and fast method for searching is to keep the data in a “digital trie.” A digital trie offers the
prospect of being able to search for an item in essentially a constant amount of time,
independent of how many items are in the data set. A digital trie combines aspects of binary searching, radix searching, and hashing. The term “digital trie” refers to the data structure used to hold the items to be searched. It is a multilevel data structure that branches N ways at each level.
Question when should the volatile modifier be used?
Answer The volatile modifier is a directive to the compiler’s optimizer that operations
involving this variable should not be optimized in certain ways. There are two special cases in which use of the volatile modifier is desirable. The first case involves memory-mapped hardware (a device such as a graphics adaptor that appears to the computer’s hardware as if it were part of the computer’s memory), and the second involves shared memory (memory used by two or more programs running simultaneously).
Most computers have a set of registers that can be accessed faster than the computer’s main memory. A good compiler will perform a kind of optimization called “redundant load and store removal.” The compiler looks for places in the code where it can either remove an instruction to load data from memory because the value is already in a register, or remove an instruction to store data to memory because the value can stay in a register until it is changed again anyway. If a variable is a pointer to something other
than normal memory, such as memory-mapped ports on a peripheral, redundant load and store optimizations might be detrimental. For instance, here’s a piece of code that might be used to time some operation:
time_t time_addition(volatile const struct timer
*t, int a)
{
int n;
int x;
time_t then;
x = 0;
then = t->value;
for (n = 0; n < 1000; n++)
{
x = x + a;
}
return t->value - then;
}
this code, the variable t->value is actually a hardware counter that is being incremented as time passes. The function adds the value of a to x 1000 times, and it returns the amount the timer was incremented by while the 1000 additions were being performed. Without the volatile modifier, a clever optimizer might assume that the value of t does not change
during the execution of the function, because there is no statement that explicitly changes
it. In that case, there’s no need to read it from memory a second time and subtract it,
because the answer will always be 0. The compiler might therefore “optimize” the function by making it always return 0. If a variable points to data in shared memory,
you also don’t want the compiler to perform redundant load and store optimizations. Shared memory is normally used to enable two programs to communicate with each other by having one program store data in the shared portion of memory and the other program read the same portion of memory. If the compiler optimizes away a load or store of shared memory, communication between the two programs will be affected.

No comments:
Post a Comment