Вы находитесь на странице: 1из 20

Below are a few questions Question: Reverse a string in C using as little additional memory as possible.

Answer: The first solution needs the size of a char and size of two integers, all of which will be allocated from the stack. This solution is the most commonly accepted good solution. Here is the code.
void reverseString(char* str) { int i, j; char temp; i=j=temp=0; j=strlen(str)-1; for (i=0; i<j; i++, j--) { temp=str[i]; str[i]=str[j]; str[j]=temp; } }

The second solution is slightly better than the first as it does not need the char space. It uses bitmanipulation (XOR in this case) to swap the chars in place.
void reverseStringBetter(char* str) { int i, j; i=j=0; j=strlen(str)-1; for (i=0; i<j; i++, j--) { str[i] ^= str[j] ; str[j] ^= str[i] ; str[i] ^= str[j] ; } } Question: - Setting, Clearing and Toggling a single bit in a value..?

#include <stdio.h> int number1 = 0x1; int number2 = 0x3; int number3 = 0x5; int main (void) { /* setting a bit*/ number1 |= 1 << 1; printf("\n 0x%x\n", number1); /* Clearing a bit */ number2 &= ~(1 << 1); printf("\n 0x%x\n", number2); /* Toggling a bit */ number3 ^= 1 << 1; printf("\n 0x%x\n", number3); return 0;

} Other Ways: Way1: /* a=target variable, b=bit number to act upon 0-n */ #define BIT_SET(a,b) ((a) |= (1<<(b))) #define BIT_CLEAR(a,b) ((a) &= ~(1<<(b))) #define BIT_FLIP(a,b) ((a) ^= (1<<(b))) #define BIT_CHECK(a,b) ((a) & (1<<(b))) /* x=target variable, y=mask */ #define BITMASK_SET(x,y) ((x) |= (y)) #define BITMASK_CLEAR(x,y) ((x) &= (~(y))) #define BITMASK_FLIP(x,y) ((x) ^= (y)) #define BITMASK_CHECK(x,y) ((x) & (y))

2#define BITOP(a,b,op) \ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))

To set a bit:
BITOP(array, bit, |=);

To clear a bit:
BITOP(array, bit, &=~);

To toggle a bit:
BITOP(array, bit, ^=);

To test a bit:
if (BITOP(array, bit, &)) ...

Q1: difference between macro and inline functions ? Ans:1. Inline follows strict parameter type checking, macros do not. 2. Macros are always expanded by preprocessor, whereas compiler may or may not replace the inline definitions. 3. compiler has no idea about macros , compiler knows about inline functions. 4. Inline follows strict parameter type checking, macros do not. 5. Macros are always expanded by preprocessor, whereas compiler may or may not 6. replace the inline definitions. I V Inline Function Preprocessor Macro good for declaring constnts eg. #define PI 3.14 Provide textual substitution Each time the macro name is encountered with arguments, the arguments used in its definition are

replaced by the actual arguments found. 1 It is a function provided by C++. It is declared by using the keyword inline before the function protoype. It is a a preprocessor directive provided by C. It is declared by using the preprocessor directive #define before the actual statement. In some cases, expressions passed as arguments to macros can be evaluated more than once. Every time you use an argument in a macro, that argument is evaluated. #define max(a,b) (a>b?a:b) void main() { int a = 0; int b = 1; int c = max(a++, b++); cout << a << endl << b << endl; } The intention is to have the program print 1 and 2, but because the macro is expanded to: int c = a++ > b++ ? a++ : b++; b will be incremented twice, and the program prints 1 and 3. //try 3 They are parsed by the compiler They are expanded by the preprocessor at pre-compile time. No such thing, hence, macros are more error prone as compared to inline functions. the The parameters are not typed (the macro works for any objects of arithmetic type). No error checking is done during

Expressions passed as arguments to inline functions are evaluated once.

Inline functions follow all the protocols of type safety enforced on normal functions. Argument types are checked, and necessary conversions are performed correctly.

