Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Params -> local vars? (http://www.velocityreviews.com/forums/t948786-params-local-vars.html)

Jon Howson 07-30-2012 07:35 PM

Params -> local vars?
 
Hello

I was reading thru some (yellowing!) mimeographed introductory notes on C
and I found code like the below.

main(argc,argv)
int argc;
char *argv[];
{
char *malloc();
char *strcpy();
int puts();
void free();

char *s;
if(argc>1 &&(s=malloc(8+strlen(argv[1])))){
strcpy(s,"Hello, ");
strcpy(s+7,argv[1]);
puts(s);
free(s);
}else{
puts("Program failed, unknown error");
}
}

I'm trying to work out what's happening. At the start of the function, I
guess the parameters are being converted into local variables, maybe a
way to get pass-by-value in C?

Also what is the advantage of declaring the string and memory functions
locally to the function?

Cheers
Jon

Eric Sosman 07-30-2012 07:54 PM

Re: Params -> local vars?
 
On 7/30/2012 3:35 PM, Jon Howson wrote:
> Hello
>
> I was reading thru some (yellowing!) mimeographed introductory notes on C
> and I found code like the below.
>
> main(argc,argv)
> int argc;
> char *argv[];
> {
> char *malloc();
> char *strcpy();
> int puts();
> void free();
>
> char *s;
> if(argc>1 &&(s=malloc(8+strlen(argv[1])))){
> strcpy(s,"Hello, ");
> strcpy(s+7,argv[1]);
> puts(s);
> free(s);
> }else{
> puts("Program failed, unknown error");
> }
> }
>
> I'm trying to work out what's happening. At the start of the function, I
> guess the parameters are being converted into local variables, maybe a
> way to get pass-by-value in C?


It's the original "K&R style" way of defining functions and
function parameters. In this style, the names of the parameters
are separated from their types: The first line lists the names,
in order, and the lines before the opening `{' "complete" the
picture by filling in the missing details: types and perhaps
qualifiers.

Modern C still supports K&R style in the name of backward
compatibility, but it's been obsolete since C89/C90 compilers
became generally available some two decades ago. In a way, it's
a good sign that you didn't know about this style; it shows that
progress is indeed taking place!

> Also what is the advantage of declaring the string and memory functions
> locally to the function?


None; it's an anti-advantage. In the long-gone Days of Yore
there was no universally-available header declaring malloc() and
free() -- some implementations provided <malloc.h>, some didn't.
Also, there was no universal header for the string functions --
some implementations used <string.h> and some used <strings.h>.
In those days there might have been a small advantage in declaring
those functions yourself, so you didn't have to worry about them
being in different (or no!) places on different systems. (Note also
that malloc() is declared as returning a `char*' -- K&R C had no
`void*'.)

But there's never been a good reason to write a free-hand
declaration of puts()! The <stdio.h> header has been around since
a microsecond after the Big Bang, and the right way to declare the
I/O functions has always been `#include <stdio.h>'.

Those old notes may have value, but only on Antiques Road Show.

--
Eric Sosman
esosman@ieee-dot-org.invalid

Stefan Ram 07-30-2012 07:59 PM

Re: Params -> local vars?
 
Jon Howson <nospam@nospam.com> writes:
>main(argc,argv)
> int argc;
> char *argv[];


This is an older variant of the C language,
that is usually not used today to write new code in.

>I'm trying to work out what's happening.


If your »introductory notes on C« do not explain this,
try other tutorials or textbooks, possibly, describing
a more recent C version.


James Kuyper 07-30-2012 08:00 PM

Re: Params -> local vars?
 
On 07/30/2012 03:35 PM, Jon Howson wrote:
> Hello
>
> I was reading thru some (yellowing!) mimeographed introductory notes on C
> and I found code like the below.
>
> main(argc,argv)
> int argc;
> char *argv[];
> {
> char *malloc();
> char *strcpy();
> int puts();
> void free();
>
> char *s;
> if(argc>1 &&(s=malloc(8+strlen(argv[1])))){
> strcpy(s,"Hello, ");
> strcpy(s+7,argv[1]);
> puts(s);
> free(s);
> }else{
> puts("Program failed, unknown error");
> }
> }
>
> I'm trying to work out what's happening. At the start of the function, I
> guess the parameters are being converted into local variables, maybe a
> way to get pass-by-value in C?


No - that's a non-prototyped function definition. They're still
supported by the C standard, but they've been obsolete ever since the
introduction of function prototypes in C90. Function prototypes turn on
various mandatory diagnostics, but as far as the actual behavior of the
code, that declaration is equivalent to:

main(int argc, char *argv[])

Note that no return type is specified. This used to be permitted; the
function was implicitly declared as returning an 'int'. However,
"implicit int" has not been supported since C99.

> Also what is the advantage of declaring the string and memory functions
> locally to the function?


You are allowed to provide your own declaration of some standard library
functions, so long as it is compatible with the correct declaration.
However, it's always a bad idea, even when permitted. You're much better
off #including the appropriate standard headers. In this case, those are
strings.h, stdio.h, and stdlib.h.

The advantage is very small, or possibly even negative: it restricts the
scope of those declarations to the body of main(). This allows
definition of identifiers with the same name and a different meaning
outside of main(), but that would still only work if they did not have
external linkage.

One disadvantage is that a declarations may become incorrect, even if it
originally was correct. That is in fact the case in this code. At one
time, before the first standard, malloc() returned a char*. However,
since the first standard malloc() has returned a void*. However, since
char* and void* are required to have the same representation and
alignment requirements, they are intended to be equivalent for this kind
of use; it would take a pretty perverse (but still fully conforming)
implementation of C for that to be a real problem.

Stephen Sprunk 07-30-2012 08:09 PM

Re: Params -> local vars?
 
On 30-Jul-12 14:35, Jon Howson wrote:
> I was reading thru some (yellowing!) mimeographed introductory notes on C
> and I found code like the below.
>
> main(argc,argv)
> int argc;
> char *argv[];
> {
> char *malloc();
> char *strcpy();
> int puts();
> void free();
>
> char *s;
> if(argc>1 &&(s=malloc(8+strlen(argv[1])))){
> strcpy(s,"Hello, ");
> strcpy(s+7,argv[1]);
> puts(s);
> free(s);
> }else{
> puts("Program failed, unknown error");
> }
> }
>
> I'm trying to work out what's happening. At the start of the function, I
> guess the parameters are being converted into local variables, maybe a
> way to get pass-by-value in C?
>
> Also what is the advantage of declaring the string and memory functions
> locally to the function?


This is K&R C, which had a different syntax for arguments and no
standard headers. To restate it in ANSI C:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
char *s;

if (argc>1 && (s = malloc(strlen(argv[1]) + 8))) {
strcpy(s, "Hello, ");
strcpy(s+7, argv[1]);
puts(s);
free(s);
} else {
puts("Program failed, unknown error");
}
}

