pass by reference is valid?

L

lisp9000

I've read that C allows two ways to pass information between
functions:

o Pass by Value
o Pass by Reference

I was talking to some C programmers and they told me there is no such
thing as pass by reference in C since you are just passing an address
(or a pointer value address I guess?). So I was wondering is this
correct?

Also I read that, "C does not have run-time typing". What does this
mean and is it true?

C just cares that you pass the correct type of arguments (int, float,
char, ...) and doesn't care about the value or variable/data structure
name is that also correct?

I wrote 3 simple test programs for the different ways to pass
information in functions. Any critiques/improvements would be welcome:


/* Example 1 */

/* func.c */

int swap(int a, int b)
{
a = b;
return a;
}

/* main.c */

int b =1;
int c = 2;

int main(void)
{

swap(b,c);
printf("%d",c);
return 0;
}

BTW in my example of func.c and main.c here it doesn't seem to matter
if I make b, c global variables or local. In writing C how do I best
decide if I should make variables global or local, or if it won't
affect the purpose of the code should I not care?

/* Example 2 */

/* func2.c */

int swap(int &a, int &b)
{
a = b;
return a;
}

/* main2.c */

int *b =1;
int *c = 2;

int main(void)
{

swap(&b,&c);
printf("%d",&c);
return 0;
}

/* Example 3 */

/* func3.c */

int swap(int *a, int *b)
{
*a = *b;
return *a;
}

/* main3.c */

int *b =1;
int *c = 2;

int main(void)
{

swap(*b,*c);
printf("%d",&c);
return 0;
}

PS: I'm learning about closures in Lisp and they seem nifty, but I
read C doesn't have them. Or is this not quite true?

Lisp 9000
 
F

Flash Gordon

I've read that C allows two ways to pass information between
functions:

o Pass by Value
o Pass by Reference

You may not have read the book carefully enough, or it may
be a bad book.
I was talking to some C programmers and they told me there is no such
thing as pass by reference in C since you are just passing an address
(or a pointer value address I guess?). So I was wondering is this
correct?

The C programmers are correct. Of course, passing a pointer by value
allows you to do something very similar to passing by reference
foo(&i);
foo can now modify the value of i because you passed a pointer to it.
Also I read that, "C does not have run-time typing". What does this
mean and is it true?

In some languages you can do something like:
func(var)
if var is an int then do something
else if var is a string do something else

In C you can't.
C just cares that you pass the correct type of arguments (int, float,
char, ...) and doesn't care about the value or variable/data structure
name is that also correct?

There are some promotions which are automatically performed, so the
above is at least misleading.
I wrote 3 simple test programs for the different ways to pass
information in functions. Any critiques/improvements would be welcome:

/* Example 1 */

/* func.c */

int swap(int a, int b)
{
a = b;
return a;
}

Why make swap return an int? I would say that void makes more sense.
Obviously it does not work as you know.
/* main.c */

int b =1;
int c = 2;

int main(void)
{

swap(b,c);
printf("%d",c);
return 0;
}

BTW in my example of func.c and main.c here it doesn't seem to matter
if I make b, c global variables or local. In writing C how do I best
decide if I should make variables global or local, or if it won't
affect the purpose of the code should I not care?

The simple rule for beginners is make them local. When you know a bit
more you make them local unless you have a *very* good reason not to.
The reason for this is that if a variable is local you can easily see
where it is modified. If it is global you have to check the entire
1,000,000 line program to see what affects it.
/* Example 2 */

/* func2.c */

int swap(int &a, int &b)

A syntax error in C. If you compiler accepts it then it is not working
as a C compiler.

/* Example 3 */

/* func3.c */

int swap(int *a, int *b)
{
*a = *b;
return *a;
}

Again, I would not return a value.
void swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
You should be able to work out the reasons for the rest of the changes
since you called the function 'swap' not 'assign'.
/* main3.c */

int *b =1;
int *c = 2;

No, no, a thousand time no. You want int variables, not pointers to int.
A pointer points somewhere, the value it points to is held somewhere
else and you have to provide that place.
int main(void)
{

swap(*b,*c);

With b and c being pointers, this would pass the value pointed to (if
the rest was correct) *not* the pointer value. The names of the
variables are 'b' and 'c' *not* '*b' and '*c'.
printf("%d",&c);

I don't even know what you were thinking.
return 0;
}