The compiler performs return type checking, function signature before putting inline function into symbol table. They can be overloaded to perform the right kind of operation for the right kind of data.

compilation. Eg. you can pass strings to a macro that does some integer arithmetic #define MAX(a, b) ((a < b) ? b : a)

int main( void) { cout << "Maximum of 10 and 20 is " << MAX("20", "10") << endl; return 0; } 5 Can be used for debugging a Can not be used for debugging as they program as they are expanded at are expanded at pre-compile time. compile time and a break point caa be placed at the inline function adefinition and step into the method for debugging step by step. Inline member functioncs can access the classs member data. The preprocessor has no permission to access member data of a class and are thus useless even if used within a class. Thus they can not even be used as member functions. Eg. #define VAL (X::i) // Error class X { int i; public: ---}; 7 Paranthesis need to be handled carefully as missing a pair or putting an extra pair may prouce undesirable results. Inline functions may or may not be expanded by the compiler. It is Macros are always expanded.

the compilers decision whether to expand the function inline or not. 9 It can be defined inside or outside the class. Inline functions pass arguments by value, just like regular functions do. If the argument is an expression such as 4.5 +7.5 then the function passes the value of the expression 12 in this case. It can not be defined insode the class.

1 0

Expressions passed into macros are not always evaluated before entering the macro body. Macros dont pass by value. Thus , #define square(x) x*x : b=square(4.5+7.5) This will be replaced by : b=4.5+7.5*4.5+7.5

1 1

Since type checking can be used in inline functions, theis problem can be avoided.

Expressions may expand inside the macro so that their evaluation precedence is different from what you expect. Eg. #define FLOOR(x,b) x>=b?0:1 Now, if expressions are used for the arguments if(FLOOR(a&0x0f,0x07)) // ... the macro will expand to if(a&0x0f>=0x07?0:1) The precedence of & is lower than that of >=, so the macro evaluation will surprise you.

Q2:- Find nth node from last in single linked list Ans:1.
LinkedListNode nthToLast(LinkedListNode head, int n) { if (head == null || n < 1) { return null; }

LinkedListNode p1 LinkedListNode p2 for (int j = 0; j if (p2 == null) { return null; } p2 = p2.next; } while (p2.next != p1 = p1.next; p2 = p2.next; } } return p1;

= head; = head; < n - 1; ++j) { // skip n-1 steps ahead // not found since list size < n

null) {

Alternatively we can set p1 and p2 apart by n nodes instead of (n-1) and then move p2 till the end of the list instead of moving till the last node:
LinkedListNode p1 = head; LinkedListNode p2 = head; for (int j = 0; j < n ; ++j) { // make then n nodes apart. if (p2 == null) { return null; } p2 = p2.next; } while (p2 != null) { // move till p2 goes past the end of the list. p1 = p1.next; p2 = p2.next; } return p1;

What do you think regarding this approach. 1. Count length of the linkedlist. 2. Actual Node index from head = linkedlist length - given index; 3. Write a function to travesre from head and get the node at the above index.

Q3: - How will you implement macro sizeof Answer: 1. #define SIZE(type) (size_t)((type *)100 + 1) - (size_t)((type *)100) 2. #define size1(var) (void *)(&var+1)-(void *)(&var) //for variable #define size2(type) ((void *)((type *)(1)+1))-((void *)((type *)(1))) //for 3. #define sizeof_op1(val) (&val +1 ) - &val // for variable ex Q4: - How will you organize 1 lakh numbers?? Ans: Q5: - Difference between little endian and big endian, write a code that tells you machine is little or big endian ?? Ans: -

#if defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN) #define #define #define #define htons(A) htonl(A) ntohs(A) ntohl(A) (A) (A) (A) (A)

#elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) #define htons(A) ((((uint16_t)(A) (((uint16_t)(A) #define htonl(A) ((((uint32_t)(A) (((uint32_t)(A) (((uint32_t)(A) (((uint32_t)(A) #define ntohs #define ntohl #else #error "Must define one of BIG_ENDIAN or LITTLE_ENDIAN" #endif Function to find Little OR Big Indian bool IsBigEndian() { short word = 0x4321; if((*(char *)& word) != 0x21 ) return true; else return false; } htons htonl & & & & & & 0xff00) >> 8) | \ 0x00ff) << 8)) 0xff000000) >> 24) | \ 0x00ff0000) >> 8) | \ 0x0000ff00) << 8) | \ 0x000000ff) << 24))

Question: - What is NAT ?? Answer: Network Address Translation helps improve security by reusing IP addresses. The NAT router translates traffic coming into and leaving the private network. Network Address Translation allows a single device, such as a router, to act as agent between the Internet (or ""public network"") and a local (or ""private"") network. When a computer running NAT receive a packet from an internal client, it replaces the packet header and translate the client's port number and internal IP address to its own port number and external IP address then sends the packet to the destination host on the Internet and keep track of the mapping information in a table, so that can route the replay to the appropriate client computer Basically, Network Address Translation allows a single device, such as a router, to act as agent between the Internet (or "public network") and a local (or "private") network. This means that only a single unique IP address is required to represent an entire group of computers to anything outside their network. The shortage of IP addresses is only one reason to use NAT. Two other good reasons are: Security

Administration Type of NAT: 1. Static NAT 2. Dynamic NAT

3.
4.

Overloading A form of dynamic NAT that maps multiple unregistered IP addresses to a single registered IP address by using different ports. Known also as PAT (Port Address Translation), single address NAT or portlevel multiplexed NAT. Overlapping.

Question: What things will you keep in mind while writing a high level design ?? Question:How will you allocate a memory to 2d integer array ??
#include <stdlib.h> int **array; array = malloc(nrows * sizeof(int *)); if(array == NULL) { fprintf(stderr, "out of memory\n"); exit or return } for(i = 0; i < nrows; i++) { array[i] = malloc(ncolumns * sizeof(int)); if(array[i] == NULL) { fprintf(stderr, "out of memory\n"); exit or return } } for(i = 0; i < nrows; i++) free(array[i]); free(array);

Question:What is alignment ??
Data structure alignment is the way data is arranged and accessed in computer memory. It consists of two separate but related issues:data alignment and data structure padding. When a modern computer reads from or writes to a memory address, it will do this in word sized chunks (e.g. 4 byte chunks on a 32-bit system). Data alignment means putting the data at a memory offset equal to some multiple of the word size, which increases the system's performance due to the way the CPU handles memory. To align the data, it may be necessary to insert some meaningless bytes between the end of the last data structure and the start of the next, which is data structure padding. For example, when the computer's word size is 4 bytes (a byte meaning 8 bits), the data to be read should be at a memory offset which is some multiple of 4. When this is not the case, e.g. the data starts at the 14th byte instead of the 16th byte, then the computer has to read two 4-byte chunks and do some calculation before the requested data has been read, or it may generate an alignment fault. Even though the previous data structure ends

at the 14th byte, the next data structure should start at the 16th byte. Two padding bytes are inserted between the two data structures to align the next data structure to the 16th byte.

Problems
A computer accesses memory by a single memory word at a time. As long as the memory word size is at least as large as the largestprimitive data type supported by the computer, aligned accesses will always access a single memory word. This may not be true for misaligned data accesses. If the highest and lowest bytes in a datum are not within the same memory word the computer must split the datum access into multiple memory accesses. This requires a lot of complex circuitry to generate the memory accesses and coordinate them. To handle the case where the memory words are in different memory pages the processor must either verify that both pages are present before executing the instruction or be able to handle a TLB miss or a page fault on any memory access during the instruction execution. The Unix malloc functions usually return aligned memory space.

Question: -

How will you align an allocated pointer ??


#include <assert.h> #include <inttypes.h> #include <stdio.h> #include <stdlib.h> static void memset_16aligned(void *space, char byte, size_t nbytes) { assert((nbytes & 0x0F) == 0); assert(((uintptr_t)space & 0x0F) == 0); } int main(void) { void *mem = malloc(1024+15); void *ptr = (void *)(((uintptr_t)mem+15) & ~ 0x0F); printf("0x%08" PRIXPTR ", 0x%08" PRIXPTR "\n", mem, ptr); memset_16aligned(ptr, 0, 1024); free(mem); return(0); }

Question: - Write a code for reversing a linked list, recursive and nonrecursive. Recursive:Node* reverse(node *hed, node *prev) { node *tmp; tmp=hed->next; hed->next=prev; if(tmp!=NULL) { hed=reverse(tmp,hed); } return hed; }

Non Recursive:Now for a non-recursive solution.


Node * reverse( Node * ptr ) { Node * temp; Node * previous = NULL; while(ptr != NULL) { temp = ptr->next; ptr->next = previous; previous = ptr; ptr = temp; } return previous;

} Q: - How to find whether a machine is 32bit or 64 bit? Write code for this..??
A:- get the sizeof pointer on the machine. If it is 32 bit means 32 bit system else if 64 means
64 bit machine. Also we can use uname system command to find the details for the same.

Question: - What is Y shape linked list.. ?? Answer:1. Find the length of both the linked list 2. Find the difference in length(d) 3. For the longer LL, traverse d node and check the addresses with another LL //*********************************************** //This Function will find the intersection of //two linked list //*********************************************** void Intersection(struct node* head1, struct node *head2) {
//find the length of each linked list int len1=Count(head1), len2=Count(head2); //find the difference between both the linked list int diff=(len1>len2)?(len1-len2):len2-len1; int remainingLength=0; //Traverse linked list with greater node //till the remaining length becomes same //for both the linked list if(len1-len2>0) { remainingLength=len1-diff; for(int i=1;i<=diff;i++) head1=head1->next; } else { remainingLength=len2-diff; for(int i=1;i<=diff;i++) head2=head2->next; }

Ans2: Method 1(Simply use two loops) Use 2 nested for loops. Outer loop will be for each node of the 1st list and inner loop will be for 2nd list. In the inner loop, check if any of nodes of 2nd list is same as the current node of first linked list. Time complexity of this method will be O(mn) where m and n are the number of nodes in two lists.

Method 2 (Mark Visited Nodes) This solution requires modifications to basic linked list data structure. Have a visited flag with each node. Traverse the first linked list and keep marking visited nodes. Now traverse second linked list, If you see a visited node again then there is an intersection point, return the intersecting node. This solution works in O(m+n) but requires additional information with each node. A variation of this solution that doesnt require modification to basic data structure can be implemented using hash. Traverse the first linked list and store the addresses of visited nodes in a hash. Now traverse the second linked list and if you see an address that already exists in hash then return the intersecting node. Method 3(Using difference of node counts) 1) Get count of the nodes in first list, let count be c1. 2) Get count of the nodes in second list, let count be c2. 3) Get the difference of counts d = abs(c1 c2) 4) Now traverse the bigger list from the first node till d nodes so that from here onwards both the lists have equal no of nodes. 5) Then we can traverse both the lists in parallel till we come across a common node. (Note that getting a common node is done by comparing the address of the nodes)

#include<stdio.h> #include<stdlib.h> /* Link list node */ struct node { int data; struct node* next; }; /* Function to get the counts of node in a linked list */ int getCount(struct node* head); /* function to get the intersection point of two linked lists head1 and head2 where head1 has d more nodes than head2 */ int _getIntesectionNode(int d, struct node* head1, struct node* head2); /* function to get the intersection point of two linked lists head1 and head2 */ int getIntesectionNode(struct node* head1, struct node* head2) { int c1 = getCount(head1); int c2 = getCount(head2); int d; if(c1 > c2) { d = c1 - c2; return _getIntesectionNode(d, head1, head2); } else {

d = c2 - c1; return _getIntesectionNode(d, head2, head1); } } /* function to get the intersection point of two linked lists head1 and head2 where head1 has d more nodes than head2 */ int _getIntesectionNode(int d, struct node* head1, struct node* head2) { int i; struct node* current1 = head1; struct node* current2 = head2; for(i = 0; i < d; i++) { if(current1 == NULL) { return -1; } current1 = current1->next; } while(current1 != NULL && current2 != NULL) { if(current1 == current2) return current1->data; current1= current1->next; current2= current2->next; } return -1; } /* Takes head pointer of the linked list and returns the count of nodes in the list */ int getCount(struct node* head) { struct node* current = head; int count = 0; while (current != NULL) { count++; current = current->next; } return count; } /* IGNORE THE BELOW LINES OF CODE. THESE LINES ARE JUST TO QUICKLY TEST THE ABOVE FUNCTION */ int main() {

/* Create two linked lists 1st 3->6->9->15->30 2nd 10->15->30 15 is the intersection point */ struct node* newNode; struct node* head1 = (struct node*) malloc(sizeof(struct node)); head1->data = 10; struct node* head2 = (struct node*) malloc(sizeof(struct node)); head2->data = 3; newNode = (struct node*) malloc (sizeof(struct node)); newNode->data = 6; head2->next = newNode; newNode = (struct node*) malloc (sizeof(struct node)); newNode->data = 9; head2->next->next = newNode; newNode = (struct node*) malloc (sizeof(struct node)); newNode->data = 15; head1->next = newNode; head2->next->next->next = newNode; newNode = (struct node*) malloc (sizeof(struct node)); newNode->data = 30; head1->next->next= newNode; head1->next->next->next = NULL; printf("\n The node of intersection is %d \n", getIntesectionNode(head1, head2)); getchar(); }
Time Complexity: O(m+n) Auxiliary Space: O(1)

Method 4 (Traverse both lists and compare addresses of last nodes) This method is only to detect if there is an intersection point or not. (Thanks to NeoTheSaviour for suggesting this) 1) Traverse the list 1, store the last node address 2) Traverse the list 2, store the last node address. 3) If nodes stored in 1 and 2 are same then they are intersecting.

Time complexity of this method is O(m+n) and used Auxiliary space is O(1)

Question: How will you implement a linked list library using void pointers? Write the complete code Ans:#include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct list { void *data; struct list *next; }List; struct check{ int i; char c; double d; } chk[] = { { 1, 'a', 1.1 }, { 2, 'b', 2.2 }, { 3, 'c', 3.3 } }; void insert(List **, void *, unsigned int);

void print(List *, void (*)(void *)); void printstr(void *); void printint(void *); void printchar(void *); void printcomp(void *); List *list1, *list2, *list3, *list4; int main(void) { char c[] int i[] = { 'a', 'b', 'c', 'd' }; = { 1, 2, 3, 4 };

char *str[] = { "hello1", "hello2", "hello3", "hello4" }; list1 = list2 = list3 = list4 = NULL; insert(&list1, &c[0], sizeof(char)); insert(&list1, &c[1], sizeof(char)); insert(&list1, &c[2], sizeof(char)); insert(&list1, &c[3], sizeof(char)); insert(&list2, &i[0], sizeof(int)); insert(&list2, &i[1], sizeof(int)); insert(&list2, &i[2], sizeof(int)); insert(&list2, &i[3], sizeof(int)); insert(&list3, str[0], strlen(str[0])+1); insert(&list3, str[1], strlen(str[0])+1); insert(&list3, str[2],strlen(str[0])+1); insert(&list3, str[3],strlen(str[0])+1); insert(&list4, &chk[0],sizeof chk[0]); insert(&list4, &chk[1],sizeof chk[1]); insert(&list4, &chk[2],sizeof chk[2]);

printf("Printing characters:"); print(list1, printchar); printf(" : done\n\n"); printf("Printing integers:"); print(list2, printint); printf(" : done\n\n"); printf("Printing strings:"); print(list3, printstr); printf(" : done\n\n"); printf("Printing composite:"); print(list4, printcomp); printf(" : done\n"); return 0; } void insert(List **p, void *data, unsigned int n) { List *temp; int i; /* Error check is ignored */ temp = malloc(sizeof(List)); temp->data = malloc(n); for (i = 0; i < n; i++) *(char *)(temp->data + i) = *(char *)(data + i); temp->next = *p; *p = temp; } void print(List *p, void (*f)(void *)) {

while (p) { (*f)(p->data); p = p->next; } } void printstr(void *str) { printf(" \"%s\"", (char *)str); }

