I'm working on porting some old K&R code to ANSI C, so I'm writing missing function prototype declarations. A lot of the function definitions have parameters with the register storage class, but I'm not sure if the register storage class specifier can be omitted in the function prototype?
With and without the register storage class specific declaration, the code compiles correctly (I tried GCC, VC++ and Watcom C). I could not find any information in the ISO/ANSI C89 standard on what is the correct way to do - is it OK if I just put the register keyword in the function definition?
int add(register int x, register int y);
int add(register int x, register int y)
{
return x+y;
}
This also builds correctly:
int add(int x, int y);
int add(register int x, register int y)
{
return x+y;
}
I want to make sure that the register storage specifier is really taken into account, according to the standard (my target is to compile using a very old compiler where this storage class specifier is important). Are both OK and it's just a question of coding style, or not?
Storage class specifiers in C language tells the compiler where to store a variable, how to store the variable, what is the initial value of the variable and life time of the variable.
A function declared with the static storage class specifier has internal linkage, which means that it may be called only within the translation unit in which it is defined. The default for a function is external linkage. The only storage class that can be specified for a function parameter is register.
The register storage class specifier indicates to the compiler that the object should be stored in a machine register. The register storage class specifier is typically specified for heavily used variables, such as a loop control variable, in the hopes of enhancing performance by minimizing access time.
The key provision is that every declaration of the function must specify a compatible type for it. That requires compatible return types, and, for declarations such as yours that contain parameter lists, compatible type for each pair of corresponding parameters.
The question then becomes whether storage-class specifiers differentiate types. They do not, though the standard says that indirectly, by omission of storage-class specifiers from its discussion of type derivation. The property specified by a storage-class specifier in an object's declaration is therefore separate from that object's type.
Moreover, C89 specifically says
The storage-class specifier in the declaration specifiers for a parameter declaration, if present, is ignored unless the declared parameter is one of the members of the parameter type list for a function definition.
(emphasis added). A function definition is a declaration accompanied by a function body, as opposed to a forward declaration, so your two codes have identical semantics.
With and without the register storage class specific declaration, the code compiles correctly (I tried gcc, VC++ and Watcom), I could not find any information in the ISO/ANSI C89 standard on what is the correct way to do, or is it ok if i just put the register keyword in the function definition?
Personally, I would be inclined to make each forward declaration identical to the declaration in the corresponding function definition. This is never wrong if the function definition itself is correct.
HOWEVER,
The register
keyword is a relic. Compilers are not obligated to make any attempt at all to actually assign register
variables to registers, and modern compilers are a lot better than humans at deciding how to assign variables to registers and otherwise to generate fast code anyway. As long as you're converting old code, I would take the opportunity to remove all appearances of the register
keyword.
C89 is obsolete. The latest version of the standard is C 2018; C 2011 is widely deployed; and C99 (also, technically, obsolete) is available almost everywhere. Perhaps there is a good reason for you to target C89, but you should strongly consider instead targeting C11 or C18, or at least C99.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With