5

I was going through some code when I encountered this in one of the source files.

int st_insert(table, key, value)
register st_table *table;
register st_data_t key;
st_data_t value;
{
    unsigned int hash_val, bin_pos;
    register st_table_entry *ptr;

    hash_val = do_hash(key, table);
    FIND_ENTRY(table, ptr, hash_val, bin_pos);

    if (ptr == 0) {
        ADD_DIRECT(table, key, value, hash_val, bin_pos);
        return 0;
    } else {
        ptr->record = value;
        return 1;
    }
}

What is this style? Is it some obscure way to declare functions? Is there some reason one might use this over normal function declarations?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
calccrypto
  • 8,583
  • 21
  • 68
  • 99
  • 3
    K&R-style. Don't use. – EOF Nov 19 '15 at 23:04
  • 3
    That is old style. (K&R style) before c89/c90. Function parameters as *register* is still weird, though. – wildplasser Nov 19 '15 at 23:05
  • It's the old style of function definitions and is now obsolete since C99. – ouah Nov 19 '15 at 23:05
  • 3
    Uhoh. This code was written around 2010... – calccrypto Nov 19 '15 at 23:06
  • 4
    @calccrypto: In that case, arrange for the author's immediate reeducation in a camp in siberia. – EOF Nov 19 '15 at 23:08
  • @wildplasser: `register` arguments are still legal in modern C. The compiler is free to ignore it and like will if the ABI does not allow it (or usese registers anyway). – too honest for this site Nov 19 '15 at 23:08
  • @Olaf: `register` doesn't have anything to do with hardware-registers, only with not taking the address of the object. – EOF Nov 19 '15 at 23:09
  • It would influence the calling convention. The caller really needs a prototype if the argument is actually passed in a register. (I can imagine this is used as an extention for embedded platforms, and maybe in kernel code and device drivers) – wildplasser Nov 19 '15 at 23:12
  • @EOF My mistake. The copyright dates go from 1996 to 2006. – calccrypto Nov 19 '15 at 23:13
  • 2010? Where did you get that from? The header shows the earliest version is from 1996 (but if I recall correctly, this was already called *old style* even almost 20 years ago). – Jongware Nov 19 '15 at 23:14
  • 4
    @EOF: Originally, `register` was definitively meant to tell the compiler to hold these variables in CPU registers. This just implied you cannot take its address. Just remember when this function definition-style was used (and when `register` was used for its original purpose). Nowadays, the side-effect is the only reason to use it, because the compiler will allocate CPU registers most times itself often better than the programmer can (although it might still take it as a hint). – too honest for this site Nov 19 '15 at 23:16
  • 1
    The linked-to code is kind of mixed style: though, bulky macros + inline functions. Plus the (IMHO) silly register arguments and old type function definitions. It appears people were afraid to touch it. But: what **is** it? Inode cache for xenix ;-? – wildplasser Nov 19 '15 at 23:26
  • @Jongware It was an estimate. I was paying more attention to the code than the date. – calccrypto Nov 19 '15 at 23:28
  • @wildplasser This is the code for OpenSM, an Infiniband controller – calccrypto Nov 19 '15 at 23:29
  • the funky do {} while() (line#299 and after) even has an error `#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\` (the final semicolon is **not** wanted!) – wildplasser Nov 19 '15 at 23:33
  • 1
    @wildplasser It does _not_ influence the calling convention, even when applied to a parameter (bear in mind, in K&R C, *all* functions were called by pushing the args on the stack, last to first; and the compiler didn't even know or care how many args the function was actually defined with; only its return type). So it means 'please copy this into a register when the function is called'. So back then it had zero effect on the calling convention. Thus IMHO it would be a dangerous idea, even in a special embedded compiler, to add that meaning. I know of no such case. – greggo Nov 19 '15 at 23:44
  • Oh my good what an ugly style!!! I hate it! – 71GA Mar 18 '21 at 09:59

1 Answers1

8

It is an old (but still valid according to the current C Standard) syntax of function definitions using an identifier list. The types of the identifies are declared after the identifier list and before the opening brace.

It is better to use functions with parameter type lists because in this case the compiler having a function prototype can check the correct list of arguments for a function call.

From the C Standard (6.9.1 Function definitions)

6 If the declarator includes an identifier list, each declaration in the declaration list shall have at least one declarator, those declarators shall declare only identifiers from the identifier list, and every identifier in the identifier list shall be declared. An identifier declared as a typedef name shall not be redeclared as a parameter. The declarations in the declaration list shall contain no storage-class specifier other than register and no initializations.

You can meet other funny constructions in old C code as for example this

memset( ( char * )p, value, n );
        ^^^^^^^^^^  

because type void was introduced later.

Jongware
  • 22,200
  • 8
  • 54
  • 100
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Vlad, do you have a date for the "later" addition of `void`? My dabbling with C goes back to roundabout the late 80s, and I clearly recall having difficulty envisioning a 'typeless variable type' (as I interpreted it then). – Jongware Nov 19 '15 at 23:33
  • @Jongware No, I have not but if I am not mistaken it is Straustrup that suggested the type void. – Vlad from Moscow Nov 19 '15 at 23:35
  • 1
    IIRC void and void* were introcuced in K&R2 /c89/c90/ansi/iso (inspired by C++) A few compilers already had it as an extention. – wildplasser Nov 19 '15 at 23:35
  • Yes, 'void' was in ANSI C, I recall this being discussed in net.lang.c around 1986 or 87 or so, and wasn't in e.g. PCC which was in fairly common use then. – greggo Nov 19 '15 at 23:47
  • @wildplasser: that resonates nicely with my recollection. First time I ever laid eyes on C was for my 3rd computer: an Atari ST. So yeah, must have been late 80s or possibly very early 90s. When I got started with Turbo C (the all-in compiler-and-linker, distinct dark blue editor and a menu bar), that had both `void` and the current style of function declarations. – Jongware Nov 19 '15 at 23:47