Q. What is a pragma?
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)
Q. What is the difference between far and near?
Some
compilers for PC compatibles use two types of pointers. Near pointers are 16
bits long and can address a 64KB range. Far pointers are 32 bits long and can
address a 1MB range.
Near pointers operate within a 64KB segment. There’s one segment for function addresses and one segment for data. Far pointers have a 16-bit base (the segment address) and a 16-bit offset. The base is multiplied by 16, so a far pointer is effectively 20 bits long. Before you compile your code, you must tell the compiler which memory model to use. If you use a small code memory model, near pointers are used by default for function addresses.
That means that all the functions need to fit in one 64KB segment. With a large-code model, the default is to use far function addresses. You’ll get near pointers with a small data model, and far pointers with a large data model. These are just the defaults; you can declare variables and functions as explicitly near or far.
Far pointers are a little slower. Whenever one is used, the code or data segment register needs to be swapped out. Far pointers also have odd semantics for arithmetic and comparison. For example, the two far pointers in the preceding example point to the same address, but they would compare as different! If your program fits in a small-data, small-code memory model, your life will be easier.
Q. When would you use a pointer to a function?
Pointers
to functions are interesting when you pass them to other functions. A function
that takes function pointers says, in effect, “Part of what I do can be
customized. Give me a pointer to a function, and I’ll call it when that part of
the job needs to be done. That function can do its part for me.” This is known
as a “callback.” It’s used a lot in graphical user interface libraries, in
which the style of a display is built into the library but the contents of the
display are part of the application.
As a simpler example, say you have an array of character pointers (char*s), and you want to sort it by the value of the strings the character pointers point to. The standard qsort() function uses function pointers to perform that task. qsort() takes four arguments,
As a simpler example, say you have an array of character pointers (char*s), and you want to sort it by the value of the strings the character pointers point to. The standard qsort() function uses function pointers to perform that task. qsort() takes four arguments,
Ø a pointer to the beginning of the array,
Ø the number of elements in the array,
Ø the size of each array element, and
Ø a comparison function, and returns an int.
Q. How are pointer variables initialized?
Pointer variable are initialized by one
of the following two ways
Ø Static memory allocation
Ø Dynamic memory allocation.
Ø Static memory allocation
Ø Dynamic memory allocation.
Q. How can you avoid
including a header more than once?
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.
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”
#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.
#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.
Q. Difference between
arrays and pointers?
Ø
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. What are the
advantages of the functions?
Ø 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.
Ø 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. Is NULL always defined
as 0?
NULL is defined as either 0 or (void*)0. These values are almost
identical; either a literal zero or a void pointer is converted automatically
to any kind of pointer, as necessary, whenever a pointer is needed (although
the compiler can’t always tell when a pointer is needed).
Q. What is the difference
between NULL and NUL?
NULL is a macro defined in <stddef.h> 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 the
sizeof operator be used to tell the size of an array passed to a function?
No. There’s no way to tell, at runtime, how many elements are in
an array parameter just by looking at the array parameter itself. Remember,
passing an array to a function is exactly the same as passing a pointer to the
first element.
Q. Is using exit() the same as using return?
No. The exit() function is used to exit your program and return
control to the operating system. The return statement is used to return from a
function and return control to the calling function. If you issue a return from
the main() function, you are essentially returning control to the calling
function, which is the operating system. In this case, the return statement and
exit() function are similar.
Q. How many levels of pointers can you have?
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.
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.
Q. What is the purpose of realloc( )?
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.
Q. Is it better to use a macro or a function?
The answer depends on the situation you are writing code for.
Macros have the distinct advantage of being more efficient (and faster) than
functions, because their corresponding code is inserted directly into your
source code at the point where the macro is called. There is no overhead
involved in using a macro like there is in placing a call to a function.
However, macros are generally small and cannot handle large, complex coding
constructs. A function is more suited for this type of situation.
Additionally, macros are expanded inline, which means that the
code is replicated for each occurrence of a macro. Your code therefore could be
somewhat larger when you use macros than if you were to use functions.
Thus, the choice between using a macro and using a function is one of deciding between the tradeoff of faster program speed versus smaller program size. Generally, you should use macros to replace small, repeatable code sections, and you should use functions for larger coding tasks that might require several lines of code.
Q. What are the standard predefined macros?
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.
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.
Q. What is a const pointer?
The access modifier keyword const is a promise the programmer
makes to the compiler that the value of a variable will not be changed after it
is initialized. The compiler will enforce that promise as best it can by not
enabling the programmer to write code which modifies a variable that has been
declared const.
A “const pointer,” or more correctly, a “pointer to const,” is a pointer which points to data that is const(constant, or unchanging). A pointer to const is declared by putting the word const at the beginning of the pointer declaration. This declares a pointer which points to data that can’t be modified. The pointer itself can be modified. The following example illustrates some legal and illegal uses of a const pointer:
const char *str = “hello”;
char c = *str /* legal */
str++; /* legal */
*str = ‘a’; /* illegal */
str[1] = ‘b’; /* illegal */
Q. why n++ executes faster than n+1?
The
expression n++ requires a single machine instruction such as INR to carry out
the increment operation whereas; n+1 requires more instructions to carry out
this operation.
Q. What is the difference between text and binary modes?
Streams can be classified into two types: text streams and
binary streams. Text streams are interpreted, with a maximum length of 255
characters. With text streams, carriage return/line feed combinations are
translated to the new line n character and vice versa. Binary streams are uninterrupted
and are treated one byte at a time with no translation of characters.
Typically, a text stream would be used for reading and writing standard text
files, printing output to the screen or printer, or receiving input from the
keyboard.
A binary text stream would typically be used for reading and writing binary files such as graphics or word processing documents, reading mouse input, or reading and writing to the modem.
Q. How do you determine whether to use a stream function or a
low-level function?
Stream functions such as fread() and fwrite() are buffered and
are more efficient when reading and writing text or binary data to files. You
generally gain better performance by using stream functions rather than their
unbuffered low-level counterparts such as read() and write().
In multi-user environments, however, when files are typically shared and portions of files are continuously being locked, read from, written to, and unlocked, the stream functions do not perform as well as the low-level functions. This is because it is hard to buffer a shared file whose contents are constantly changing. Generally, you should always use buffered stream functions when accessing nonshared files and you should always use the low-level functions when accessing shared files.
Q. What is static memory allocation and dynamic memory allocation?
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 assingned to pointer variables, such assignments are known as dynamic memory allocation.memory is assined during run time.
Q. When should a far pointer be used?
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 functions 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 benefit of using const for declaring constants?
The benefit of using the const keyword is that the compiler
might be able to make optimizations based on the knowledge that the value of
the variable will not change. In addition, the compiler will try to ensure that
the values won’t be changed inadvertently.
Of course, the same benefits apply to #defined constants. The reason to use const rather than #define to define a constant is that a const variable can be of any type (such as a struct, which can’t be represented by a #defined constant). Also, because a const variable is a real variable, it has an address that can be used, if needed, and it resides in only one place in memory.
Q. What is the easiest sorting method to use?
The
answer is the standard library function qsort(). It’s the easiest sort by far
for several reasons:
It is already written.
It is already debugged.
It has been optimized as much as possible (usually).
Void qsort(void *buf, size_t num, size_t size, int (*comp)(const void *ele1, const void *ele2));
It is already written.
It is already debugged.
It has been optimized as much as possible (usually).
Void qsort(void *buf, size_t num, size_t size, int (*comp)(const void *ele1, const void *ele2));
Q. What is Preprocessor?
The preprocessor is used to modify your program according to the
preprocessor directives in your source code. Preprocessor directives (such as
#define) give the preprocessor specific instructions on how to modify your
source code. The preprocessor reads in all of your include files and the source
code you are compiling and creates a preprocessed version of your source code.
This preprocessed version has all of its macros and constant symbols replaced
by their corresponding code and value assignments. If your source code contains
any conditional preprocessor directives (such as #if), the preprocessor
evaluates the condition and modifies your source code accordingly.
The preprocessor contains many features that are powerful to use, such as creating macros, performing conditional compilation, inserting predefined environment variables into your code, and turning compiler features on and off. For the professional programmer, in-depth knowledge of the features of the preprocessor can be one of the keys to creating fast, efficient programs.
Q. What is the heap?
The 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. What will the preprocessor do for a program?
The C preprocessor is used to modify your program according to
the preprocessor directives in your source code. A preprocessor directive is a
statement (such as #define) that gives the preprocessor specific instructions
on how to modify your source code. The preprocessor is invoked as the first
part of your compiler program’s compilation step. It is usually hidden from the
programmer because it is run automatically by the compiler.
The preprocessor reads in all of your include files and the source code you are compiling and creates a preprocessed version of your source code. This preprocessed version has all of its macros and constant symbols replaced by their corresponding code and value assignments. If your source code contains any conditional preprocessor directives (such as #if), the preprocessor evaluates the condition and modifies your source code accordingly.
Q. 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 <string.h> and assign the address of strcmp() to pf: pf = strcmp;
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 <string.h> and assign the address of strcmp() to pf: pf = strcmp;
Q. What is the purpose of main( ) function?
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
Ø 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. How can you restore a redirected standard stream?
The preceding example showed how you can redirect a standard
stream from within your program. But what if later in your program you wanted
to restore the standard stream to its original state? By using the standard C
library functions named dup() and fdopen(), you can restore a standard stream
such as stdout to its original state.
The dup() function duplicates a file handle. You can use the dup() function to save the file handle
corresponding to the stdout standard stream. The fdopen() function opens a stream that has been
duplicated with the dup() function.
Q. What is #line used for?
The
#line preprocessor directive is used to reset the values of the _ _LINE_ _ and
_ _FILE_ _ symbols,
respectively. This directive is commonly used in fourth-generation languages that generate C language source files.
respectively. This directive is commonly used in fourth-generation languages that generate C language source files.
Q. What
is the difference between the memmove() and memcpy() function?
memmove() offers guaranteed behavior if the
source and destination arguments overlap. memcpy() makes no such guarantee, and
may therefore be more efficient to implement. It's always safer to use
memmove().
No comments:
Post a Comment
Don't judge me like you know me.Don't talk to me if you don't like me. I am my own person and If you don't like that i don't give a f***