C

Overview of C Language

C is a structured programming language developed by Dennis Ritchie in 1973 at Bell Laboratories. It is one of the most popular computer languages today because of its structure, high-level abstraction, machine independent feature etc. C language was developed to write the UNIX operating system, hence it is strongly associated with UNIX, which is one of the most popular network operating system in use today and heart of internet data superhighway.

History of C language

C language has evolved from three different structured language ALGOL, BCPL and B Language. It uses many concepts from these languages while introduced many new concepts such as datatypes, struct, pointer etc. In 1988, the language was formalised by American National Standard Institute(ANSI). In 1990, a version of C language was approved by the International Standard Organisation(ISO) and that version of C is also referred to as C89.

Evolution of c language
The idea behind creating C language was to create an easy language which requires a simple compiler and enables programmers to efficiently interact with the machine/system, just like machine instructions.


Why C Language is so popular?

C language is a very good language to introduce yourself to the programming world, as it is a simple procedural language which is capable of doing wonders.
Programs written in C language takes very less time to execute and almost executes at the speed of assembly language instructions.
Initially C language was mainly used for writing system level programs, like designing operating systems, but there are other applications as well which can be very well designed and developed using C language, like Text Editors, Compilers, Network Drivers etc.

Latest Version of C

The current latest version of C language is C11, which was introduced in 2011. It is supported by all the standard C language compilers.
Many new features have been introduced in this version and an overall attempt to improve compatibility of the C language with C++ language has been made. We will learn about the C11edition, once we are done with learning C language, towards the end of this tutorial series.


Beginning with C programming:
  1. Structure of a C program
    After the above discussion, we can formally assess the structure of a C program. By structure, it is meant that any program can be written in this structure only. Writing a C program in any other structure will hence lead to a Compilation Error.
    The structure of a C program is as follows:
    The components of the above structure are:
    1. Header Files Inclusion: The first and foremost component is the inclusion of the Header files in a C program.
      A header file is a file with extension .h which contains C function declarations and macro definitions to be shared between several source files.
      Some of C Header files:
      • stddef.h – Defines several useful types and macros.
      • stdint.h – Defines exact width integer types.
      • stdio.h – Defines core input and output functions
      • stdlib.h – Defines numeric conversion functions, pseudo-random network generator, memory allocation
      • string.h – Defines string handling functions
      • math.h – Defines common mathematical functions
      Syntax to include a header file in C:
      #include <(header_file_name).h>
      
    2. Main Method Declaration: The next part of a C program is to declare the main() function. The syntax to declare the main function is:
      Syntax to Declare main method:
      int main()
      {}
      
    3. Variable Declaration: The next part of any C program is the variable declaration. It refers to the variables that are to be used in the function. Please note that in C program, no variable can be used without being declared. Also in a C program, the variables are to be declared before any operation in the function.
      Example:
      int main()
      {
          int a;
      .
      .
      
    4. Body: Body of a function in C program, refers to the operations that are performed in the functions. It can be anything like manipulations, searching, sorting, printing, etc.
      Example:
      int main()
      {
          int a;
      
          printf("%d", a);
      .
      .
      
    5. Return Statement: The last part in any C program is the return statement. The return statement refers to the returning of the values from a function. This return statement and return value depend upon the return type of the function. For example, if the return type is void, then there will be no return statement. In any other case, there will be a return statement and the return value will be of the type of the specified return type.
      Example:
      int main()
      {
          int a;
      
          printf("%d", a);
      
          return 0;
      }
      
  2. Writing first program:
    Following is first program in C

    #include <stdio.h>
    int main(void)
    {
        printf("GeeksQuiz");
        return 0;
    }
    Let us analyze the program line by line.
    Line 1: [ #include <stdio.h> ] In a C program, all lines that start with are processed by preprocessor which is a program invoked by the compiler. In a very basic term, preprocessor takes a C program and produces another C program. The produced program has no lines starting with #, all such lines are processed by the preprocessor. In the above example, preprocessor copies the preprocessed code of stdio.h to our file. The .h files are called header files in C. These header files generally contain declaration of functions. We need stdio.h for the function printf() used in the program.
    Line 2 [ int main(void) ] There must to be starting point from where execution of compiled C program begins. In C, the execution typically begins with first line of main(). The void written in brackets indicates that the main doesn’t take any parameter (See this for more details). main() can be written to take parameters also. We will be covering that in future posts.
    The int written before main indicates return type of main(). The value returned by main indicates status of program termination. See this post for more details on return type.
    Line 3 and 6: [ { and } ] In C language, a pair of curly brackets define a scope and mainly used in functions and control statements like if, else, loops. All functions must start and end with curly brackets.
    Line 4 [ printf(“GeeksQuiz”); ] printf() is a standard library function to print something on standard output. The semicolon at the end of printf indicates line termination. In C, semicolon is always used to indicate end of statement.
    Line 5 [ return 0; ] The return statement returns the value from main(). The returned value may be used by operating system to know termination status of your program. The value 0 typically means successful termination.




What does main() return in C and C++?


C
According to coding standards, a good return program must exit the main function with 0. Although we are using void main() in C, In which we have not suppose to write any kind of written statement but that doesn’t mean that C code doesn’t require 0 as exit code. Let’s see one example to clear our thinking about need of return 0 statement in our code.
Example #1 :




#include <stdio.h>
  
void main()
{
  
    // This code will run properly
    // but in the end,
    // it will demand an exit code.
    printf("It works fine");
}
Output:
It works fine
Runtime Error:
NZEC
As we can see in the output the compiler throws a runtime error NZEC, Which means that Non Zero Exit Code. That means that our main program exited with non zero exiting code so if we want to be a developer than we make these small things in our mind.
Correct Code for C :




#include <stdio.h>
  
int main()
{
  
    // This code will run properly
    // but in the end,
    // it will demand an exit code.
    printf("This is correct output");
    return 0;
}
Output:
This is correct output
Note: Returning value other than zero will throw the same runtime error. So make sure our code return only 0.
Example #2 :




#include <stdio.h>
  
int main()
{
  
    printf("GeeksforGeeks");
    return "gfg";
}
Output:
It works fine
Runtime Error:
NZEC
Correct Code for C :




#include <stdio.h>
  
int main()
{
  
    printf("GeeksforGeeks");
    return 0;
}
Output:
GeeksforGeeks
C++
In case of C++, We are not able to use void keyword with our main() function according to coding namespace standards that’s why we only intend to use int keyword only with main function in C++. Let’s see some examples to justify these statements.
Example #3 :




#include <iostream>
using namespace std;
  
void main()
{
    cout << "GeeksforGeeks";
}
Compile Errors:
prog.cpp:4:11: error: '::main' must return 'int'
 void main()
           ^
Correct Code for C++ :



#include <iostream>
using namespace std;
  
int main()
{
    cout << "GeeksforGeeks";
    return 0;
}
Output:
GeeksforGeeks
Example #4 :




#include <iostream>
using namespace std;
  
char main()
{
    cout << "GeeksforGeeks";
    return "gfg";
}
Compile Errors:
prog.cpp:4:11: error: '::main' must return 'int'
 char main()
           ^
prog.cpp: In function 'int main()':
prog.cpp:7:9: error: invalid conversion from 'const char*' to 'int' [-fpermissive]
  return "gfg";
         ^
Correct Code for C++ :





#include <iostream>
using namespace std;
  
int main()
{
    cout << "GeeksforGeeks";
    return 0;
}












Why to use fgets() over scanf() in C?


Any time you use an *f function, whether it be printfscanf, or their derivatives (fprintf, fscanf, etc…), you are doing more things than you might realize. Not only are you reading (or writing) something, but-and here’s the problem- you are interpreting it. The format string can be thought of as kind of an ‘eval’ function like you would see if you program in Lisp. So the problem with simply reading input from the user and echoing it back out is that a malevolent actor can simply insert a function pointer or executable code and voila, you are no longer in control.
Advantage of using scanf():
The user doesn’t need to know the size of the stack, which is the starter code is one-hundred bytes. That’s kind of good, although anyone can just sit there trying longer and longer input strings until BufferOverflow error occur. Ideally, you would just write a script that automatically tries increasing string sizes and reads the exit code of the program. Once it detects an error, you simply work your way back to a close estimate of the stack. Any modern operating system using memory address randomization to make the whole process of hijacking an application harder, but it’s by no means impossible.
fgets() over scanf():
fgets function is short for file-get-string. Remember that files can be pretty much anything on *nix systems (sockets, streams, or actual files), so we can use it to read from standard input, which again, is also technically a file. This also makes our program more robust, because as mentioned in the source, simply adjust the code to read from the command line, a file, or stdin, without much trouble.
Crucially, the fgets function also allows us to specify a specific buffer length, thereby disallowing any buffer overflow attacks. If you look at the full code below, you’ll notice that a default buffer size has been defined as a macro. Remember that C can’t use ‘const int’ variables to initialize an array properly. You can hack it using variable-length arrays (VLA’s), but it’s not ideal, and I strongly recommend against it. So while in C++ we would normally use literally anything else, here we do use preprocessor macros, but keep in mind that C and C++ have vastly different capabilities when it comes to their static type checking, namely that C++ is good over C. Hence fgets() method can actually Handle Errors during I/O.
So the code to actually read the user input is as follows:




char* inputBuffer = malloc(sizeof(char) * DEFAULT_BUFFER_SIZE);
memset(inputBuffer, NUL, DEFAULT_BUFFER_SIZE);
  
char* result = NULL;
  
while (result == NULL) {
    result = fgets(inputBuffer, DEFAULT_BUFFER_SIZE, stdin);
  
    if (inputBuffer[strlen(inputBuffer) - 1] != '\n') {
        ErrorInputStringTooLong();
  
        // Since 'result' is the canary
        // we are using to notify of a failure
        // in execution, set it to NULL, to indicate an error.
        // This is a useful value because
        // if for some reason the fgets f/nction were
        // to fail, the return value would also be NULL.
  
        result = NULL;
    }
}
As expected, we dynamically allocate a buffer of predetermined size. Dynamically allocating it as opposed to stack-allocating it gives us another layer of protection against stack smashing.
Note: We are explicitly zeroing out the memory in the inputBuffer. C does nothing for you, and malloc is no exception. The call to malloc returns a pointer to the first memory cell of the requested memory, but the values in every single one of those cells are unchanged from before the call. For all intents and purposes, they are garbage, so we zero them out. Note also that by zeroing out, we are automatically giving ourselves the null terminator, although the fgets function does actually append a null to the end of the input string, provided there is enough room in the buffer.
When the user inputs too long string:
You’ll notice that I check to make sure the last read value was not a new line. If that is true, this means that the user passed in an input string that was too long. To fix this, we need to set our ‘result’ variable to NULL so we cycle through the loop again, but we also need to clear out the input buffer. Otherwise, the program will simply read from the old input, which has not yet been used, rather than prompting the user for additional input. To handle this, I supply two additional functions.



static inline void ErrorInputStringTooLong()
{
  
    // NOTE: Print to stderr, not to stdout.
    fprintf(stderr, "[ERROR]: The input was too long, please try again.\n");
  
    // Having notified the user,
    // clear the input buffer and return.
    ClearInputBuffer();
}
  
static inline void ClearInputBuffer()
{
  
    // This variable is merely here to munch the garbage out of the input
    // buffer. As long as the input buffer's current character is not either
    // a new line character or the end of input, keep reading characters. This
    // seems to be the only portable way of clearing the input buffer.
    char c = NUL;
  
    while ((c = getchar()) != '\n' && c != EOF) {
        // Do nothing until input buffer fully flushed.
    }
}
Related Posts Plugin for WordPress, Blogger...