A modern coder would just use printf(), but perhaps that hadn't been
taught yet or would have obscured what the text was trying to teach
about string manipulation--or printf() was considered excessive for such
a trivial task on the day's limited machines.

Unless you're interested in software archaeology, I would recommend you
discard any text that uses K&R C, which has been obsolete since ANSI C
was published in 1989.

S

--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking

Keith Thompson 07-30-2012 08:49 PM

Re: Params -> local vars?
 
Jon Howson <nospam@nospam.com> writes:
> I was reading thru some (yellowing!) mimeographed introductory notes on C
> and I found code like the below.
>
> main(argc,argv)
> int argc;
> char *argv[];


This is an old-style function definition. It was the only form
available before the 1989 ANSI C standard introduced prototypes
(borrowed from C++). It's still legal -- except for the omission of the
return type of main, which has been invalid since C99.

The modern equivalent is:

int main(int argc, char *argv[]) { ... }

which has the advantage that it makes the parameter types visible to
callers (which is typically less relevant for main than for other
functions).

> {
> char *malloc();
> char *strcpy();
> int puts();
> void free();
>
> char *s;
> if(argc>1 &&(s=malloc(8+strlen(argv[1])))){
> strcpy(s,"Hello, ");
> strcpy(s+7,argv[1]);
> puts(s);
> free(s);
> }else{
> puts("Program failed, unknown error");
> }
> }
>
> I'm trying to work out what's happening. At the start of the function, I
> guess the parameters are being converted into local variables, maybe a
> way to get pass-by-value in C?


