Artigo em Português do Brasil:
Been a while since I’ve posted here, I have already exceeded what was agreed with you, put a small article here all week under the GNU libc, but to resolve the pending here are my first small tests and reviews on Chapter 1 and 2 .
Chapter 1 as one would expect only serves as an introduction to manual and the ANSI C, but with some important information for new developers in C language and especially in the use of GCC. For example, the book considers all the examples will be presented here and in the book are compiled with the argument ‘-ansi’ which tells GCC to use the standard ANSI C.
Moreover it gives a special attention in the header files (so called ‘#include‘ statements that contains functions, structures, constants, …) citing that such policies should be included in the first lines of source code before any other statement (as he says this is not a mandatory rule but must be seen as such), he also talks about the basic difference to include a header in double quotation marks and signs of less than and greater than:
#include “file.h” It’s typically a header file that you had designed and put in your working directory.
#include <stdio.h> Pay attention to the less than sign and greater than when a header is declared in this way means that it is associated with the system and is part of any library.
note: an interesting thing that the manual says in this section is that if their functions, structures, etc (header data) is not declared at the beginning of this program may cause a loss in performance of their software.
Another relevant fact of this first section is what the manual says not expected to use reserved words, for example, never declare a variable as exit (because the exit function that exists in libC), this can cause errors in your program or get someone who is reading your code to be confused with that statement. There are several other examples which he cites as variables with ‘E’ followed by capital letters (mean error codes and should not be used, …).
Well of course this is all very basic and that is why I am writing everything very quickly and briefly tell only facts that I found interesting in this introductory chapter.
This second part is where things get interesting for those who like a little theory and many examples, from here I’ll do some tests I found interesting features in each chapter, this one in particular talks about how to handle and report to the user error code. The header responsible for the functions of interpretation error is errno.h.
volatile int errno
This variable is quite interesting because it keeps returning the error of each issue of your program, the initial value of this variable is zero, this variable can be changed asynchronously by being kind of volatile, it can be modified via signals but there is a specific signal that stores this value and restore when necessary, this value is modified every time a function returns an error. Remember that this variable should not be checked to find out where in your program error occurred.
All values returned by this variable are integers and have a statement in your header with prefix ‘E’ as EAGAIN and EFAULT, below I list three of the hundreds constants error that I found interesting quote as an example:
EACCES: Permission denied.
ENOENT: No such file or directory.
EIO: Input / Output Error.
We will now see a simple example of error trying to open a file that does not exist, in this example we listed below we will not use any error detection function but we can see that the value of the variable errno is set by the compiler after he found a error in function call.
#include #include int main (void) ( fopen ("/tmp/naoexist.txt", "r"); printf ("Return errno:%dn", errno); return 0; ) 20:14:59 tosh$ ./errno01 Return errno: 2
We could simply read the manual of function ‘fopen’ and see what gives when it returns success or error, and in an ‘if’ conditional print something like: “This file does not exist” when he returned NULL (null is the return fopen error reported in your manual).
Now let’s see an example of using two error functions of ‘errno.h‘ header that tells us exactly what happened when there was a problem in function call, the statement ‘strerror‘ returns a pointer to a string that holds the content the error message from previous function (obviously if it has returned problem, remembering that the goal of these error functions are not detect where a problem occurred, but what problem happened). And the statement ‘perror‘ returns to the standard output the message with something that you put into the function:
#include <stdio.h> #include <stdlib.h> int main (void) ( FILE *fp; char *p; if (!(fp = fopen("/tmp/noexist.txt", "r"))) ( / * First function 'strerror' * / p = (char *) strerror (errno); printf ("%sn", p); / * Second function 'perror' * / perror ("fopen"); ) return 0; ) 20:48:38 tosh $ ./errno02 No such file or directory fopen: No such file or directory
As you see we have two differents outputs but with the same error, the first output was produced by the ‘strerror‘ statement and printed by the ‘printf‘ function, and the second by the ‘perror‘ function. But and if you want to show an error differently that was showed of by standard? The function ‘error‘ can do it for you as listed below:
#include #include int main (void) ( fopen ("/tmp/noexist.txt", "r"); error (0, EACCES, "fopen"); return 0; ) 20:48:17 tosh $ ./errno03 ./errno03: fopen: Permission denied Tosh 20:48:19 $ echo $? 0
We can see two cool things here, the return code of the program was zero and the message was ‘permission denied‘. This happens because the function ‘error‘ returns the error code that you pass in the first argument and the code of message that you put in the second argument.
Well friends, its enough for today! In the next article will talk about dynamic memory allocation described in the chapter three of GNU C library. See you later!