int main(void)
{
int b=2;
int c=3;
printf("%d %d\n",b,c);
swap(&b,&c);
printf("%d %d\n",b,c);
return 0;
}

You use & to get a pointer to a variable.
PS: I'm learning about closures in Lisp and they seem nifty, but I
read C doesn't have them. Or is this not quite true?

C does not have them.

Personally I think trying to learn two languages at once is a mistake.
 
A

Army1987

I've read that C allows two ways to pass information between
functions:

o Pass by Value
o Pass by Reference

I was talking to some C programmers and they told me there is no such
thing as pass by reference in C since you are just passing an address
(or a pointer value address I guess?). So I was wondering is this
correct?

Also I read that, "C does not have run-time typing". What does this
mean and is it true?

C just cares that you pass the correct type of arguments (int, float,
char, ...) and doesn't care about the value or variable/data structure
name is that also correct?

I wrote 3 simple test programs for the different ways to pass
information in functions. Any critiques/improvements would be welcome:


/* Example 1 */

/* func.c */

int swap(int a, int b)
{
a = b;
return a;
}

/* main.c */

int b =1;
int c = 2;

int main(void)
{

swap(b,c);
printf("%d",c);
return 0;
}

BTW in my example of func.c and main.c here it doesn't seem to matter
if I make b, c global variables or local.
Because the parameter b would shadow out the global variable. This
is not a very Good Thing to do in general...

In writing C how do I best
decide if I should make variables global or local, or if it won't
affect the purpose of the code should I not care?
No, you should make them local unless there is a good reason to do
otherwise. (BTW, the terms the C Standard uses are "file scope"
and "block scope").
/* Example 2 */

/* func2.c */

int swap(int &a, int &b)
No such thing in C. You were thinking about C++? If so, go to
comp.lang.c++.
{
a = b;
return a;
}

/* main2.c */

int *b =1;
This is a constraint violation, though on some compilers it does
compile to the equivalent of int *b = (int *)1. Simplifying a bit,
b contains the address of the memory location 1. It doesn't even
need to be correctly aligned to contain an int. This is definitely
*not* what you were trying to do.
int *c = 2;

int main(void)
{

swap(&b,&c);
&b is the address of the object b, which in turn contains the
address of memory location 1.
printf("%d",&c);
return 0;
}

/* Example 3 */

/* func3.c */

int swap(int *a, int *b)
{
*a = *b;
return *a;
}

/* main3.c */

int *b =1;
int *c = 2;

int main(void)
{

swap(*b,*c);
*b means the int located at the address contained in b. And you
are likely not to be allowed to read from address 1. Ka-Boom!
printf("%d",&c);
return 0;
}

Try this:
int swap(int *a, int *b)
{
*a = *b;
return *a;
}
int main(void)
{
int b = 1;
int c = 2;
swap(&b, &c);
printf("%d %d\n", b, c);
return 0;
}
 
B

Bart van Ingen Schenau

I've read that C allows two ways to pass information between
functions:

o Pass by Value
o Pass by Reference

I was talking to some C programmers and they told me there is no such
thing as pass by reference in C since you are just passing an address
(or a pointer value address I guess?). So I was wondering is this
correct?

It depends on how 'Pass by Reference' is interpreted.
In general computer science, passing a pointer to some data qualifies
as 'Pass by Reference'.
In the context of C++, and for those who want to distinguish between the
parameter passing methods of C and C++, the term 'Pass by Reference'
gets reserved for the situation that C++ reference types are used. The
mechanism of passing a pointer is then referred to as 'Pass by
Address'.

You could also argue that C only has 'Pass by Value', because if you are
passing a pointer to something, then it is the value of the pointer
that gets passed.
Also I read that, "C does not have run-time typing". What does this
mean and is it true?

You will have to ask whoever made that statement what they meant with
the term 'run-time typing'.
One main characteristic of C is that all types used in the program, as
well as the exact type for each variable, must be known to the
compiler.
C just cares that you pass the correct type of arguments (int, float,
char, ...) and doesn't care about the value or variable/data structure
name is that also correct?

