简体   繁体   中英

Variable declaration after function's argument list

I stumpled upon a C code, where variables seem to be declared after the argument list of a function. I did not know that this was possible.

In the code, int r and int *a are declared right after the argument list of arr2int . How does this affect the local variables a and r of arr2int ?

The actual reason why I want to understand the code is because if I let it run on my linux x86 a[1] = 1 at //MARKER when arr2int ist called the fist time.

But if I let it run ona an ARM-based omap4 dev board a[1]=0 and I dont know why there is a difference.

Could someone comment on this please?

long arr2int(a,r)
int r;
int *a;
{
   int i;
   long mul, result = 0, temp;

   //MARKER
   for (i=1; i<=r; i++) {
      mul = 1;
      temp = a[i]-1;
      while (temp--)
         mul = mul << 1;
      result += mul;
   }
   return(result);
}

And the calling method:

void generateEncodingTable(){
    register int i,j;
    long temp;
    int seed = 133757;

    printf("\n[I] - Generating Encoding Table\n");
    for (pattern = 0; pattern < 4096; pattern++) {
        temp = pattern << 11;          /* multiply information by X^{11} */
        encoding_table[pattern] = temp + get_syndrome(temp);/* add redundancy */
    }

    decoding_table[0] = 0;
    decoding_table[1] = 1;
    temp = 1; 
    for (i=2; i<= 23; i++) {
        temp *= 2;
        decoding_table[get_syndrome(temp)] = temp;
    }

    a[1] = 1; a[2] = 2;

    temp = arr2int(a,2);
    decoding_table[get_syndrome(temp)] = temp;
    for (i=1; i<253; i++) {
        nextcomb(23,2,a);
        temp = arr2int(a,2);
    decoding_table[get_syndrome(temp)] = temp;
    }

    a[1] = 1; a[2] = 2; a[3] = 3;
    temp = arr2int(a,3);
    decoding_table[get_syndrome(temp)] = temp;
    for (i=1; i<1771; i++) {
        nextcomb(23,3,a);
        temp = arr2int(a,3);
        decoding_table[get_syndrome(temp)] = temp;
    }
}

This is an old notation known as K & R (Kernighan & Ritchie, after Brian Kernighan and Dennis Ritchie) Notation for declaring the functions. If your compiler supports it, you can use it and it is same as declaring the function with ANSI notation.

As mention by others, this is an early style of function coding.

Following is a pitfall of that style. Be aware there is no type checking on passed parameters. It may explain your run time differences.

Say you declare a function

int foo(a,b,c);

All the compiler sees at that point is a function named "foo" taking 3 arguments and returning an int . Thus usage checking is limited to that.

Let's assume sizeof(short) < sizeof(int) < sizeof(long) and the function is defined as

int foo(a,b,c)
  int a;
  long b;
  int c;
{ /* code body */ }

Notice the following usage of foo

int d,e,f;
d = foo(1,2L,3);
e = foo((short)1,2L,3);
f = foo(1,2,3);

The first usages works fine, the right size integers are passed to foo .
The 2nd usages also works fine. The first argument is promoted to int size before the call, much like printf("%d", (short)2) promotes (short)2 to int before passing to printf() .
The 3rd is a problem as the compiler does not know the second argument needs to be long . Thus the data passed to foo is not passed correctly. --> UB

This is an old C syntax. If your compiler can swallow it then it should work the same as if you have declared the functions the normal, ANSI way.

This is K&R C, ie, the C language described by the first edition of The C Programming Language by Brian Kernighan and Dennis Ritchie. The second edition has turned to ANSI C(C89).

You shoul always use ANSI C style:

Rationale for International Standard - Programming Languages C 6.11.6 Function declarators

The characterization as obsolescent of the use ofthe “old style” function declarations and definitions, that is, the traditional style not using prototypes, signals the Committee's intent that the new prototype style should eventually replace the old style.

The gist of this case is that the new syntax addresses some of the most glaring weaknesses of the language defined in K&R, that the new style is superior to the old style on every count.

It is just a way of declaring types of function parameters:

void func (first_param, second_param)
int first_param;
int second_param;
{
 // ...
}

is equal to

void func (int first_param, int second_param)
{
 // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM