Hello World! how it should be in C on Linux
So many novice programmers think they know how to write Hello World. Naturally, with this example, after all, most textbooks begin.
And let's see how this is done.
Typically, in a C tutorial, this program looks something like this:
The first thing we see here is that launching this program will never know how it was executed. So you need to add a return code. The printf function, as we know, returns the number of characters printed. Or, if there was an error, a negative value. Given this, the program will look something like this: Dear readers, forgive me, but then I will add many corrections to it at once, otherwise this post will grow so that nobody reads it to the end. Whoever wants to can correct their code every time the next paragraph ends. And that will be right. This is the best way to understand what I want to say with this post. Now let's think a little further.
Is it really a critical mistake that we were not able to immediately print the entire message? Of course not! After all, it’s not always what we run that writes lines to the console. And there is a difference. We are now writing under Linux (didn’t you forget about this?), But it is very different. And the output can be sent, for example, to some strange device that simply cannot write more than one character at a time. So printf will not be enough for us; you need to write until it works out.
Now, what if we don’t have “Hello World! \ N”? And if there is a line like “Use% s to print string”? We cannot use printf here if we want this code to be used elsewhere. But we want this, otherwise what kind of programmers are we?
And by the way, what does error mean for printf ()? Anything, we don’t know anything about it until we get into the library code.
So apparently we will have to use something below the level. What do we have then? puts ()? Moreover, we don’t know anything about errors. Apparently you need to use write ().
So what do we get at the moment? We use write (). If not everything is written out, we continue from where we left off. We handle errors.
By the way, what about errors? You already looked at man 2 write? Did not look? But in vain. After all, if the write () function returned a negative value, this does not necessarily mean that we are out of luck. Let's take a look at man. And if we look carefully, we will see there that a negative value can be returned to us if the call was interrupted by a signal. (You do not know what signals are? Find out urgently if you want to write under Linux). But this is not necessarily a mistake. What if the user just at that moment changed some configuration file and sent all processes SIGHUP, which usually means "reconfigure"?
And at this moment I - surprise surprise - will show the code of what we should have got by this moment.
This is how the correct hello world should look like in my opinion. Maybe I forgot to process something somewhere. In this case, it is better not to minus immediately, but correct in the comments.
If the habrazhiteli likes this article, there will be articles on the topic "how textbooks differ from real life."
______________________
And let's see how this is done.
Typically, in a C tutorial, this program looks something like this:
#include <stdio.h>
void main()
{
printf("Hello world\n");
}
The first thing we see here is that launching this program will never know how it was executed. So you need to add a return code. The printf function, as we know, returns the number of characters printed. Or, if there was an error, a negative value. Given this, the program will look something like this: Dear readers, forgive me, but then I will add many corrections to it at once, otherwise this post will grow so that nobody reads it to the end. Whoever wants to can correct their code every time the next paragraph ends. And that will be right. This is the best way to understand what I want to say with this post. Now let's think a little further.
#include <stdio.h>
#include <string.h>
int main()
{
const char * msg = "Hello world!\n";
int printf_res = printf(msg);
if (printf_res < strlen(msg))
{
return 1;
} else {
return 0;
}
}
Is it really a critical mistake that we were not able to immediately print the entire message? Of course not! After all, it’s not always what we run that writes lines to the console. And there is a difference. We are now writing under Linux (didn’t you forget about this?), But it is very different. And the output can be sent, for example, to some strange device that simply cannot write more than one character at a time. So printf will not be enough for us; you need to write until it works out.
Now, what if we don’t have “Hello World! \ N”? And if there is a line like “Use% s to print string”? We cannot use printf here if we want this code to be used elsewhere. But we want this, otherwise what kind of programmers are we?
And by the way, what does error mean for printf ()? Anything, we don’t know anything about it until we get into the library code.
So apparently we will have to use something below the level. What do we have then? puts ()? Moreover, we don’t know anything about errors. Apparently you need to use write ().
So what do we get at the moment? We use write (). If not everything is written out, we continue from where we left off. We handle errors.
By the way, what about errors? You already looked at man 2 write? Did not look? But in vain. After all, if the write () function returned a negative value, this does not necessarily mean that we are out of luck. Let's take a look at man. And if we look carefully, we will see there that a negative value can be returned to us if the call was interrupted by a signal. (You do not know what signals are? Find out urgently if you want to write under Linux). But this is not necessarily a mistake. What if the user just at that moment changed some configuration file and sent all processes SIGHUP, which usually means "reconfigure"?
And at this moment I - surprise surprise - will show the code of what we should have got by this moment.
#include <unistd.h>
#include <string.h>
#include <errno.h>
int main()
{
const char * const msg = "Hello World!\n";
const char * begin = msg;
const char * const end = begin + strlen(msg);
while (begin < end)
{
size_t remaining = end - begin;
ssize_t res = write(STDOUT_FILENO, begin, remaining);
if (res >= 0)
{
begin += res;
continue; // Let's send the remaining part of this message
}
if (EINTR == errno)
{
continue; // It's just a signal, try again
}
return 1; // It's a real error
}
return 0; // OK! Let's celebrate and drink some beer!
}
This is how the correct hello world should look like in my opinion. Maybe I forgot to process something somewhere. In this case, it is better not to minus immediately, but correct in the comments.
If the habrazhiteli likes this article, there will be articles on the topic "how textbooks differ from real life."
______________________