12 interesting questions and answers about the C language

  • 2020-04-02 02:30:19
  • OfStack

This article summarizes 12 questions and answers about C language, which is very helpful to deepen the understanding of the difficulties in C language programming. Readers can refer to:

1. Gets () method

Q: the following code has a hidden problem. Can you find it?

Answer: the inconspicuous problem is the use of the gets() method. This method accepts a parameter of type string, but does not detect if the value has enough space to copy the data. So we generally use the fgets() method here to do better in the future.


#include<stdio.h>
 
int main(void)
{
  char buff[10];
  memset(buff,0,sizeof(buff));
 
  gets(buff);
 
  printf("n The buffer entered is [%s]n",buff);
 
  return 0;
}

2. Strcpy () method

Q: password protection is a very basic feature, see if you can figure out the following code ?


#include<stdio.h>
 
int main(int argc, char *argv[])
{
  int flag = 0;
  char passwd[10];
 
  memset(passwd,0,sizeof(passwd));
 
  strcpy(passwd, argv[1]);
 
  if(0 == strcmp("LinuxGeek", passwd))
  {
    flag = 1;
  }
 
  if(flag)
  {
    printf("n Password cracked n");
  }
  else
  {
    printf("n Incorrect passwd n");
 
  }
  return 0;
}

3. Return type of the main() method

Q: can the following code be compiled? If so, is there a problem implicit in this code?


#include<stdio.h>
 
void main(void)
{
  char *ptr = (char*)malloc(10);
 
  if(NULL == ptr)
  {
    printf("n Malloc failed n");
    return;
  }
  else
  {
    // Do some processing
 
    free(ptr);
  }
 
  return;
}

Answer: the answer is that the code compiles, but it leaves a warning about the return type of the main() method. The real return type of the main() method should be 'int' instead of 'void'. This is because the 'int' return type allows the program to return status values. This value is especially important if the program is attached to another application.

4. Memory leak

Q: is there a memory leak in the following code?


#include<stdio.h>
 
void main(void)
{
  char *ptr = (char*)malloc(10);
 
  if(NULL == ptr)
  {
    printf("n Malloc failed n");
    return;
  }
  else
  {
    // Do some processing
  }
 
  return;
}

Answer: well, even if the code above doesn't free up the pointer PTR, it doesn't actually cause a memory leak even if the program ends, because when the program ends, all the memory that was originally occupied is gone. But if the above code were inside the while loop that would cause serious problems

Bonus: if you need to learn more about memory leaks, you can refer to this article (link: #)

5. Free () method

Q: why does the following code crash when the user types 'freeze' but work fine when they type 'zebra'?


#include<stdio.h>
 
int main(int argc, char *argv[])
{
  char *ptr = (char*)malloc(10);
 
  if(NULL == ptr)
  {
    printf("n Malloc failed n");
    return -1;
  }
  else if(argc == 1)
  {
    printf("n Usage n");
  }
  else
  {
    memset(ptr, 0, 10);
 
    strncpy(ptr, argv[1], 9);
 
    while(*ptr != 'z')
    {
      if(*ptr == '')
        break;
      else
        ptr++;
    }
 
    if(*ptr == 'z')
    {
      printf("n String contains 'z'n");
      // Do some more processing
    }
 
    free(ptr);
  }
 
  return 0;
}

Answer: the root of the problem is that the code changed the address of the PTR pointer in the while loop. When entered as 'zebra', the while loop ends even before the first execution, so the memory address freed by free() is the one malloc() originally assigned. But when you type 'freeze', the address of the PTR record is changed in the while loop because the wrong address will be passed to the free() method causing a crash.

6. Atexit with _exit

Q: the atexit() method is not called in the following code. Do you know why?


#include<stdio.h>
 
void func(void)
{
  printf("n Cleanup function called n");
  return;
}
 
int main(void)
{
  int i = 0;
 
  atexit(func);
 
  for(;i<0xffffff;i++);
 
  _exit(0);
}

Answer: this is because the _exit() method is used. This method does not call methods associated with clearing data, such as atexit().

7. Void * and C structure

Q: can you design a method to take any type of argument and return an integer? Is there a way to pass more than one of these simultaneously?

A: A method that accepts arguments of any type looks like this:


int func(void *ptr)

If we need to pass more than one parameter, we can pass a structure that contains those parameters

8. * and ++ operators

Q: what will the following code output? Why is that?


#include<stdio.h>
 
int main(void)
{
  char *ptr = "Linux";
  printf("n [%c] n",*ptr++);
  printf("n [%c] n",*ptr);
 
  return 0;
}

A: the output above will be:

Because ++ has the same priority as *, *p TRS ++ will operate from right to left. Following this logic, ptr-+ + will be executed first and then * PTR. So the first result is L prime. Also because ++ is executed, the next printf() results in 'I'.

9. Making changes in Code segment

Q: the following code must crash while running. Can you tell me why?


#include<stdio.h>
 
int main(void)
{
  char *ptr = "Linux";
  *ptr = 'T';
 
  printf("n [%s] n", ptr);
 
  return 0;
}

Answer: this is because this line of code is trying to change the string 'Linux' stored in read-only memory by * PTR = 'T'. Of course it doesn't work that's why it crashes.

10, Process that changes its own name

Q: can you write a program that changes its name as it runs?

Answer: the following code can be done


#include<stdio.h>
 
int main(int argc, char *argv[])
{
  int i = 0;
  char buff[100];
 
  memset(buff,0,sizeof(buff));
 
  strncpy(buff, argv[0], sizeof(buff));
  memset(argv[0],0,strlen(buff));
 
  strncpy(argv[0], "NewName", 7);
 
  // Simulate a wait. Check the process
  // name at this point.
  for(;i<0xffffffff;i++);
 
  return 0;
}

11. Return address of local variable

Q: is there a problem with the following code? If so, how?


#include<stdio.h>
 
int* inc(int val)
{
 int a = val;
 a++;
 return &a;
}
 
int main(void)
{
  int a = 10;
 
  int *val = inc(a);
 
  printf("n Incremented value is equal to [%d] n", *val);
 
  return 0;
}

Answer: while the above code sometimes works well, there are serious pitfalls in method inc(). When the inc() method is executed, reusing the address of the local variable results in incalculable results. The solution is to pass the address of variable a to main().

12. Handle the printf() parameter

Q: what is the output of the following code?


#include<stdio.h>
 
int main(void)
{
  int a = 10, b = 20, c = 30;
 
  printf("n %d..%d..%d n", a+b+c, (b = b*2), (c = c*2));
 
  return 0;
}

Answer: the output will be


110..40..60

This is because the parameters are processed from right to left, and then printed from left to right.


Related articles: