andrew@teletron.UUCP (Andrew Scott) (04/14/88)
In article <7667@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes: > In article <5980@utcsri.UUCP> flaps@utcsri.UUCP (Alan J Rosenthal) writes: > >In C it is permissible to call any function (including > >user-defined ones) with the wrong number of arguments, so long as any > >arguments not actually passed are not accessed by the function being > >called. > > Not true in general. If you read Dennis's anti-noalias diatribe, > near the end you may recall that he identified two botches in original > C, one of which was that printf()-like functions existed without > adequate language support. The reason for the ,... approach of ANSI > C is to provide adequate language support for variadic arguments. I am working on a bit of code in which I call a vectored function. The code to invoke the vector goes something like this: void (*vector)(); int arg; (*vector)(arg); The integer argument is available to the function if necessary; sometimes the vectored function doesn't need the argument. Now, a question related to the above comments. Is the following code "bad"? That is, should I re-work it so that all possible functions assigned to the vector have exactly one integer argument, as to be consistent with the vector call? void funcA(arg) int arg; { /* do something */ } void funcB() { /* do something else */ } ... vector = funcA; /* this is fine */ vector = funcB; /* is this? */ I'm hoping that I can leave it as it is, because funcA() and funcB() are library functions, and I wouldn't want to have kludgey function argument interfaces with unused arguments, etc. Also, I have a totally unrelated question. In making a library of functions, I have run into a couple of problems with the argument interface to some func- tions. Specifically, suppose one (integer) argument is range limited to values in the range 0..1000. Should the argument be of type short, to emphasize the range of the argument? Or, should I use ints everywhere and simply document the range of acceptable argument values. How about function return values? If the value is also range limited, should I use a smaller type or just docu- ment the range of return values so that a user of the function can cast it into a smaller type for storage purposes if desired. I was looking to UNIX libraries for inspiration; the aproach there seems to be "use int for everything except use long for large values". Thanks. -- Andrew Scott andrew@teletron.uucp or ..alberta!teletron!andrew
gwyn@brl-smoke.ARPA (Doug Gwyn ) (04/16/88)
In article <253@teletron.UUCP> andrew@teletron.UUCP (Andrew Scott) writes: > (*vector)(arg); > void funcA(arg) > void funcB() For maximal portability, your functions all need to have identical interfaces, either precisely the same number and types of arguments and return value, or all variadic arguments (in which case there must still be at least one fixed "anchor" argument of the same type). On a large number of architectures, though, you can get away with your current approach. >in the range 0..1000. Should the argument be of type short, to emphasize the >range of the argument? Or, should I use ints everywhere and simply document >the range of acceptable argument values. How about function return values? The main reason most existing functions use int is that that was the type to which all smaller integral types were widened at the function interface. This widening is not required for ANSI C when prototypes are used. The best style would be to use the appropriate type AND document the interface. The safest thing to do is to use int anyway, because some compilers may incorrectly handle other function definitions (they aren't supposed to mishandle these, but it's been known to happen).
flaps@dgp.toronto.edu (Alan J Rosenthal) (04/17/88)
In article <253@teletron.UUCP> andrew@teletron.UUCP (Andrew Scott) writes: > void (*vector)(); > int arg; > > (*vector)(arg); > ... [ possible values of `vector' are the following two functions: ] > > void funcA(arg) > int arg; > { > /* do something */ > } > > void funcB() > { > /* do something else */ > } > ... >should I re-work it so that all possible functions assigned to the >vector have exactly one integer argument, as to be consistent with the >vector call? I argue that as is it is fine K&R C (if you like, "pre-ansi C"). Others here have recently disagreed with me. It definitely is invalid ANSI C and should be re-worked as you say. You may also want to change the declaration of vector to something more like "void (*vector)(int);". >Also, I have a totally unrelated question... >Suppose one (integer) argument is limited to values in the range >0..1000. Should the argument be of type short, to emphasize the range >of the argument? Or should I use ints everywhere and simply document >the range of acceptable argument values? How about function return >values? The argument is not of type short. If you examine the default arithmetic promotions, you will see that shorts in an expression become ints. Therefore it is impossible to actually pass a short, since the mention of a short is an int-valued, not short-valued, expression.[1] In other words, "SHOULD the argument be of type short" is not the question. [ Also, you would still have to document the range limitation, as ``short'' allows -32768 to 32767, not just 0 to 1000. ] Unfortunately, compilers do not give an error message for a declaration such as int f(x) short x; { ... } In fact, K&R, and all current practice, makes it quite clear that the short declaration is simply rewritten to be an int declaration. (The same behaviour happens for array formal declarations, which are rewritten as pointer declarations due to the conversion of array names to pointers in expressions.) I think that this rewriting is bizarre, but some people take advantage of it for "comment" purposes. You may choose to use "short" for this purpose in your functions, but I would recommend against it as this bizarre rewriting can cause some strange facts. For example, within the function `f' as defined above, the call ``scanf("%hd",&x)'' would be invalid as x is not a short, it is an int. Now as for function return values, the situation is not quite the same. For these I would argue for using int rather than char or short for the same reason I would argue against using char or short for single variables (i.e. when they're not part of a larger object like an array). This is simply that since they keep getting converted to ints for calculations, it really isn't helpful to merely store them as smaller objects. In the case of function return values which are probably just in a register somewhere anyway, the advantage then becomes zero and the penalty remains non-zero. ajr -- [1] In ANSI-compatible compilers it will be possible to pass shorts and chars, by using the Pascal-style declarations. This is used in some of the library functions. Obviously, some people consider this advantageous. I personally can only see the advantage on 8-bit machines. -- Make: Don't know how to keep up with all the new features. Stop.