void printint(void *n) { printf(" %d", *(int *)n); } void printchar(void *c) { printf(" %c", *(char *)c); } void printcomp(void *comp) { struct check temp = *(struct check *)comp; printf(" '%d:%c:%f", temp.i, temp.c, temp.d); } Question: - Sorted array is given, find 2 nos whose sum equals X ?? Answer: Complement the odd bits in a byte How does traceroute works What are the different means of IPC in linux kernel What is difference between process and threads done done done

What is difference between const char *, char const * etc... Write a code to merge two sorted linked lists

done done

If ttl is set to 15 and we have 10 machines, and each machine takes 2 seconds to process the packet, will the packet reach the end point? done Single linked list questions Given a pointer to node in linked list, no start pointer is given, how would you delete the node ?? to detect a loop in linked list? How many ways can you do that Find the middle node in the linked list done done

In binary search tree parent pointer is given, given is pointer to 2 nodes, find their least common successor. If we go up the tree its a Y shape linked list question, not a tree question. What is 1 and 2's complement How is -1 stored in computer What is masking? What is IP fragmentation? How will you assemble and identify packets which are fragmented? What are storage classes in C What are volatile variables, when to use them How will you make blocking call in C What does FD_ISSET do How will you send a RAW IP packet How will you send a RAW MAC packet When PF_PACKET is used What is difference between hub and bridge Can gdb be used to debug inline functions? How What are ICMP redirects? What is active and passive ftp? Which ftp will work when we are behind a NAT machine (compression fails behind a NAT machine and we have a separate function to bypass such packets, nat_adm_ctrl)

What is port forwarding When to use SNAT and DNAT What happens when we open a web page in terms of packet and OSI flow The best link on endianess - http://www.linuxjournal.com/article/6788 Linux system programming - http://users.abo.fi/lchang/Linuxprg.html Best link on semaphores and mutex http://blog.feabhas.com/2009/09/mutex-vs-semaphores--part-1-semaphores/ http://blog.feabhas.com/2009/09/mutex-vs-semaphores--part-2-the-mutex/

Study the diagram in http://www.frozentux.net/iptables-tutorial/iptablestutorial.html Chapter 6. Traversing of tables and chains The diagram is a beauty and explains how a packet comes from the network and goes out of the network inside a linux box. NAT is a very common thing these days, study in detail. Iptables abd Ebtables http://ebtables.sourceforge.net/br_fw_ia/br_fw_ia.html

Also I am forwarding the fragmented IP packets, open in wireshark and read in detail. By default wireshark applies its intelligence and show the entire packet when it gets all the fragments in human readable form. You can turn this off. Packet sent is of size 333 including ip header. MTU is set to 100 bytes. So the split is Ip header Ip payload len len Ip len total

origframe frag_fram e1 frag_fram e2 frag_fram e3 frag_fram e4

20 20 20 20 20

313 80 80 80 73

333 100 100 100 93

As we can see IP payload 313 is fragmented and not IP header. Check for all the fields in IP header and this is a very common question, how will NAT and fragmentation work? The best way to understand a protocol is use linux commands to change networking and open packets in wireshark, and play around.

Вам также может понравиться