As I wrote above, it's an old-style definition. (Parameters are really
local variables anyway; they differ from other local variables in how
they're declared and in the way they're initialized with the values of
the arguments given in the call.)

> Also what is the advantage of declaring the string and memory functions
> locally to the function?


None. The right way to get those declarations is:

#include <stdlib.h> /* malloc, free */
#include <string.h> /* strcpy */
#include <stdio.h> /* puts */

which also has the advantage of providing prototypes, so the compiler
can diagnose calls with incorrect arguments.

The code as posted will probably work with modern compilers (as long as
they permit the old-style "implicit int" rule, dropped by C99), but it's
not a good example for writing new code.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Joe Pfeiffer 07-31-2012 03:56 AM

Re: Params -> local vars?
 
Jon Howson <nospam@nospam.com> writes:

> Hello
>
> I was reading thru some (yellowing!) mimeographed introductory notes on C
> and I found code like the below.
>
> main(argc,argv)
> int argc;
> char *argv[];
> {
> char *malloc();
> char *strcpy();
> int puts();
> void free();
>
> char *s;
> if(argc>1 &&(s=malloc(8+strlen(argv[1])))){
> strcpy(s,"Hello, ");
> strcpy(s+7,argv[1]);
> puts(s);
> free(s);
> }else{
> puts("Program failed, unknown error");
> }
> }
>
> I'm trying to work out what's happening. At the start of the function, I
> guess the parameters are being converted into local variables, maybe a
> way to get pass-by-value in C?


Do you mean this part?

> main(argc,argv)
> int argc;
> char *argv[];
> {


That's just the way parameters used to be declared. It means exactly
the same thing as

main(int argc, char *argv[])

> Also what is the advantage of declaring the string and memory functions
> locally to the function?


I can't think of one off-hand.

Mark Bluemel 07-31-2012 07:34 AM

Re: Params -> local vars?
 
On 30/07/2012 21:09, Stephen Sprunk wrote:

> Unless you're interested in software archaeology, I would recommend you
> discard any text that uses K&R C, which has been obsolete since ANSI C
> was published in 1989.


A little harsh - I think that K&R 1st edition is worth keeping if you
have a copy.


Kleuske 07-31-2012 07:29 PM

Re: Params -> local vars?
 
On Tue, 31 Jul 2012 08:34:42 +0100, Mark Bluemel saw fit to publish the
following:

> On 30/07/2012 21:09, Stephen Sprunk wrote:
>
>> Unless you're interested in software archaeology, I would recommend you
>> discard any text that uses K&R C, which has been obsolete since ANSI C
>> was published in 1989.

>
> A little harsh - I think that K&R 1st edition is worth keeping if you
> have a copy.


Not really smart, either. It may just be a collectors item.I would pay
money for an original K&R manual, if only for sentimental reasons.

For educational purposes, however, I'm with Sprunk.

Eric Sosman 07-31-2012 07:51 PM

Re: Params -> local vars?
 
On 7/31/2012 3:29 PM, Kleuske wrote:
> On Tue, 31 Jul 2012 08:34:42 +0100, Mark Bluemel saw fit to publish the
> following:
>
>> On 30/07/2012 21:09, Stephen Sprunk wrote:
>>
>>> Unless you're interested in software archaeology, I would recommend you
>>> discard any text that uses K&R C, which has been obsolete since ANSI C
>>> was published in 1989.

>>
>> A little harsh - I think that K&R 1st edition is worth keeping if you
>> have a copy.

>
> Not really smart, either. It may just be a collectors item.I would pay
> money for an original K&R manual, if only for sentimental reasons.


US$3.44 plus $3.99 shipping on Ebay. Get 'em while they're hot.

(No, I'm not selling mine.)

> For educational purposes, however, I'm with Sprunk.


Seconded, or maybe thirded. The language has changed a lot
in the three and a half decades since K&R came off the presses,
and many code samples in K&R, though exemplary (by definition!)
at the time would nowadays be considered poor style if not just
plain broken.

"Whan that Aprill, with his shoures soote
The droghte of March hath perced to the roote
And bathed every veyne in swich licour,
Of which vertu engendred is the flour ..."

A classic of English literature, but not much help in learning
English. Just so with K&R: The language has moved on.

--
Eric Sosman
esosman@ieee-dot-org.invalid


All times are GMT. The time now is 08:27 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.