ALX Project 0x00. C - Hello, World

ALX Project 0x00. C - Hello, World

Introduction

To be able to solve all the problems under this project, you should have a basic understanding of the following concepts:

Task 0. Preprocessor

Write a script that runs a C file through the preprocessor and saves the result into another file.

  • The C file name will be saved in the variable $CFILE

  • The output should be saved in the file c

First thing is to break down the problem in a bid to understand it:

  1. Write a bash script.

  2. Run it through the preprocessor and output the result into another file.

  3. We were also given the following hints:

    a. The C file in question has been placed in a variable called CFILE (in my example, we will call it VARIABLE)

    b. The file into which we save the output from the preprocessor is called c (we will use OUTPUTFILE ) instead of c.

    The simple solution to a task like that is as follows:

#!/bin/bash
gcc -E "$VARIABLE" -o OUTPUTFILE

Now let's break down the code:

  1. #!/bin/bash is called the shebang directive and simply tells the interpreter or program that should be used to run the code written. For a more detailed explanation check out my post on Shebang.

  2. gcc is the program that translates the code written in a high-level programming language (in this instance our C code) into machine-readable code that can be executed by a computer's processor. Note that we could have used the cpp (c preprocessor) command as well. Read more here.

  3. The "-E" option is a flag that instructs the GCC compiler to run the preprocessor stage of compilation only. Read more on the C compilation process here.

  4. "$VARIABLE" - the dollar sign ($) is how you extract the value stored in a variable so in this context, the preprocessor runs on the contents of the file or variable. The content of this file is just C code. So in sum, there is a file called VARIABLE which contains some code written in the C programming language and we extract that C code by prepending the $ sign. Also, note that while the command will work without the double quotes, I placed double quotes around the variable name. This simply ensures that the command will work correctly with file names or paths that contain spaces or special characters.

  5. The "-o" flag simply tells the compiler that all the output that was generated should but stored in a specific file called OUTPUTFILE in our case.

Task 1. Compiler

Write a script that compiles a C file but does not link.

  • The C file name will be saved in the variable $CFILE (but I will use $SOMECFILE. in my example)

  • The output file should be named the same as the C file, but with the extension .o instead of .c.

    • Example: if the C file is main.c, the output file should be main.o

This problem is similar to [Task 0**](https://anyt3k.hashnode.dev/alx-project-0x00-c-hello-world#heading-task-0-preprocessor) above so kindly check the explanation from that section. Here, the task is to halt the compilation process after the code has been compiled to object code and linking has NOT been done. If you do not understand this, a thorough explanation of the C compilation process** is given here. The command to do this is as follows:

#!/bin/bash
gcc -c "$SOMECFILE"
  1. #!/bin/bash is explained under Task 0.

  2. gcc is the compiler.

The -c option tells gcc to compile but not link the file. The output file is named based on the original C file name, with the extension changed to '.o'. By default, GCC will output object code in a file with the same name as the input file, but with the ".o" extension. So if the value of the $my_file variable is "example.c", the output file will be "example.o".

Task 2. Assembler

Write a script that generates the assembly code of a C code and saves it in an output file.

  • The C file name will be saved in the variable $CFILE ($SOMEVAR in my example)

  • The output file should be named the same as the C file, but with the extension .s instead of .c.

    • Example: if the C file is main.c, the output file should be main.s

This problem is similar the Task 0 so a similar explanation holds true. The code is as follows:

#!/bin/bash
gcc -S "$SOMEVAR"

The only new thing here is the -S flag and the .s extension. so I will focus on just those.

  • The -S option tells gcc to generate assembly code and pause the compilation process and the -o option specifies the output file name. By default, GCC will output assembly code in a file with the same name as the input file, but with the ".s" extension. So if the value of the $my_file variable is "example.c", the output file will be "example.s".

Task 3. Name

Write a script that compiles a C file and creates an executable named cisfun.(fun_var in my example)

  • The C file name will be saved in the variable $CFILE ($MYVAR in the example below).
#!/bin/bash
gcc "$MYVAR" -o fun_var

Here, the compiler is allowed to go through all the steps in the compilation, and the final output is stored in the variable fun_var.

NB: The -o option specifies the name of the output file that the compiler should generate. In this case, the output file will be named "fun_var" and it is an executable as the question suggested.

It could be a shared library, or any other type of file depending on what the program is meant to do. The actual file type and format of the output file are determined by the compiler based on the contents of the input file and the compiler options used. The file could be an executable file with no extension or it could have an extension like .exe on Windows or no extension on Unix-based systems.

Task 4. Hello, puts

Write a C program that prints exactly "Programming is like building a multilingual puzzle, followed by a new line.

  • Use the function puts

  • You are not allowed to use printf

  • Your program should end with the value 0

The problem tells us to write code that outputs a specific string. Take note that the string given starts with a " and does not end with one. With this in mind, let's look at how we can print the example string below:

  • "Programming is the best ( but we will use "ALX is the best in the example below)

We are told to only use puts and NOT printf so what is the difference between the two? The simple answer is that puts automatically appends the newline character (\n) while print does not. Read more about the differences here. Let's see an example.

#include <stdio.h>
/**
 * main - Entry point
 *
 * Description: Calls puts and recieves value returned by puts after its
 * execution.
 * Return: Always return 0 to indicate success
 */
int main(void)
{
    puts("\"ALX is the best");
    return (0);
}

Let's break down the code:

  • int main(void) - This is the prototype and it is simply the entry point of the program.

  • The second line puts("\"Programming is the best"); uses the puts function to output the message "Programming is the best to the console. The backslash before the double quote is an escape character that tells the compiler to treat the double quote as part of the string rather than the end of the string.

The third line return (0); ends the main function and returns a value of zero to the operating system, indicating that the program executed successfully.

Task 5. Hello, printf

Write a C program that prints exactly with proper grammar, but the outcome is a piece of art,, followed by a new line.

  • Use the function printf

  • You are not allowed to use the function puts

  • Your program should return 0

  • Your program should compile without warning when using the -Wall gcc option.

This problem is similar to Task 4 except that we are permitted to use printfas opposed to putsin the previous problem. I will use a similar sentence (with proper care, a dog is mans best friend,)as the one in the problem to explain.

#include <stdio.h>

/**
 * main - Entry point
 * Return: Always 0 (Success)
 */
int main(void)
{
    printf("with proper care, a dog is mans best friend,\n");
    return (0);
}

The key thing to note here is that the newline is printed by adding the sequence "\n" at the tail end. This would not be necessary had we used the puts function instead. Read on the differences between puts and printf here.

Task 6. Size is not grandeur, and territory does not make a nation

Write a C program that prints the size of various types on the computer it is compiled and run on.

  • You should produce the exact same output as in the example

  • Warnings are allowed

  • Your program should return 0

  • You might have to install the package libc6-dev-i386 on your Linux to test the -m32 gcc option

Task 7. Intel

Write a script that generates the assembly code (Intel syntax) of a C code and save it in an output file.

  • The C file name will be saved in the variable $CFILE.

  • The output file should be named the same as the C file, but with the extension .s instead of .c.

    • Example: if the C file is main.c, the output file should be main.s

This problem is similar to Task 2 except that we are asked to make sure the assembly code output has intel syntax.

Assuming you have GCC installed on your machine, you can generate the assembly code for a C file named "example.c" using the following command:

gcc -S -masm=intel example.c -o example.s

This command instructs GCC to generate the assembly code in Intel syntax ("-masm=intel") for the file "example.c" and save it in a file named "example.s" ("-o example.s").

Here's a breakdown of the options used in the command:

  • "-S": tells GCC to generate assembly code instead of object code

  • "-masm=intel": The "-masm=intel" option is a compiler flag that is used to specify the assembly language syntax to be used by the GNU Compiler Collection (GCC) when generating assembly code.

    By default, GCC uses the AT&T syntax for assembly code, which is different from the Intel syntax. The Intel syntax is used by most other assemblers, including the Microsoft Assembler (MASM). The "-masm=intel" option instructs GCC to use the Intel syntax for the generated assembly code. This can be useful if you are working with code that was originally written for MASM or another assembler that uses the Intel syntax. To use this option, you would typically include it as part of the command line arguments when invoking GCC,

  • "example.c": the name of the C file you want to compile

  • "-o example.s": specifies the output file name for the generated assembly code

You can run this command in a terminal or shell, and it will generate the assembly code for "example.c" and save it in "example.s". You can then open "example.s" with a text editor or any other tool to view the generated assembly code.

Note that the generated assembly code may not be the most optimal or efficient version, so you may need to further optimize it by hand or using other tools.

TASK 8. UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity

Write a C program that prints exactly and that piece of art is useful" - Dora Korpar, 2015-10-19, followed by a new line, to the standard error.

  • You are not allowed to use any functions listed in the NAME section of the man (3) printf or man (3) puts

  • Your program should return 1

  • Your program should compile without any warnings when using the -Wall gcc option.

#include <stdio.h>
/**
 * main- Entry point
 * @void: parameter
 * Return: 1 (success)
 **/
int main(void)
{
    fprintf(stderr, "and that piece of art is useful\" - \
Dora Korpar, 2015-10-19\n");
    return (1);
}

This is a preprocessor directive that includes the standard input/output library header file "stdio.h". This library provides functions for reading and writing data to and from files, as well as to the standard input and output streams.

/**
 * main- Entry point
 * @void: parameter
 * Return: 1 (success)
 **/

This is a documentation comment that explains the purpose of the "main" function. It states that the function is the entry point of the program and takes no arguments. It also specifies that the function returns an integer value of 1 to indicate success.

int main(void)
{
    fprintf(stderr, "and that piece of art is useful\" - \
Dora Korpar, 2015-10-19\n");
    return (1);
}

This is the implementation of the "main" function. The function uses the "fprintf" function to print the given message to the standard error stream. The message is enclosed in double quotes and includes an escaped double quote to represent the quote within the message. The backslash followed by a newline character (\n) is used to continue the message onto the next line for formatting purposes.

Finally, the function returns an integer value of 1 to indicate success. Note that the return value is not necessary for this program, as it does not interact with other programs or scripts.

SOME EXTRA NOTES ON printf(), puts(), and fprintf().

All three functions are used to print data to the standard output stream, but they differ in their specific functionality:

printf() and puts() are used to print data to the standard output stream, whereas fprintf() is used to print formatted data to a specified output stream.

fprintf() is used to print formatted data to a specified output stream, such as a file or network socket. It takes the output stream as its first argument, followed by a format string and any additional arguments that correspond to the placeholders in the format string. The output is sent to the specified output stream, rather than the standard output stream.