Yes, that is correct.
I wrote 3 simple test programs for the different ways to pass
information in functions. Any critiques/improvements would be welcome:


/* Example 1 */

/* func.c */

int swap(int a, int b)
{
a = b;
return a;
}

Given this implementation, I think the name 'assign' would have been
better for this function (same goes for the other examples).

This function uses 'Pass by Value', and therefor any changes you make to
a and b will be discarded as soon as you leave the function.
/* main.c */

int b =1;
int c = 2;

int main(void)
{

swap(b,c);
printf("%d",c);
return 0;
}

BTW in my example of func.c and main.c here it doesn't seem to matter
if I make b, c global variables or local. In writing C how do I best
decide if I should make variables global or local, or if it won't
affect the purpose of the code should I not care?

The default should be to use local variables.
The advantage of local variables is that they are only visible within
the block where they are declared. This means that in different
(non-nested) blocks, you can re-use the same name for different
purposes.

Global variables should be avoided as much as possible. Use them only
when there is no reasonable alternative and even then you should prefer
to declare them as 'static', which will limit their visibility to the
current source file.
/* Example 2 */

/* func2.c */

int swap(int &a, int &b)

This is a syntax error in C.

/* Example 3 */

/* func3.c */

int swap(int *a, int *b)
{
*a = *b;
return *a;
}

This function uses 'Pass by Address'.
Changes to a and b themselves will not be visible or preserved outside
the function, but changes to *a or *b are visible and preserved.
/* main3.c */

int *b =1;
int *c = 2;

These two lines should generate a loud complaint from the compiler.
For this example, it is best to declare b and c the same as in example 1
int b =1;
int c = 2;
int main(void)
{

swap(*b,*c);

This is the wrong syntax for calling the function.
You need to pass the address of b and c, so you call the function like
this:
swap(&b, &c);
printf("%d",&c);

This should just be:
printf("%d", c);

But note that the function swap() does not actually modify its second
argument, so you will see no change here.
return 0;
}

A more useful illustration of 'Pass by Value and 'Pass by Address' would
be this:

#include <stdio.h>

void swap_value(int lhs, int rhs)
{
int temp;

printf("Inside swap_value(in): lhs = %d, rhs = %d\n", lhs, rhs);
temp = lhs;
lhs = rhs;
rhs = temp;
printf("Inside swap_value(out): lhs = %d, rhs = %d\n", lhs, rhs);
}

void swap_address(int* lhs, int* rhs)
{
int temp;

printf("Inside swap_address(in): *lhs = %d, *rhs = %d\n", *lhs, *rhs);
temp = *lhs;
*lhs = *rhs;
*rhs = temp;
printf("Inside swap_address(out): *lhs = %d, *rhs = %d\n", *lhs,
*rhs);
}

int main()
{
int a;
int b;

a = 1;
b = 42;
printf("Before swap_value(a,b): a = %d, b = %d\n", a, b);
swap_value(a,b);
printf("After swap_value(a,b): a = %d, b = %d\n", a, b);

a = 1;
b = 42;
printf("Before swap_address(a,b): a = %d, b = %d\n", a, b);
swap_address(a,b);
printf("After swap_address(a,b): a = %d, b = %d\n", a, b);

return 0;
}
PS: I'm learning about closures in Lisp and they seem nifty, but I
read C doesn't have them. Or is this not quite true?

C does indeed not have closures.
Lisp 9000

Bart v Ingen Schenau
 
K

Keith Thompson

I've read that C allows two ways to pass information between
functions:

o Pass by Value
o Pass by Reference

I was talking to some C programmers and they told me there is no such
thing as pass by reference in C since you are just passing an address
(or a pointer value address I guess?). So I was wondering is this
correct?

Yes and no.

C does not have pass-by-reference as a built-in language feature. All
function arguments are passed by value. That's the most important
thing to remember.

But it's easy to *emulate* pass-by-reference by passing pointers (the
pointers are passed by value of course) -- just as you can emulate
linked lists using structs and pointers.

C doesn't have pass-by-reference, but that doesn't mean your C program
can't use pass-by-reference (or at least the equivalent of
pass-by-reference).

