sagi said:
Hello erveryone,I am a newcomer here and the word of c.
Here I have a question confused me a lot that when I read codes I
found some declaration like that:
"int regcomp(regex_t *restrict comoiled, const char *restrict
parttern, int cflags) "
or something like that
" int strnlen(const char FAR *s, int count)"
what does the "restrict" or "FAR" means?
FAR is not part of standard C. I believe that it is either a keyword or
a macro. Either way, it only works on certain systems (which don't
include any system I write programs for). You would get a better answer
than I could give you by asking in a newsgroup for the appropriate
compiler or operating system.
To understand the restrict keyword, consider the following function. It
takes as arguments a list of characters, and a string, and it adds 1 to
any character in the string which matches one of the characters in the list.
void blankchars(const char blanklist[], char string[])
{
if(blanklist == NULL || string == NULL)
return;
for( ; *blanklist; blanklist++)
{
for(size_t i=0; string
; i++)
{
if(string == *blanklist)
string++;
}
}
}
What happens if this function is called as follows? :
char alphabet[] = "abcde";
blankchars(alphabet, alphabet);
On my home computer, the result of this call will be that alphabet now
contains the string "bddff". Do you understand why?
Well, that is probably not what anyone would want the function to do. In
fact, there's no reasonable thing for the function to do when the
blanklist and the string overlap in any way.
You might think that it should check for overlap between the blanklist
and the output string. The obvious way to do this would seem to be
compare blanklist, string, and strlen(blanklist) and strlen(string).
Unfortunately, if blanklist and string do NOT overlap, then comparing
them with <, >, <=, >= or by subtracting them has behavior that is not
defined by the C standard. On many machines it will work as you might
expect, but on many real machines, it will produce erroneous results or
possibly even cause your program to abort().
You can compare pointers to different arrays for equality, and there's a
perfectly portable way to check for overlap that makes use of that fact.
Just compare a pointer to every character in one string for equality
with pointers to the starting and ending characters of the other string,
and vice versa. However, it's rather inefficient.
The simplest approach is simply to document that the function is not
guaranteed to work properly if there's any overlap between the strings
pointed at by its two arguments. This is a very popular choice, and it's
the one take by the C standard library itself in most cases like that.
However, just because you've documented that restriction, doesn't mean
that that compiler knows anything about it. Because you've decided not
to worry about overlapping arguments, you could have re-written the
innermost loop as follows:
int c = *blanklist;
for(size_t i; string; i++)
{
if(string == c)
string = ' ';
}
When there is no overlap, this code produces exactly the same result as
the original program. This is a very simple optimization, and under
other circumstances, virtually any modern compiler would perform
optimizations like this one for you, even at the lowest optimization levels.
However, in this particular circumstance, the compiler cannot perform
this optimization for you. The compiler has to generate code which will
work as required by the C standard, even if string and *blanklist
refer to the same character, and that's not the case for the optimized
version of the code. With the optimized version, blankchars(alphabet,
alphabet) would produce "fffff" (on my machine). The compiler thinks
it's important to make sure that this case produces "bddff", and will
therefore not perform the optimization. It doesn't know that you don't
care about that case.
This is where "restrict" comes in. If we change the function declaration to
void blankchars(const char restrict blanklist[], char restrict string[])
then this tells the compiler that developers and users of blankchars()
will work together to make sure that string and *blanklist never
refer to the same object. That gives the compiler permission to perform
optimizations like the one above.
The down side of 'restrict' is that, if the requirements it imposes are
violated, the behavior is undefined. It's no longer the case that we can
say that the result of calling blankchars(alphabet, alphabet) is to set
alphabet to "bddff". It is now technically possible that just about
anything could happen, including causing your program to abort.
In this particular case, it is most likely to produce "fffff", but in
more complicated cases, the problems created by the permitted
optimizations could be arbitrarily bad. However, to be fair, in those
more complicated cases, the problems would probably also be pretty bad
if the "restrict" keyword was not used.