[...]
/* Example 1 */

/* func.c */

int swap(int a, int b)
{
a = b;
return a;
}

/* main.c */

int b =1;
int c = 2;

int main(void)
{

swap(b,c);
printf("%d",c);
return 0;
}

As you've seen, this doesn't work. But your swap() function doesn't
even *try* to swap its two arguments; Flash Gordon already covered
that. Since you're calling printf, you *must* have
#include <stdio.h>
at the top of your program. If your compiler doesn't warn you about
this, crank up the warning level. And you should print a '\n' at the
end of your program's output.

If you want to test whether a swap function works, you need to print
*both* values.

As a matter of style, your variable names are poorly chosen. You use
'a' and 'b' as the parameter names for swap(), but you use 'b' and 'c'
as the names of the variables whose values you pass to it. That's
perfectly legal (names in different scopes don't have to be distinct),
but it's confusing.

[...]
/* Example 2 */

/* func2.c */

int swap(int &a, int &b)
[snip]

This appears to be C++, not C. (C++ has a feature called "references"
that C does not.) If you want to program in C, figure out how to make
your compiler act as a C compiler.
/* Example 3 */

/* func3.c */

int swap(int *a, int *b)
{
*a = *b;
return *a;
}

/* main3.c */

int *b =1;
int *c = 2;

int main(void)
{

swap(*b,*c);
printf("%d",&c);
return 0;
}
[...]

There are a number of serious errors in this code. Either your
compiler isn't telling you about them (in that case, you need to turn
up its diagnostic level), it's giving you warning messages and you're
ignoring them.

For example,
int *b = 1;
attempts to assign an int value to an int* variable. This is illegal
(more precisely it's a "constraint violation", and any conforming
compiler is required to complain about it).

Learn how to invoke your compiler so that (a) it compiles C, not C++,
and (b) so that it complains about as many errors in your code as
possible -- and pay close attention to any messages it produces, even
if they're just warnings.
 
R

Richard Tobin

Bart van Ingen Schenau said:
You could also argue that C only has 'Pass by Value', because if you are
passing a pointer to something, then it is the value of the pointer
that gets passed.

I think this is the clearest way to describe it. After all, if you
assign to the (pointer) value in the called function, it doesn't
affect anything in the caller. You have to explicitly dereference
the passed it to get the effect of call-by-reference.

-- Richard
 
J

Joe Wright

Keith said:
I've read that C allows two ways to pass information between
functions:

o Pass by Value
o Pass by Reference

I was talking to some C programmers and they told me there is no such
thing as pass by reference in C since you are just passing an address
(or a pointer value address I guess?). So I was wondering is this
correct?

Yes and no.

C does not have pass-by-reference as a built-in language feature. All
function arguments are passed by value. That's the most important
thing to remember.

But it's easy to *emulate* pass-by-reference by passing pointers (the
pointers are passed by value of course) -- just as you can emulate
linked lists using structs and pointers.

C doesn't have pass-by-reference, but that doesn't mean your C program
can't use pass-by-reference (or at least the equivalent of
pass-by-reference).

[much snippage]

Pass-by-reference is the devil's spawn. In C++ it has its own syntax and
can be 'seen' at least. 11 years ago, in a land far away, I was
sentenced to maintain someone else's program, written in dBASEIV.

Three main storage classes of memory variables are PUBLIC, PRIVATE and
LOCAL. I was already a C programmer and PUBLIC simply meant file-scope
to me. Likewise, LOCAL was auto within a function block. This PRIVATE
thing was new and different. It is also the default storage class.

The effect of PRIVATE is to have calls to subroutines carry PRIVATE
variables with it without cluttering up the argument list.

a = 2
b = 4
c = 8

d = foo()
? d

func foo()
return a + b + c
endfunc

In the xBASE languages, ? is the print command and executing the above
will produce 14 on the console.

But PRIVATE has also the reference aspect like this..

a = 2
foo(a)
? a

func foo(x)
x = 9
return

The parameter x in foo is a reference to variable a in the caller. The
'? a' line will print 9. I don't remember anymore how long it took me to
figure that one out but more than a few hours.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top