Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

segfault w/ block, but not file scope

25 views
Skip to first unread message

Dieter

unread,
Jan 5, 2006, 10:30:11 PM1/5/06
to
Hi.

In the snippet of code below, I'm trying to understand why when the

struct dirent ** namelist

is declared with "file" scope, I don't have a problem freeing the
allocated memory. But when the struct is declared in main (block scope)
it will segfault when passing namelist to freeFileNames().

Since this seems to be just a matter of my understanding scope and
pointer parameter passing better, I only included what thought to be
relevant code. I'll happily provide compilable code if deemed necessary.

Please see commented lines:


struct dirent **namelist; /* file scope works */

int main(void)
{
/* struct dirent **namelist */ /* block scope doesn't work */
int n;

n = getFileNames(H5DIR, namelist); /* included from mylib.h */
freeFileNames(namelist, n); /* included from mylib.h */

return 0;
}


Thank you very much for your comments,
Dieter

Dieter

unread,
Jan 5, 2006, 10:44:27 PM1/5/06
to

Here's the actual code if needed. Although dirent.h is platform
specific, I think my question is relative to standard C.

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

#define H5DIR "/home/stella/data/h5/rawTables"

int getFileNames(char *directory, struct dirent **namelist);
int freeFileNames(struct dirent **namelist, int entries);

struct dirent **namelist;

int main(void)
{
int n;

n = getFileNames(H5DIR, namelist);
printf("%d\n",n);
err = freeFileNames(namelist, n);
if (err==0)
printf("There wasn't any files");
return 0;
}

int getFileNames(char *directory, struct dirent **namelist)
{
int n, i;

n = scandir(directory, &namelist, 0, alphasort);
if(n == -1){
perror("scandir returned: ");
exit(1);
}
if(n == 0){
printf("No files found. Quiting.\n\n");
exit(1);
}
for (i=0;i<n;i++){
printf("File: %s\n", namelist[i]->d_name);
}

return n;
}

int freeFileNames(struct dirent **namelist, int entries)
{
int i;

if (namelist == NULL)
return 0;
else{
printf("%d",entries);
for (i = 0; i < entries; i++){
free(namelist[i]);
namelist[i] = NULL;
printf("%d,", i);
}
puts("\n");
free(namelist);
namelist = NULL;
}

return 1;
}

Jack Klein

unread,
Jan 5, 2006, 11:42:28 PM1/5/06
to
On Thu, 05 Jan 2006 22:44:27 -0500, Dieter <usenet...@comcast.net>
wrote in comp.lang.c:

> Dieter wrote:
> > Hi.
> >
> > In the snippet of code below, I'm trying to understand why when the
> >
> > struct dirent ** namelist
> >
> > is declared with "file" scope, I don't have a problem freeing the
> > allocated memory. But when the struct is declared in main (block scope)
> > it will segfault when passing namelist to freeFileNames().
> >
> > Since this seems to be just a matter of my understanding scope and
> > pointer parameter passing better, I only included what thought to be
> > relevant code. I'll happily provide compilable code if deemed necessary.
> >
> > Please see commented lines:
> >
> >
> > struct dirent **namelist; /* file scope works */
> >
> > int main(void)
> > {
> > /* struct dirent **namelist */ /* block scope doesn't work */
> > int n;
> >
> > n = getFileNames(H5DIR, namelist); /* included from mylib.h */
> > freeFileNames(namelist, n); /* included from mylib.h */
> >
> > return 0;
> > }
> >
> >
> > Thank you very much for your comments,
> > Dieter
>
> Here's the actual code if needed. Although dirent.h is platform
> specific, I think my question is relative to standard C.

The actual code is not needed, and is indeed off-topic. Your problem
has a great deal to do with how the function scandir(), which is
apparently from dirent.h, deals with pointers.


> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <dirent.h>
> #include <errno.h>
>
> #define H5DIR "/home/stella/data/h5/rawTables"
>
> int getFileNames(char *directory, struct dirent **namelist);
> int freeFileNames(struct dirent **namelist, int entries);
>
> struct dirent **namelist;

When you define this pointer a file scope, it has static storage
duration and is therefore initialized to NULL. When you define it
inside a function, it has automatic storage duration by default and it
not initialized at all.

> int main(void)
> {
> int n;
>
> n = getFileNames(H5DIR, namelist);
> printf("%d\n",n);
> err = freeFileNames(namelist, n);
> if (err==0)
> printf("There wasn't any files");
> return 0;
> }
>
> int getFileNames(char *directory, struct dirent **namelist)
> {
> int n, i;
>
> n = scandir(directory, &namelist, 0, alphasort);

[snip]

On the last line of code above, you pass a pointer to 'namelist'
(therefore a char ***) to scandir(). Presumably this function checks
whether the pointed-to char ** is NULL or not, and if it is NULL, it
allocates the necessary memory. And also presumably, if the
pointed-to char ** is not NULL, it assumes that it points to valid
memory and uses it. At the end you try to free a pointer that was not
allocated.

I would suggest that you study the documentation for the function
scandir() and see what the requirements are for that parameter.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

Dieter

unread,
Jan 6, 2006, 12:30:27 AM1/6/06
to

Jack, I sincerely thank you for commenting.

NULL initialization was certainly an issue.

Dieter

Chuck F.

unread,
Jan 6, 2006, 1:35:01 AM1/6/06
to
Dieter wrote:

> Jack Klein wrote:
>
>> [snip]
>>
>> On the last line of code above, you pass a pointer to
>> 'namelist' (therefore a char ***) to scandir(). Presumably
>> this function checks whether the pointed-to char ** is NULL or
>> not, and if it is NULL, it allocates the necessary memory.
>> And also presumably, if the pointed-to char ** is not NULL, it
>> assumes that it points to valid memory and uses it. At the
>> end you try to free a pointer that was not allocated.
>>
>> I would suggest that you study the documentation for the
>> function scandir() and see what the requirements are for that
>> parameter.
>
> Jack, I sincerely thank you for commenting.
>
> NULL initialization was certainly an issue.

All of which points out why we want queries to be topical. Once
you involve an unknown header (dirent) and an unknown function
(scandir) nobody can have any accurate idea what goes on. This is
why this whole thread should have been on a newsgroup dealing with
your system in the first place.

The fact that Jack could make an educated guess does not affect
this. His guess could well have been total nonsense, and could
have missed important factors. There is (in principle) noone here
to correct any mistakes.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>

M.B

unread,
Jan 6, 2006, 1:59:32 AM1/6/06
to
sorry if thjis is a duplicate reply...

I guess this is a scope issue for variable "namelist"
I suggest to change the function
int getFileName(char *,struct dirent ***);
and make necessary changes to code.
it may work fine

bcoz scandir i guess sets "struct dirent **" itself.
if its global all is fine, but local variables 0 its problem-same as
pass by value

thanks
-M.B

M.B

unread,
Jan 6, 2006, 2:02:05 AM1/6/06
to
please check
pass by value
v/s pass by ref/pointers carefully


hope this helps to solve the issue

Chris Torek

unread,
Jan 6, 2006, 1:59:19 AM1/6/06
to
In article <SZWdnSAon_epeSDe...@comcast.com>

Dieter <usenet...@comcast.net> wrote:
>struct dirent **namelist; /* file scope works */
>
>int main(void)
>{
> /* struct dirent **namelist */ /* block scope doesn't work */
> int n;
>
> n = getFileNames(H5DIR, namelist); /* included from mylib.h */

This passes the *value* of the variable "namelist" to the function.
If namelist has block scope, the variable is also automatic, and hence
uninitialized, and hence contains garbage. If namelist has file
scope, the variable also has static duration and hence is
initialized to NULL.

In any case, getFileNames() cannot change the value stored in
the variable named "namelist" (unless it does not declare one
of its own, and does access the file-scope one). So it makes
no sense to pass the value in the first place, if namelist is
a block-scope variable.

If getFileNames() needs to modify namelist, it will need the
address of the variable:

extern int getFileNames(first_type, struct dirent ***);
...
int main(void) {
struct dirent **namelist;
int n;

/* optional: namelist = NULL; */
n = getFileNames(H5DIR, &namelist);

> freeFileNames(namelist, n); /* included from mylib.h */

Presumably the NULL-initialized file-scope static-duration version
causes freeFileNames() to be a no-op. Passing the uninitialized
value of the block-scope version presumably does not.

> return 0;
>}
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.

Dieter

unread,
Jan 6, 2006, 2:26:42 AM1/6/06
to

Yes I appreciate that.

My question, I believed, was standard C specific and debated whether to
post it here. In the future *anything* including anything other than
standard C will be posted elsewhere.

Possibly the newsgroup's name could be changed to comp.lang.C.standard,
or some such. It might eliminate a small amount of the regular grief you
all encounter.

Regards,
Dieter

Dieter

unread,
Jan 6, 2006, 2:28:53 AM1/6/06
to

Thank you for your comments MB.

Dieter

unread,
Jan 6, 2006, 2:31:14 AM1/6/06
to

My apologies to the regulars for an OT inclusion related to the question.


< This Thread Closed >


Thanks,
Dieter

Dieter

unread,
Jan 6, 2006, 2:45:56 AM1/6/06
to

You've hit the nail on the head. That's exactly what I've been having
trouble wrapping my mind around.

* Pass the address of the pointer in order to return it's value modified. *

The N indirection, dynamic allocation, and passing them has been
confusing me.


Thanks Chris

M.B

unread,
Jan 6, 2006, 12:47:36 AM1/6/06
to

I guess this is a scope issue for variable "namelist"

M.B

unread,
Jan 6, 2006, 12:51:55 AM1/6/06
to
please chanmge function int getFileName(char *,struct dirent **);
to int getFileNames(char *,struct dirent ***) and make necessary
changes to code to accomodate this

its a pass by value v/s pass by reference issue

M.B

unread,
Jan 6, 2006, 2:28:19 AM1/6/06
to

Chuck F. wrote:
> Dieter wrote:
> > Jack Klein wrote:
> >
> >> [snip]
> >>
> >> On the last line of code above, you pass a pointer to
> >> 'namelist' (therefore a char ***) to scandir(). Presumably
> >> this function checks whether the pointed-to char ** is NULL or
> >> not, and if it is NULL, it allocates the necessary memory.
> >> And also presumably, if the pointed-to char ** is not NULL, it
> >> assumes that it points to valid memory and uses it. At the
> >> end you try to free a pointer that was not allocated.
> >>


> >> I would suggest that you study the documentation for the
> >> function scandir() and see what the requirements are for that
> >> parameter.
> >
> > Jack, I sincerely thank you for commenting.
> >
> > NULL initialization was certainly an issue.
>
> All of which points out why we want queries to be topical. Once
> you involve an unknown header (dirent) and an unknown function
> (scandir) nobody can have any accurate idea what goes on. This is
> why this whole thread should have been on a newsgroup dealing with
> your system in the first place.
>

btw dirent or dirent.h is not alien. its of course not in ansi but in
posix (k&r also mentions it)

> The fact that Jack could make an educated guess does not affect
> this. His guess could well have been total nonsense, and could
> have missed important factors. There is (in principle) noone here
> to correct any mistakes.
>

I agree here. Anyone replying here want to help in any case. But we all
can help in giving suggestions but not spoonfeed. I may not know what
others know . knowlegde sharing is the idea here.

M.B

unread,
Jan 6, 2006, 2:30:43 AM1/6/06
to

Chuck F. wrote:
> Dieter wrote:
> > Jack Klein wrote:
> >
> >> [snip]
> >>
> >> On the last line of code above, you pass a pointer to
> >> 'namelist' (therefore a char ***) to scandir(). Presumably
> >> this function checks whether the pointed-to char ** is NULL or
> >> not, and if it is NULL, it allocates the necessary memory.
> >> And also presumably, if the pointed-to char ** is not NULL, it
> >> assumes that it points to valid memory and uses it. At the
> >> end you try to free a pointer that was not allocated.
> >>


> >> I would suggest that you study the documentation for the
> >> function scandir() and see what the requirements are for that
> >> parameter.
> >
> > Jack, I sincerely thank you for commenting.
> >
> > NULL initialization was certainly an issue.
>
> All of which points out why we want queries to be topical. Once
> you involve an unknown header (dirent) and an unknown function
> (scandir) nobody can have any accurate idea what goes on. This is
> why this whole thread should have been on a newsgroup dealing with
> your system in the first place.
>

btw dirent or dirent.h is not alien. its of course not in ansi but in
posix (k&r also mentions it)

> The fact that Jack could make an educated guess does not affect


> this. His guess could well have been total nonsense, and could
> have missed important factors. There is (in principle) noone here
> to correct any mistakes.
>

I agree here. Anyone replying here want to help in any case. But we all


can help in giving suggestions but not spoonfeed. I may not know what
others know . knowlegde sharing is the idea here.

> --

M.B

unread,
Jan 6, 2006, 2:22:25 AM1/6/06
to
This works without segfault.

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

#define H5DIR "./"

int getFileNames(char *directory, struct dirent ***namelist);


int freeFileNames(struct dirent **namelist, int entries);


int main(void)
{
int n,err;
struct dirent **namelist;

n = getFileNames(H5DIR,&namelist);


printf("%d\n",n);
err = freeFileNames(namelist, n);
if (err==0)
printf("There wasn't any files");
return 0;

}

int getFileNames(char *directory, struct dirent ***namelist)
{
int n, i;

n = scandir(directory, namelist, 0, alphasort);


if(n == -1){
perror("scandir returned: ");
exit(1);
}
if(n == 0){
printf("No files found. Quiting.\n\n");
exit(1);
}
for (i=0;i<n;i++){

printf("File: %s\n", (*namelist)[i]->d_name);
}

return n;

}

int freeFileNames(struct dirent **namelist, int entries)

Dieter

unread,
Jan 6, 2006, 3:09:21 AM1/6/06
to
MB, I can't express enough how much I appreciate your contribution.
Thank you for taking the time... and bending the sacred rules a little. :)

Keith Thompson

unread,
Jan 6, 2006, 3:47:55 AM1/6/06
to

In this case, there wasn't really any need to guess. The code causing
the problem was:

struct dirent **namelist;


int n;
n = getFileNames(H5DIR, namelist);

It might as well have been:

struct foo **bar;
int n;
n = bleeble(blah, bar);

Regardless of what struct dirent/struct foo is, and regardless of what
getFileNames() or bleeble() does with its arguments, passing an
uninitialized variable to a function is almost certainly an error.
(Come to think of it, drop the "almost".)

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

tmp123

unread,
Jan 6, 2006, 4:38:34 AM1/6/06
to
Dieter wrote:
> int getFileNames(char *directory, struct dirent **namelist)
> {
> int n, i;
>
> n = scandir(directory, &namelist, 0, alphasort);

Hi,

As other groups members has remarked, the problem was in the call to
scandir (the program doesn't works if the variable is global and also
doesn't works if it is local. The only diference is how bad are the
effects).

I want only to remark two things about modify a function parameter:
a) The changes done to the value of a parameter will be always lost at
function return.
b) Change a parameter is under stylistic discussion (in particular, I
never do it. If necessary, I declare a local and init it with the
parameter value), and, who knows if allowed by standard. By example, a
SPARC CPU uses registers to pass parameters, so, the address of a
parameter is something that breaks to normal function prologs
(assembler code at start of fucntion).

In conclusion, any line of the kind "&parameter" must be carefully
reviewed.

Kind regards.

Richard Heathfield

unread,
Jan 6, 2006, 4:40:42 AM1/6/06
to
M.B said:

> its a pass by value v/s pass by reference issue

Since C doesn't have pass by reference, it is clear to me that you are
talking nonsense.


--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

M.B

unread,
Jan 6, 2006, 5:01:01 AM1/6/06
to

Why do we initialize the variable if the variable is it is being
returned by the called function with a valid value
for ex
void f(int *i)
{
*i=1;
return;
}

int main(void)
{
int k; /*why need int k=0... */
f(&k);
...
return(0);
}
------------------
related
----------------------
void f(int i) /* I intend to modify i */
{
i=1;
return;
}

int main(void)
{
int k=0; /*why need int k=0... */
f(k);
...
return(0);
}

No effect on variable "k"
what initialization (0) helps in this case


>
> --
> Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
> San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
> We must do something. This is something. Therefore, we must do this.

- M.B

Dieter

unread,
Jan 6, 2006, 5:11:25 AM1/6/06
to
tmp123 wrote:
> Dieter wrote:
>
>>int getFileNames(char *directory, struct dirent **namelist)
>>{
>> int n, i;
>>
>> n = scandir(directory, &namelist, 0, alphasort);
>
>
> Hi,
>
> As other groups members has remarked, the problem was in the call to
> scandir (the program doesn't works if the variable is global and also
> doesn't works if it is local. The only diference is how bad are the
> effects).
>
> I want only to remark two things about modify a function parameter:
> a) The changes done to the value of a parameter will be always lost at
> function return.
> b) Change a parameter is under stylistic discussion (in particular, I
> never do it. If necessary, I declare a local and init it with the
> parameter value),

Hi tmp,

Hmm, this last point you made is not quite clear to me. My goal is to
try to localize/modularize most of what I can and dynamic
allocation~value passing will also be necessarily frequent (I think)
considering event driven considerations. I don't see how I'd be able to
avoid it.

Thanks for your commenting,
Dieter

Chuck F.

unread,
Jan 6, 2006, 6:33:59 AM1/6/06
to

Please use English, not dudespeak, in this newsgroup, and include
adequate context. Between the two your article is totally
meaningless. See below for further advice.

tmp123

unread,
Jan 6, 2006, 8:25:51 AM1/6/06
to


Sorry, it is my fault, I've not been clear enough:

Some examples:

void foo(int *a)
{
*a=14;
}

void test ( int a )
{
int b;
b=2; /* 1: of course, OK */
a=2; /* 2: probably OK, but I do not know if according statndard, and
only in my personal style, not nice */
foo(&b); /* 3: OK */
foo(&a); /* 4: same than 2. In additon, dangerous in the sense that
it is
easy to thing that "a" will be modified afetr
return. Moreover, in some
machines "a" is stored in a register, so, &a
causes an small dificulty */
}

Is point 4 the one that, I do not say wrong, but I suggest to verify
carefully. In fact, one line like this one is the origin of the problem
in your post.

Kind regards.

M.B

unread,
Jan 6, 2006, 9:01:24 AM1/6/06
to

Sorry if i did'nt get you
But why would anyone ever write such a construct
In this case "a" could as well be a local var in test
bcoz after return from test (to main or somewhere) anyway parameter to
test remains unchanged

Randy Howard

unread,
Jan 6, 2006, 9:16:06 AM1/6/06
to
M.B wrote
(in article
<1136532499....@z14g2000cwz.googlegroups.com>):

>> All of which points out why we want queries to be topical. Once
>> you involve an unknown header (dirent) and an unknown function
>> (scandir) nobody can have any accurate idea what goes on. This is
>> why this whole thread should have been on a newsgroup dealing with
>> your system in the first place.
>>
> btw dirent or dirent.h is not alien. its of course not in ansi but in
> posix (k&r also mentions it)

It most certainly is alien to those not using a POSIX platform,
and IIRC, it pre-dates POSIX. Even so, there is no guarantee
that a standard conforming C compiler and linker will no a thing
about it. That's the whole point.

>> The fact that Jack could make an educated guess does not affect
>> this. His guess could well have been total nonsense, and could
>> have missed important factors. There is (in principle) noone here
>> to correct any mistakes.
>>
>
> I agree here. Anyone replying here want to help in any case. But we all
> can help in giving suggestions but not spoonfeed. I may not know what
> others know . knowlegde sharing is the idea here.

No, the issue raised was that if someone asks a question about a
nonstandard extension that is rarely seen, or at least not by
the regulars, then any responses offered could be complete
bullschildt, yet go undetected. When you ask a question in a
forum populated by people that specialize on the topic, you get
much better (and peer reviewed) answers. When you ask a
question on GPS navigation in comp.graphics.apps.photoshop, no
telling what will happen.

--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw
How 'bout them Horns?

Jordan Abel

unread,
Jan 6, 2006, 1:46:21 PM1/6/06
to

scandir(const char *dirname, struct dirent ***namelist, int
(*select)(struct dirent *), int (*compar)(const void *, const void *));

According to the the manpage, it appears to build an array of pointer to
struct dirent, the with the array of pointers and the object pointed to
by each pointer being from malloc(). It then stores the "array" [i.e.
first level of malloc pointer] in *namelist.

My understanding of the manpage on my implementation, backed up by my
reading of the source on my particular implementation, is that it
ignores any previously-pointed-to value and only stores to *namelist.

[why are you calling 'struct dirent' 'char'?]

> At the end you try to free a pointer that was not allocated.

You snipped this part, so I can't comment on it. According to the
manpage, you are supposed to free each member of *namelist [individual
struct dirent *] in turn, then free *namelist. The question is, what
differs between his two versions?

Jordan Abel

unread,
Jan 6, 2006, 1:48:06 PM1/6/06
to
On 2006-01-06, Richard Heathfield <inv...@invalid.invalid> wrote:
> M.B said:
>
>> its a pass by value v/s pass by reference issue
>
> Since C doesn't have pass by reference, it is clear to me that you are
> talking nonsense.

"pass by reference", in common usage, can also apply to the practice
(common in C and appearing several places in the standard library) of
passing a pointer to a value intended to be stored into, rather than any
alternate calling convention specifically supported by the language

Keith Thompson

unread,
Jan 6, 2006, 1:53:29 PM1/6/06
to
"M.B" <mbpr...@gmail.com> writes:
> Keith Thompson wrote:
[...]

>> In this case, there wasn't really any need to guess. The code causing
>> the problem was:
>>
>> struct dirent **namelist;
>> int n;
>> n = getFileNames(H5DIR, namelist);
>>
>> It might as well have been:
>>
>> struct foo **bar;
>> int n;
>> n = bleeble(blah, bar);
>>
>> Regardless of what struct dirent/struct foo is, and regardless of what
>> getFileNames() or bleeble() does with its arguments, passing an
>> uninitialized variable to a function is almost certainly an error.
>> (Come to think of it, drop the "almost".)
>
> Why do we initialize the variable if the variable is it is being
> returned by the called function with a valid value

Because evaluating an uninitialized variable, whether by using it as a
function argument or in some other expression, invokes undefined
behavior.

> for ex
> void f(int *i)
> {
> *i=1;
> return;
> }
>
> int main(void)
> {
> int k; /*why need int k=0... */
> f(&k);
> ...
> return(0);
> }

That's not the same thing. There's no need to initialize k, because
you're not passing the value of k to f(); you're merely passing its
address. Within f(), the value of *i is uninitialized garbage, but
that's ok because it doesn't attempt to read it. The value of i is a
valid address (specifically the address of main's k), so there's no
problem referring to i.

> ------------------
> related
> ----------------------
> void f(int i) /* I intend to modify i */
> {
> i=1;
> return;
> }
>
> int main(void)
> {
> int k=0; /*why need int k=0... */
> f(k);
> ...
> return(0);
> }
>
> No effect on variable "k"
> what initialization (0) helps in this case

This f() function is very strangely written. The first thing it does
is assign a value to its parameter, losing whatever value was passed
in by the caller. It would make more sense to declare "void f(void)"
and make i a local variable.

For a realistic function f() that uses the value of its parameter, it
wouldn't make sense to call it with an uninitialized value. Even with
f() as written, if you changed "int k=0;" to "int k;", just evaluating
the value of k invokes undefined behavior. In practice, this is
unlikely to cause any visible symptoms; type int typically doesn't
have any trap representations. You are likely, however, to get a
warning from the compiler.

>> --
>> Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
>> San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
>> We must do something. This is something. Therefore, we must do this.

When you post a followup, please delete any quoted text that isn't
relevant. In particular, don't quote a signature unless you're
actually commenting on the signature. (Deletions are typically marked
with "[...]" or "[snip]".)

Keith Thompson

unread,
Jan 6, 2006, 2:12:32 PM1/6/06
to
"tmp123" <tmp...@menta.net> writes:
> Dieter wrote:
>> int getFileNames(char *directory, struct dirent **namelist)
>> {
>> int n, i;
>>
>> n = scandir(directory, &namelist, 0, alphasort);
>
> As other groups members has remarked, the problem was in the call to
> scandir (the program doesn't works if the variable is global and also
> doesn't works if it is local. The only diference is how bad are the
> effects).

The variable in question was a pointer which is passed to a function.
If it's global, it's initialized to a null pointer value, which could
be a perfectly valid value for that argument. Whether this is
actually the case depends on the details of the non-standard function
scandir().

> I want only to remark two things about modify a function parameter:
> a) The changes done to the value of a parameter will be always lost at
> function return.
> b) Change a parameter is under stylistic discussion (in particular, I
> never do it. If necessary, I declare a local and init it with the
> parameter value), and, who knows if allowed by standard. By example, a
> SPARC CPU uses registers to pass parameters, so, the address of a
> parameter is something that breaks to normal function prologs
> (assembler code at start of fucntion).
>
> In conclusion, any line of the kind "&parameter" must be carefully
> reviewed.

A parameter is effectively a local variable, initialized to the value
given in the call. Taking its address is no more problematic that
taking the address of any other local variable. The fact that it may
have been passed in a register is irrelevant; if you take and use its
address, the compiler *must* store it in memory somewhere.

I tend to agree with you about the style issue of not modifying the
value of a parameter within a function. If I see a reference to a
parameter within a function, I tend to assume that it refers to the
value that was passed by the caller; if the function modifies it,
understanding the function requires a more complex mental model. But
this is at least partly because I've spent a lot of time working in a
language that makes parameters constant by default; I think that was a
good idea from a language design point of view, but it's not what C
does. In C, as I said, a parameter is really just a local variable,
and as a *reader* of C you have to be prepared to deal with code that
treats it as a variable.

Dieter

unread,
Jan 6, 2006, 6:22:36 PM1/6/06
to

Hi Kieth, thank you for your comments.

So if I understand correctly, It's advisable, that when passing a
pointer in the paramater of a called function (that needs to be modified
for the originating (calling) scope, /for example/ ), that the paramater
(passed pointer) should then be pointed to by a local pointer variable
in the called function. This then makes *clear* the individuality
between the original value being passed and the modification of that
value, and is then,in effect, modifying the value in the calling scope.

Dieter

Keith Thompson

unread,
Jan 6, 2006, 7:21:07 PM1/6/06
to
Dieter <usenet...@comcast.net> writes:
> Keith Thompson wrote:
[...]
>> A parameter is effectively a local variable, initialized to the value
>> given in the call. Taking its address is no more problematic that
>> taking the address of any other local variable. The fact that it may
>> have been passed in a register is irrelevant; if you take and use its
>> address, the compiler *must* store it in memory somewhere.
>> I tend to agree with you about the style issue of not modifying the
>> value of a parameter within a function. If I see a reference to a
>> parameter within a function, I tend to assume that it refers to the
>> value that was passed by the caller; if the function modifies it,
>> understanding the function requires a more complex mental model. But
>> this is at least partly because I've spent a lot of time working in a
>> language that makes parameters constant by default; I think that was a
>> good idea from a language design point of view, but it's not what C
>> does. In C, as I said, a parameter is really just a local variable,
>> and as a *reader* of C you have to be prepared to deal with code that
>> treats it as a variable.
>
> Hi Kieth, thank you for your comments.

It's "Keith".

> So if I understand correctly, It's advisable, that when passing a
> pointer in the paramater of a called function (that needs to be
> modified for the originating (calling) scope, /for example/ ), that
> the paramater (passed pointer) should then be pointed to by a local
> pointer variable in the called function. This then makes *clear* the
> individuality between the original value being passed and the
> modification of that value, and is then,in effect, modifying the value
> in the calling scope.

Um, no. I wasn't talking about pointers at all.

C doesn't directly implement pass-by-reference, so it's emulated by
passing a pointer (the pointer itself is, of course, passed by value).

For example:

#include <stdio.h>

static void increment(int *ptr)
{
*ptr ++;
}

int main(void)
{
int i = 42;
increment(&i);
printf("i = %d\n", i);
return 0;
}

Since ptr itself is never modified, the style issue I discussed above
doesn't arise. There would be no advantage stylistic or otherwise, in
making a local copy of ptr within the increment() function.

The case I was talking about was something more like this:

#include <stdio.h>

static void count_to_ten(int n)
{
while (n <= 10) {
printf("%d\n", n);
n++;
}
}

int main(void)
{
count_to_ten(5);
return 0;
}

Here the count_to_ten() function modifies the value of its parameter
(which obviously can have no effect on the caller). Some might
consider it poor style to the parameter like this, since it's natural
to think of n as the value that was passed in. But there's nothing
*really* wrong with it; n is just a local variable, and it's perfectly
legal to modify it. But in a more complex function, you might want to
look at the *original* value of n that was passed in; modifying n
makes this impossible. The problem can be avoided by copying n to
another local variable, and leaving the parameter value alone.

Either approach is acceptable, but some people are a bit uneasy about
modifying parameters.

Dieter

unread,
Jan 6, 2006, 8:53:01 PM1/6/06
to
Keith Thompson wrote:
> Dieter <usenet...@comcast.net> writes:
>
>>Keith Thompson wrote:
>
> [...]
>
>>>A parameter is effectively a local variable, initialized to the value
>>>given in the call. Taking its address is no more problematic that
>>>taking the address of any other local variable. The fact that it may
>>>have been passed in a register is irrelevant; if you take and use its
>>>address, the compiler *must* store it in memory somewhere.
>>>I tend to agree with you about the style issue of not modifying the
>>>value of a parameter within a function. If I see a reference to a
>>>parameter within a function, I tend to assume that it refers to the
>>>value that was passed by the caller; if the function modifies it,
>>>understanding the function requires a more complex mental model. But
>>>this is at least partly because I've spent a lot of time working in a
>>>language that makes parameters constant by default; I think that was a
>>>good idea from a language design point of view, but it's not what C
>>>does. In C, as I said, a parameter is really just a local variable,
>>>and as a *reader* of C you have to be prepared to deal with code that
>>>treats it as a variable.
>>
>>Hi Kieth, thank you for your comments.
>
>
> It's "Keith".
>

Oops, sorry about that, my fingers are accustomed to "ie" /Dieter/

I thank you sincerely and yes that makes perfect sense. :)

Dieter

Chris Torek

unread,
Jan 6, 2006, 9:11:37 PM1/6/06
to
In article <lnlkxsn...@nuthaus.mib.org>

Keith Thompson <ks...@mib.org> wrote:
>C doesn't directly implement pass-by-reference, so it's emulated by
>passing a pointer (the pointer itself is, of course, passed by value).
>
>For example:
>
> #include <stdio.h>
>
> static void increment(int *ptr)
> {
> *ptr ++;
> }

Your example is somewhat marred by missing parentheses, or a
misplaced operator -- you mean:

++*ptr;

or

(*ptr)++;

[snippage]


>The case I was talking about was something more like this:
>
> #include <stdio.h>
>
> static void count_to_ten(int n)
> {
> while (n <= 10) {
> printf("%d\n", n);
> n++;
> }
> }

[snippage]


>Here the count_to_ten() function modifies the value of its parameter
>(which obviously can have no effect on the caller). Some might
>consider it poor style to the parameter like this, since it's natural
>to think of n as the value that was passed in.

I think this is fine, myself; but it is true that some prefer to
write:

static void count_to_ten(const int n0) {
int n = n0;
while (n <= 10) ...
}

Some (but not all) of these folks use the "const" qualifier, as shown
above, to make sure they do not accidentally modify n0.

I will take this opportunity to note that, in functions that do
deliberately modify a parameter, I tend to declare a local that is
one level "less pointer-y". For instance, in the code at the
start of this thread, I might write the routine that calls
scandir() as:

int somefunc(const char *dir, struct dirent ***anamelist) {
struct dirent **namelist;
int i, n;

n = scandir(dir, &namelist, NULL, NULL);
if (n == -1) ... handle error ...
for (i = 0; i < n; i++)
... work with namelist[i] ...
...
*anamelist = namelist; /* set extra return value */
return n; /* and return "main" return value */
}

This avoids the need to write (*anamelist) everywhere that "namelist"
appears. Of course &(*anamelist) simplifies to anamelist, so the
scandir call itself is no simpler; but the contents of the "for"
loop -- where we work with namelist[i]->field instead of
(*anamelist)[i]->field -- are much easier to read.

There is no particular reason to defer updating *anamelist until
the end of the function, but no particular reason to do it earlier,
either.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.

Keith Thompson

unread,
Jan 6, 2006, 9:41:10 PM1/6/06
to
Chris Torek <nos...@torek.net> writes:
> In article <lnlkxsn...@nuthaus.mib.org>
> Keith Thompson <ks...@mib.org> wrote:
>>C doesn't directly implement pass-by-reference, so it's emulated by
>>passing a pointer (the pointer itself is, of course, passed by value).
>>
>>For example:
>>
>> #include <stdio.h>
>>
>> static void increment(int *ptr)
>> {
>> *ptr ++;
>> }
>
> Your example is somewhat marred by missing parentheses, or a
> misplaced operator -- you mean:
>
> ++*ptr;
>
> or
>
> (*ptr)++;

D'oh! Thanks for catching that. (I did compile and run it; I just
missed the fact that the output was "i = 42" rather than the intended
"i = 43".)

Netocrat

unread,
Jan 6, 2006, 10:02:19 PM1/6/06
to
On Fri, 06 Jan 2006 18:46:21 +0000, Jordan Abel wrote:
> On 2006-01-06, Jack Klein <jack...@spamcop.net> wrote:
[...]

>>> int getFileNames(char *directory, struct dirent **namelist)
>>> {
>>> int n, i;
>>>
>>> n = scandir(directory, &namelist, 0, alphasort);
>>
>> [snip]
>>> On the last line of code above, you pass a pointer to 'namelist'
>> (therefore a char ***) to scandir(). Presumably this function checks
>> whether the pointed-to char ** is NULL or not, and if it is NULL, it
>> allocates the necessary memory. And also presumably, if the
>> pointed-to char ** is not NULL, it assumes that it points to valid
>> memory and uses it.
>
> My understanding of the manpage on my implementation, backed up by my
> reading of the source on my particular implementation, is that it
> ignores any previously-pointed-to value and only stores to *namelist.

If that's true for the OP's platform too (which seems likely) then the
behaviour Jack guessed scandir() to have wasn't a contributor to the
problem. When you write *namelist above, I assume that you refer to the
parameter within scandir() - with type struct dirent ***, not the variable
passed by the caller as &namelist, with type struct dirent **.

> [why are you calling 'struct dirent' 'char'?]
>
>> At the end you try to free a pointer that was not allocated.
>
> You snipped this part, so I can't comment on it. According to the
> manpage, you are supposed to free each member of *namelist [individual
> struct dirent *] in turn, then free *namelist. The question is, what
> differs between his two versions?

The answer that's turned up elsewhere in the thread is:
since namelist is being passed to getFileNames() as a struct dirent **,
the operations performed on it by scandir() are lost to the caller - it
needs to be passed as &namelist with getFileNames() taking a struct
dirent ***, in the same way that scandir() does.

The file-scope declaration set namelist to NULL, so that the user-defined
function to free it returned without problems, but when defined at
function scope in main(), given that it was (a) not initialised and (b)
the intended changes to the initial value were lost due to "passing by
value rather than reference", the user-defined function to free it was
operating on an invalid pointer. I've re-copied part of that function
below:

int freeFileNames(struct dirent **namelist, int entries)

{
int i;

if (namelist == NULL)
return 0;
else{

...
free(namelist[i]);
...
free(namelist);
Both lines above invoke UB when namelist is defined at function-scope
in main since by this point it still hasn't been set.
namelist = NULL;
Redundant assignment since the function is operating on a different copy
of the pointer than the caller and is about to return anyhow.
}

return 1;
}

--
http://members.dodo.com.au/~netocrat

tmp123

unread,
Jan 6, 2006, 4:32:24 AM1/6/06
to
Dieter wrote:
> int getFileNames(char *directory, struct dirent **namelist)
> {
> int n, i;
>
> n = scandir(directory, &namelist, 0, alphasort);


Hi,

As other groups members has remarked, the problem was in the call to
scandir (the program doesn't works if the variable is global and also
doesn't works if it is local. The only diference is how bad are the
effects).

I want only to remark two things about modify a function parameter:


a) The changes done to the value of a parameter will be always lost at
function return.
b) Change a parameter is under stylistic discussion (in particular, I
never do it. If necessary, I declare a local and init it with the
parameter value), and, who knows if allowed by standard. By example, a
SPARC CPU uses registers to pass parameters, so, the address of a
parameter is something that breaks to normal function prologs
(assembler code at start of fucntion).

In conclusion, any line of the kind "&parameter" must be carefully
reviewed.

Kind regards.

M.B

unread,
Jan 6, 2006, 5:37:01 AM1/6/06
to
Richard Heathfield wrote:
> M.B said:
>
> > its a pass by value v/s pass by reference issue
>
> Since C doesn't have pass by reference, it is clear to me that you are
> talking nonsense.
>
>
I presume u area c++ guy to talk like this.
pass by reference is a generic term for ur info.
C iimplements this by pointers.

- M.B

M.B

unread,
Jan 6, 2006, 8:30:09 AM1/6/06
to

Chuck F. wrote:
> M.B wrote:
> > sorry if thjis is a duplicate reply...
> >
> > I guess this is a scope issue for variable "namelist" I suggest
> > to change the function int getFileName(char *,struct dirent
> > ***); and make necessary changes to code. it may work fine
> >
> > bcoz scandir i guess sets "struct dirent **" itself. if its
> > global all is fine, but local variables 0 its problem-same as
> > pass by value
>
> Please use English, not dudespeak, in this newsgroup, and include
> adequate context. Between the two your article is totally
> meaningless. See below for further advice.

For letting out context, my mistake sorry.
English - hope this is not an english literature group. People want
answers and its enough if they get those in anyway. go hell with
correct English.

Also please check if the advice given in your signature works
correctly.

And finally, noone has time and patience to reply to trolls.

M.B

unread,
Jan 6, 2006, 9:48:22 AM1/6/06
to
I agree to some extend, but the question is whether we can push off any
queries just because they stray slightly in to an area beyond the group
topic (is this a sacred line ?).
in any case the problem here was not due to use of any non standard
functions etc (just that it was part of the code).

Keith Thompson

unread,
Jan 7, 2006, 3:26:00 AM1/7/06
to
"M.B" <mbpr...@gmail.com> writes:
> Chuck F. wrote:
>> M.B wrote:
>> > sorry if thjis is a duplicate reply...
>> >
>> > I guess this is a scope issue for variable "namelist" I suggest
>> > to change the function int getFileName(char *,struct dirent
>> > ***); and make necessary changes to code. it may work fine
>> >
>> > bcoz scandir i guess sets "struct dirent **" itself. if its
>> > global all is fine, but local variables 0 its problem-same as
>> > pass by value
>>
>> Please use English, not dudespeak, in this newsgroup, and include
>> adequate context. Between the two your article is totally
>> meaningless. See below for further advice.
>
> For letting out context, my mistake sorry.
> English - hope this is not an english literature group. People want
> answers and its enough if they get those in anyway. go hell with
> correct English.

You don't need to write flawless English, especially if it doesn't
happen to be your native language, but avoiding abbreviations like "u"
for "you" and "bcoz" for "because" make it *much* easier to understand
you.

> Also please check if the advice given in your signature works
> correctly.

As far as I know it does. Are you saying it doesn't?

> And finally, noone has time and patience to reply to trolls.

Chuck F. is not a troll. Trust me on this.

Richard Heathfield

unread,
Jan 7, 2006, 6:02:22 AM1/7/06
to
M.B said:

> Richard Heathfield wrote:
>> M.B said:
>>
>> > its a pass by value v/s pass by reference issue
>>
>> Since C doesn't have pass by reference, it is clear to me that you are
>> talking nonsense.
>>
>>
> I presume u area c++ guy to talk like this.

I don't know the u area. I'm from the UK. As for C++, no, I'm not talking
about C++.

> pass by reference is a generic term for ur info.

I've never been to ur. I repeat that C does not have pass by reference. If
you disagree, show me the part of the C Standard that supports your
viewpoint.

> C iimplements this by pointers.

In C, pointers are passed by value.

Joe Wright

unread,
Jan 7, 2006, 1:20:48 PM1/7/06
to
M.B wrote:
> Richard Heathfield wrote:
>
>>M.B said:
>>
>>
>>>its a pass by value v/s pass by reference issue
>>
>>Since C doesn't have pass by reference, it is clear to me that you are
>>talking nonsense.
>>
>>
>
> I presume u area c++ guy to talk like this.
> pass by reference is a generic term for ur info.
> C iimplements this by pointers.
>

M.B., you clearly don't know what 'pass by reference' means. C doesn't
do it, even with pointers. Whether C++ does it is of no interest here.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---

Jordan Abel

unread,
Jan 7, 2006, 1:59:14 PM1/7/06
to
On 2006-01-07, Joe Wright <joeww...@comcast.net> wrote:
> M.B wrote:
>> Richard Heathfield wrote:
>>
>>>M.B said:
>>>
>>>
>>>>its a pass by value v/s pass by reference issue
>>>
>>>Since C doesn't have pass by reference, it is clear to me that you are
>>>talking nonsense.
>>>
>>>
>>
>> I presume u area c++ guy to talk like this.
>> pass by reference is a generic term for ur info.
>> C iimplements this by pointers.
>>
>
> M.B., you clearly don't know what 'pass by reference' means. C doesn't
> do it, even with pointers. Whether C++ does it is of no interest here.

Yes it does. time() takes its argument by reference [as do many other
functions in time.h, for historical reasons] You are conflating a
generic concept with a specific feature C++ has that C does not.

Joseph Dionne

unread,
Jan 7, 2006, 2:19:35 PM1/7/06
to
Joe Wright wrote:
> M.B wrote:
>
>> Richard Heathfield wrote:
>>
>>> M.B said:
>>>
>>>
>>>> its a pass by value v/s pass by reference issue
>>>
>>>
>>> Since C doesn't have pass by reference, it is clear to me that you are
>>> talking nonsense.
>>>
>>>
>>
>> I presume u area c++ guy to talk like this.
>> pass by reference is a generic term for ur info.
>> C iimplements this by pointers.
>>
>
> M.B., you clearly don't know what 'pass by reference' means. C doesn't
> do it, even with pointers. Whether C++ does it is of no interest here.
>


Ah, newbies!

Definition of 'pass by reference'

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr233.htm

Keith Thompson

unread,
Jan 7, 2006, 3:20:56 PM1/7/06
to
Richard Heathfield <inv...@invalid.invalid> writes:
> M.B said:
[...]

> I've never been to ur. I repeat that C does not have pass by reference. If
> you disagree, show me the part of the C Standard that supports your
> viewpoint.
>
>> C iimplements this by pointers.
>
> In C, pointers are passed by value.

I think M.B has a point, though he didn't state it particularly
coherently.

No, the C doesn't directly support pass by reference, but, like many
other things, it does support it indirectly.

C doesn't support linked lists or binary trees, but they can easily be
implemented in C.

We all know what the relevant features of the C language are and how
they can be used to implement what other languages might implement
more directly. The only argument here is about the meaning of the
statement "C has pass-by-value" or "C supports pass-by-value"; this
debate would perhaps be more appropriate in an English usage
newsgroup.

Joseph Dionne

unread,
Jan 7, 2006, 3:51:17 PM1/7/06
to
Keith Thompson wrote:
> Richard Heathfield <inv...@invalid.invalid> writes:
>
>>M.B said:
>
> [...]
>
>>I've never been to ur. I repeat that C does not have pass by reference. If
>>you disagree, show me the part of the C Standard that supports your
>>viewpoint.
>>
>>
>>>C iimplements this by pointers.
>>
>>In C, pointers are passed by value.
>
>
> I think M.B has a point, though he didn't state it particularly
> coherently.
>
> No, the C doesn't directly support pass by reference, but, like many
> other things, it does support it indirectly.
>

In the context of passing a variable 'by reference' so that original 'object'
can be altered, c does indeed "pass by reference." In the context of passing
an immutable variable(object) so that the original 'object' remains unaltered
has morphed "pass by reference" from it's original definition since the
creation of the concept "pass by reference" pioneered by early language
developers.

> C doesn't support linked lists or binary trees, but they can easily be
> implemented in C.
>

The manor of how a data construct is passed to sub functions(methods) has no
relation to the data construct itself, i.e. a linked list, tree of any flavor,
or even "arrays". Any data container exceeding the ability of the cpu to
"store" the value in one of its processing registers is an artifact and the
cpu has no "intelligence" to directly use it.

A cpu "knows" how to add to primitive ints, but has not knowledge how to
concatenate two human readable "strings."

Richard Heathfield

unread,
Jan 7, 2006, 4:01:54 PM1/7/06
to
Keith Thompson said:

> Richard Heathfield <inv...@invalid.invalid> writes:
>> M.B said:
> [...]
>> I've never been to ur. I repeat that C does not have pass by reference.
>> If you disagree, show me the part of the C Standard that supports your
>> viewpoint.
>>
>>> C iimplements this by pointers.
>>
>> In C, pointers are passed by value.
>
> I think M.B has a point,

I don't.

> though he didn't state it particularly coherently.

Quite.

> No, the C doesn't directly support pass by reference, but, like many
> other things, it does support it indirectly.

I don't see that at all. All function argument expressions are evaluated and
those resulting *values* are given to the function concerned. A clearer
case of pass-by-value you could not hope to see.

The reason I think it matters is this: once a newcomer to C works out that
*everything* in C is pass-by-value, it makes the abstract machine much
easier to understand, much more obvious. There is a didactic value in
insisting on what is, after all, only the truth.

Keith Thompson

unread,
Jan 7, 2006, 4:31:26 PM1/7/06
to
Joseph Dionne <jdi...@hotmail.com> writes:
> Keith Thompson wrote:
>> Richard Heathfield <inv...@invalid.invalid> writes:
>>
>>>M.B said:
>> [...]
>>
>>> I've never been to ur. I repeat that C does not have pass by
>>> reference. If you disagree, show me the part of the C Standard that
>>> supports your viewpoint.
>>>
>>>>C iimplements this by pointers.
>>>
>>>In C, pointers are passed by value.
>> I think M.B has a point, though he didn't state it particularly
>> coherently.
>> No, the C doesn't directly support pass by reference, but, like many
>> other things, it does support it indirectly.
>
> In the context of passing a variable 'by reference' so that original
> 'object' can be altered, c does indeed "pass by reference." In the
> context of passing an immutable variable(object) so that the original
> 'object' remains unaltered has morphed "pass by reference" from it's
> original definition since the creation of the concept "pass by
> reference" pioneered by early language developers.
[...]

Sorry, but I don't understand what you mean. Are you disagreeing with
my statement that C doesn't support pass by reference indirectly, but
does support it indirectly?

We all know about emulating pass by reference using pointers. If
you're talking about something else, can you provide an example?

Keith Thompson

unread,
Jan 7, 2006, 4:40:34 PM1/7/06
to
Richard Heathfield <inv...@invalid.invalid> writes:
> Keith Thompson said:
>> Richard Heathfield <inv...@invalid.invalid> writes:
>>> M.B said:
>> [...]
>>> I've never been to ur. I repeat that C does not have pass by reference.
>>> If you disagree, show me the part of the C Standard that supports your
>>> viewpoint.
>>>
>>>> C iimplements this by pointers.
>>>
>>> In C, pointers are passed by value.
>>
>> I think M.B has a point,
>
> I don't.
>
>> though he didn't state it particularly coherently.
>
> Quite.
>
>> No, the C doesn't directly support pass by reference, but, like many
>> other things, it does support it indirectly.
>
> I don't see that at all. All function argument expressions are evaluated and
> those resulting *values* are given to the function concerned. A clearer
> case of pass-by-value you could not hope to see.
>
> The reason I think it matters is this: once a newcomer to C works out that
> *everything* in C is pass-by-value, it makes the abstract machine much
> easier to understand, much more obvious. There is a didactic value in
> insisting on what is, after all, only the truth.

Yes, it's important to understand that all function arguments in C are
passed by value. C doesn't have pass-by-reference as a language
feature. But it does support pass-by-reference as a programming
technique.

Suppose I have some Pascal code that uses pass-by-reference (no
guarantee that I've gotten the syntax correct):

function increment(var n: integer)
begin
n := n + 1;
end;

...

n : integer;
n := 42;
increment(n);

The translation to C is straightforward:

void increment(int *n)
{
(*n)++;
}

...

int n;
n = 42;
increment(&n);

Of course you're passing the address of n *by value* to the
increment() function. C doesn't directly support pass-by-reference.
But passing a pointer argument is how you, as a programmer, can
*implement* pass-by-reference.

(I'm 100% certain that I'm not telling you anything you don't already
know; the point is to figure out just where we disagree.)

Perhaps it would be clearer to use different names for the language
feature and the programming technique. I don't have any good ideas
about that. Since it's such a common technique, it should have a
pithier name than "passing the address of a variable so the function
can use it to modify the value of the variable itself".

Joseph Dionne

unread,
Jan 7, 2006, 4:42:11 PM1/7/06
to

I disagree with your assertion that c does not support pass by reference. I
am saying 'pass by reference' meant passing an address to variable memory in a
pointer, which by the way *is* a construct the cpu *knows* how to handle.

"pass by reference', since the creation of c++ and other OOP languages, has
been a new "meaning".

Joseph Dionne

unread,
Jan 7, 2006, 4:53:11 PM1/7/06
to

It has been twenty years since I coded pascal, I will dispute your pascal code
other than to ask is "increment(1)" syntactically correct and will the pascal
increment() increment memory address 0x0001?


But, the link below gives a good, concrete explanation of "pass by reference"
and "pass by value".

http://csis.pace.edu/~bergin/iticse2000/params.html

In your c code, increment(&n) *is* pass by reference simply because the
original memory can be altered, but I can code an increment() function for
pass by value too.

int increment(int ii) { return(ii+1); }

The original value of ii will remain unaltered, unless of course you code
ii = increment(ii);

Richard Heathfield

unread,
Jan 7, 2006, 4:56:11 PM1/7/06
to
Keith Thompson said:

> (I'm 100% certain that I'm not telling you anything you don't already
> know; the point is to figure out just where we disagree.)

I'm for whatever makes C easier to understand. Heaven knows it's hard enough
already, without making it harder.

When you say "pointers" and "pass by reference", yes, OF COURSE I know what
you mean. But J Random Newbie over there, who already has a hundred new
concepts buzzing around his head right now and who does not fully
understand what pointers *are* yet, let alone what they are *for*, is going
to think "pointers, right, the little * thing, okay, pass-by-reference,
right, * means pass by reference, which means I can update it, great..."
and he is going to think he understands things a little better - and then
he is (eventually) going to wonder why this:

void allocstr(char *s, size_t n)
{
s = malloc(n);

if(s == NULL) abort();
}

doesn't seem to do what he wants.

Joseph Dionne

unread,
Jan 7, 2006, 5:14:54 PM1/7/06
to
Richard Heathfield wrote:
> Keith Thompson said:
>
>
>>(I'm 100% certain that I'm not telling you anything you don't already
>>know; the point is to figure out just where we disagree.)
>
>
> I'm for whatever makes C easier to understand. Heaven knows it's hard enough
> already, without making it harder.
>
> When you say "pointers" and "pass by reference", yes, OF COURSE I know what
> you mean. But J Random Newbie over there, who already has a hundred new
> concepts buzzing around his head right now and who does not fully
> understand what pointers *are* yet, let alone what they are *for*, is going
> to think "pointers, right, the little * thing, okay, pass-by-reference,
> right, * means pass by reference, which means I can update it, great..."
> and he is going to think he understands things a little better - and then
> he is (eventually) going to wonder why this:
>
> void allocstr(char *s, size_t n)
> {
> s = malloc(n);
>
> if(s == NULL) abort();
> }
>
> doesn't seem to do what he wants.
>

A pointer can be passed by value, it that address of the memory storing an
address to memory used for "data", or passed by reference to "hide" it memory
address from the function called.

For example, using your allocstr() function called by value;

{
char *t;

allocstr(t,10);
}

Will not have the desired result, char pointer t will remain pointing at it
original ram address both before and after the call to allocstr(). However, I
can pass a reference to t, syntactically &s, that WILL have the desired result.

Further "by value" passing of pointers is strlen() implementation, for example;

int strlen(char *s)
{
int ii;

for(ii=0;*s;ii++);

return(ii);
}

{
char *t = "hello world";

strlen(t);
}

The t variable still points at 'h' because the contents of t is passed by
value, Pointers are primitives in c, just like char, int, and long.

Joseph Dionne

unread,
Jan 7, 2006, 5:23:57 PM1/7/06
to
Richard Heathfield wrote:
> Keith Thompson said:
>
>
>>(I'm 100% certain that I'm not telling you anything you don't already
>>know; the point is to figure out just where we disagree.)
>
>
> I'm for whatever makes C easier to understand. Heaven knows it's hard enough
> already, without making it harder.
>
> When you say "pointers" and "pass by reference", yes, OF COURSE I know what
> you mean. But J Random Newbie over there, who already has a hundred new
> concepts buzzing around his head right now and who does not fully
> understand what pointers *are* yet, let alone what they are *for*, is going
> to think "pointers, right, the little * thing, okay, pass-by-reference,
> right, * means pass by reference, which means I can update it, great..."
> and he is going to think he understands things a little better - and then
> he is (eventually) going to wonder why this:
>
> void allocstr(char *s, size_t n)
> {
> s = malloc(n);
>
> if(s == NULL) abort();
> }
>
> doesn't seem to do what he wants.
>

(Corrected. I'll reread what I type from now on.)

A pointer can be passed by value -- its contents,the address of the memory use
for "data" storage, to "hide" its address from the function called, or the
address location of the pointer itself can be passed by reference to "expose"
its "data content" to modification.

For example, using your allocstr() function called by value;

{
char *t;

allocstr(t,10);
}

Will not have the desired result, char pointer t will remain pointing at it
original ram address both before and after the call to allocstr(). However, I

can pass a reference to t, syntactically &t, that WILL have the desired result.

Further "by value" passing of pointers is strlen() implementation, for example;

int strlen(char *s)
{
int ii;

for(ii=0;*s;ii++);

return(ii);
}

{
char *t = "hello world";

strlen(t);
}

The t variable still points at 'h' because the contents of t is passed by
value, Pointers are primitives in c, just like char, int, and long.

Are we *debating* language syntax or capabilities?

Keith Thompson

unread,
Jan 7, 2006, 5:36:02 PM1/7/06
to
Joseph Dionne <jdi...@hotmail.com> writes:
> Keith Thompson wrote:
[...]

>> Suppose I have some Pascal code that uses pass-by-reference (no
>> guarantee that I've gotten the syntax correct):
>> function increment(var n: integer)
>> begin
>> n := n + 1;
>> end;
>> ...
>> n : integer;
>> n := 42;
>> increment(n);
>> The translation to C is straightforward:
>> void increment(int *n)
>> {
>> (*n)++;
>> }
>>
>> ...
>>
>> int n;
>> n = 42;
>> increment(&n);
> It has been twenty years since I coded pascal, I will dispute your
> pascal code other than to ask is "increment(1)" syntactically correct
> and will the pascal increment() increment memory address 0x0001?

<OT>
No, that's not a problem. In Pascal, for an ordinary (pass-by-value)
parameter, the argument can be any expression of the appropriate type.
For a var (pass-by-reference) parameter, the actual parameter must
be a variable.
</OT>

> In your c code, increment(&n) *is* pass by reference simply because
> the original memory can be altered, but I can code an increment()
> function for pass by value too.

The call increment(&n) passes the *value* of &n. This is used to
implement the equivalent of passing n by reference, something that the
C language doesn't directly support.

Keith Thompson

unread,
Jan 7, 2006, 5:40:31 PM1/7/06
to
Richard Heathfield <inv...@invalid.invalid> writes:
> Keith Thompson said:
>> (I'm 100% certain that I'm not telling you anything you don't already
>> know; the point is to figure out just where we disagree.)
>
> I'm for whatever makes C easier to understand. Heaven knows it's hard enough
> already, without making it harder.
>
> When you say "pointers" and "pass by reference", yes, OF COURSE I know what
> you mean. But J Random Newbie over there, who already has a hundred new
> concepts buzzing around his head right now and who does not fully
> understand what pointers *are* yet, let alone what they are *for*, is going
> to think "pointers, right, the little * thing, okay, pass-by-reference,
> right, * means pass by reference, which means I can update it, great..."
> and he is going to think he understands things a little better - and then
> he is (eventually) going to wonder why this:
>
> void allocstr(char *s, size_t n)
> {
> s = malloc(n);
>
> if(s == NULL) abort();
> }
>
> doesn't seem to do what he wants.

Then we need to make it very clear to J Random Newbie that C doesn't
support pass by reference as a languag construct. Don't say that the
"*" means pass by reference; say that the "*" means you're passing a
pointer value, which can be used to do the equivalent of pass by
reference. Until J Random Newbie is able to hold that entire complex
thought in his head, he's not going to be able to be an effective C
programmer.

Pass by reference is a very common and useful programming technique,
one that C supports quite well (though arguably a little more clumsily
than some other languages do).

Joe Wright

unread,
Jan 7, 2006, 5:49:59 PM1/7/06
to

I may have to look this up because an exact example eludes me right now.
In general, 'pass by reference' means that the argument the callee
receives is the object itself, not a pointer to it. Vague memory has it
that dBASE IV would pass by reference like..

MANY = 0

INCREMENT(MANY)

..would result in MANY being equal 1 because it was MANY, not its value
which is passed to INCREMENT().

PROCEDURE INCREMENT(N)
N = N + 1
RETURN

Joe Wright

unread,
Jan 7, 2006, 5:57:56 PM1/7/06
to

Not a newbie. The above URL is not a definition of 'pass by reference'
but an description of how to fake it.

Jordan Abel

unread,
Jan 7, 2006, 6:00:49 PM1/7/06
to

And uses it extensively in the standard library:

math.h: frexp, modf,
stdio.h: fscanf (and friends), fprintf (and friends, for %n), fgetpos,
fsetpos,
stdlib.h: strtol (and friends),
time.h: mktime, time, asctime, asctime, ctime, gmtime, localtime

Possibly others i've missed from later standards (this was written by
grepping c89 for (.*\*.*) and manually selecting the functions that use
this mechanism.

Joseph Dionne

unread,
Jan 7, 2006, 6:11:04 PM1/7/06
to

The *value* of a long is memory big enough to hold a define number data bits,
same for the *value* of int, and char variables. The *value* of a pointer
variable is the number of bits needed to hold a memory address, a special
purpose "integer" if you will. Admittedly, this duality is confusing.

I believe the confusion, and abuse of pointers derives from the duality in
nature of a pointer. Sure, one can "read/write" to a pointer, the it is the
"magic" of automatic dereferencing by the compiler. The pointer variable only
contains a memory address.

That is not to be confused that a pointer's value, the memory address of the
data to which it points, can be passed by reference or by value, regardless of
the syntax by which this is done.

Joseph Dionne

unread,
Jan 7, 2006, 6:12:28 PM1/7/06
to

Yes it does! The "language construct" is simply not one character, but two "&n".

Joseph Dionne

unread,
Jan 7, 2006, 6:13:41 PM1/7/06
to
Joe Wright wrote:
> Joseph Dionne wrote:
>
>> Joe Wright wrote:
>>
>>> M.B wrote:
>>>
>>>> Richard Heathfield wrote:
>>>>
>>>>> M.B said:
>>>>>
>>>>>
>>>>>> its a pass by value v/s pass by reference issue
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Since C doesn't have pass by reference, it is clear to me that you are
>>>>> talking nonsense.
>>>>>
>>>>>
>>>>
>>>> I presume u area c++ guy to talk like this.
>>>> pass by reference is a generic term for ur info.
>>>> C iimplements this by pointers.
>>>>
>>>
>>> M.B., you clearly don't know what 'pass by reference' means. C
>>> doesn't do it, even with pointers. Whether C++ does it is of no
>>> interest here.
>>>
>>
>>
>> Ah, newbies!
>>
>> Definition of 'pass by reference'
>>
>> http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr233.htm
>>
>
>
> Not a newbie. The above URL is not a definition of 'pass by reference'
> but an description of how to fake it.
>

Whatever!

Mark McIntyre

unread,
Jan 7, 2006, 6:14:35 PM1/7/06
to
On Sat, 07 Jan 2006 21:42:11 GMT, in comp.lang.c , Joseph Dionne
<jdi...@hotmail.com> wrote:

>> We all know about emulating pass by reference using pointers. If
>> you're talking about something else, can you provide an example?
>>
>
>I disagree with your assertion that c does not support pass by reference.

snip


>"pass by reference', since the creation of c++ and other OOP languages, has
>been a new "meaning".

This may be so, but the current meaning is the one that is current.
Once upon a time gay meant happy, and eye meant egg. You can see there
is opportunity for considerable confusion by using an archaic meaning.
Mark McIntyre
--

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----

Keith Thompson

unread,
Jan 7, 2006, 6:20:11 PM1/7/06
to
Joseph Dionne <jdi...@hotmail.com> writes:
[...]

> The *value* of a long is memory big enough to hold a define number
> data bits, same for the *value* of int, and char variables.

Ok. (One could question whether values are made of bits, but let's
not get into that.)

> The *value* of a pointer variable is the number of bits needed to
> hold a memory address, a special purpose "integer" if you will.

No, I won't. Pointers are not integers. Pointers are pointers.

> Admittedly, this duality is confusing.

The value of a pointer variable is a pointer value, also known as an
address. I don't know what duality you're referring to. Pointers and
integers are different things. One of the operations you can perform
on a pointer, dereferencing, happens to give you the value of what it
points to. As long as you keep this straight, it shouldn't be all
that confusing.


>
> I believe the confusion, and abuse of pointers derives from the
> duality in nature of a pointer. Sure, one can "read/write" to a
> pointer, the it is the "magic" of automatic dereferencing by the
> compiler. The pointer variable only contains a memory address.

What automatic dereferencing are you referring to? In C, pointers are
not implicitly dereferenced; that's what the unary "*" operator is
for. Can you provide an example, in C code, of what you're talking
about?

> That is not to be confused that a pointer's value, the memory address
> of the data to which it points, can be passed by reference or by
> value, regardless of the syntax by which this is done.

The value of a pointer (an address) can be passed *by value*. You can
effectively pass a pointer value by reference if you pass a
pointer-to-pointer; then you're passing the pointer-to-pointer by
value.

Joseph Dionne

unread,
Jan 7, 2006, 6:21:28 PM1/7/06
to

And, the whole topic gets even more confusing because of privative arrays,
i.e. int ii[5]. Here ii is "handled" as *both* a pointer and real memory
storage. Obviously one does not assign to the ii[] with "ii = 0" but uses a
subscript to isolate one int's actually memory storage address, i.e. "ii[0] =
0". However to pass the ii[] to a function(int *), the call can be simply
coded as "function((int *)ii)" with the cast only needed to fake out
prototyping compilers.

Joseph Dionne

unread,
Jan 7, 2006, 6:23:22 PM1/7/06
to
Mark McIntyre wrote:
> On Sat, 07 Jan 2006 21:42:11 GMT, in comp.lang.c , Joseph Dionne
> <jdi...@hotmail.com> wrote:
>
>
>>>We all know about emulating pass by reference using pointers. If
>>>you're talking about something else, can you provide an example?
>>>
>>
>>I disagree with your assertion that c does not support pass by reference.
>
> snip
>
>>"pass by reference', since the creation of c++ and other OOP languages, has
>>been a new "meaning".
>
>
> This may be so, but the current meaning is the one that is current.
> Once upon a time gay meant happy, and eye meant egg. You can see there
> is opportunity for considerable confusion by using an archaic meaning.
> Mark McIntyre

So when enough people refer to the period from sunrise to sunshine (the day)
as night, we all need to use their incorrect definition?

Keith Thompson

unread,
Jan 7, 2006, 6:43:05 PM1/7/06
to
Joseph Dionne <jdi...@hotmail.com> writes:
> Keith Thompson wrote:
[...]
>> Then we need to make it very clear to J Random Newbie that C doesn't
>> support pass by reference as a languag construct. Don't say that the
>> "*" means pass by reference; say that the "*" means you're passing a
>> pointer value, which can be used to do the equivalent of pass by
>> reference. Until J Random Newbie is able to hold that entire complex
>> thought in his head, he's not going to be able to be an effective C
>> programmer.
>> Pass by reference is a very common and useful programming technique,
>> one that C supports quite well (though arguably a little more clumsily
>> than some other languages do).
>>
>
> Yes it does! The "language construct" is simply not one character,
> but two "&n".

You're making Richard's point that we shouldn't talk about pass by
reference in C.

&n is simply an expression consisting of a unary "&" operator and an
identifier; it yields the address of n. *p is an expression
consisting of a unary "*" operator and an identifier; it dereferences
the pointer p and yields the value of the object it points to. These
constructs can be combined to implement the programming technique
known as pass by reference.

If you want to think of

void increment(int *p) ... increment(&n);

as "pass by reference", that's fine -- but you *must* understand that
it's built from lower-level constructs.

Note that a function with exactly the same interface:

void check_for_null(int *p)
{
if (p == NULL) {
fprintf(stderr, "p is a null pointer\n");
}
}

has nothing to do with pass by reference; it simply takes a pointer
parameter which is passed by value. Pointers aren't magical; they're
simply types with a particular set of operations that can be applied
to them.

Mark McIntyre

unread,
Jan 7, 2006, 6:47:35 PM1/7/06
to
On Sat, 07 Jan 2006 23:23:22 GMT, in comp.lang.c , Joseph Dionne
<jdi...@hotmail.com> wrote:

>Mark McIntyre wrote:
>> On Sat, 07 Jan 2006 21:42:11 GMT, in comp.lang.c , Joseph Dionne
>> <jdi...@hotmail.com> wrote:
>>
>>>"pass by reference', since the creation of c++ and other OOP languages, has
>>>been a new "meaning".
>>
>> This may be so, but the current meaning is the one that is current.
>

>So when enough people refer to the period from sunrise to sunshine (the day)
>as night, we all need to use their incorrect definition?

If you want to avoid confusion, and being thought of as a pompous ass,
yes IMHO. YMMV. HAND.

Joseph Dionne

unread,
Jan 7, 2006, 6:52:21 PM1/7/06
to
Keith Thompson wrote:
> Joseph Dionne <jdi...@hotmail.com> writes:
> [...]
>
>>The *value* of a long is memory big enough to hold a define number
>>data bits, same for the *value* of int, and char variables.
>
>
> Ok. (One could question whether values are made of bits, but let's
> not get into that.)
>
>
>>The *value* of a pointer variable is the number of bits needed to
>>hold a memory address, a special purpose "integer" if you will.
>
>
> No, I won't. Pointers are not integers. Pointers are pointers.
>
>
>>Admittedly, this duality is confusing.
>
>
> The value of a pointer variable is a pointer value, also known as an
> address. I don't know what duality you're referring to. Pointers and
> integers are different things. One of the operations you can perform
> on a pointer, dereferencing, happens to give you the value of what it
> points to. As long as you keep this straight, it shouldn't be all
> that confusing.
>

I can increment the memory address of the pointer, or I can alter the memory
to which the pointer points. This is not true for a privative long variable
who can only have it data altered. That is the "duality" of which I speak.

>>I believe the confusion, and abuse of pointers derives from the
>>duality in nature of a pointer. Sure, one can "read/write" to a
>>pointer, the it is the "magic" of automatic dereferencing by the
>>compiler. The pointer variable only contains a memory address.
>
>
> What automatic dereferencing are you referring to? In C, pointers are
> not implicitly dereferenced; that's what the unary "*" operator is
> for. Can you provide an example, in C code, of what you're talking
> about?
>

Using my strlen() example;

int strlen(char *s)
{
int ii;

for(ii=0;*s;ii++,s++) ;
return(ii);
}

{
char *t;

strlen(t);
}

One would "think" the strlen call would be "strlen(&t)" but that is incorrect
because the compiler "knows" t is already a pointer. The same is true for
this usage of a "pointer."

{
char a[32] = "hello world";

strlen(a);
}

Again the compiler *considers* a a pointer even though in fact it is simple
"label," as in assembler, to *mark* the start of a block of memory.

>
>>That is not to be confused that a pointer's value, the memory address
>>of the data to which it points, can be passed by reference or by
>>value, regardless of the syntax by which this is done.
>
>
> The value of a pointer (an address) can be passed *by value*. You can
> effectively pass a pointer value by reference if you pass a
> pointer-to-pointer; then you're passing the pointer-to-pointer by
> value.
>

So, your definition of "pass by reference" would be if *not* passing a pointer
to a pointer by value?

Joseph Dionne

unread,
Jan 7, 2006, 6:57:38 PM1/7/06
to
Keith Thompson wrote:
> Joseph Dionne <jdi...@hotmail.com> writes:
>
>>Keith Thompson wrote:
>
> [...]
>
>>>Then we need to make it very clear to J Random Newbie that C doesn't
>>>support pass by reference as a languag construct. Don't say that the
>>>"*" means pass by reference; say that the "*" means you're passing a
>>>pointer value, which can be used to do the equivalent of pass by
>>>reference. Until J Random Newbie is able to hold that entire complex
>>>thought in his head, he's not going to be able to be an effective C
>>>programmer.
>>>Pass by reference is a very common and useful programming technique,
>>>one that C supports quite well (though arguably a little more clumsily
>>>than some other languages do).
>>>
>>
>>Yes it does! The "language construct" is simply not one character,
>>but two "&n".
>
>
> You're making Richard's point that we shouldn't talk about pass by
> reference in C.
>
> &n is simply an expression consisting of a unary "&" operator and an
> identifier; it yields the address of n. *p is an expression
> consisting of a unary "*" operator and an identifier; it dereferences
> the pointer p and yields the value of the object it points to. These
> constructs can be combined to implement the programming technique
> known as pass by reference.

No way! '&' is a bit wise logical AND, to get the contents of a pointer, one
codes it as "&pointer" not "& pointer" which will generate an error.

Joseph Dionne

unread,
Jan 7, 2006, 7:01:42 PM1/7/06
to
Mark McIntyre wrote:
> On Sat, 07 Jan 2006 23:23:22 GMT, in comp.lang.c , Joseph Dionne
> <jdi...@hotmail.com> wrote:
>
>
>>Mark McIntyre wrote:
>>
>>>On Sat, 07 Jan 2006 21:42:11 GMT, in comp.lang.c , Joseph Dionne
>>><jdi...@hotmail.com> wrote:
>>>
>>>
>>>>"pass by reference', since the creation of c++ and other OOP languages, has
>>>>been a new "meaning".
>>>
>>>This may be so, but the current meaning is the one that is current.
>>
>>So when enough people refer to the period from sunrise to sunshine (the day)
>>as night, we all need to use their incorrect definition?
>
>
> If you want to avoid confusion, and being thought of as a pompous ass,
> yes IMHO. YMMV. HAND.
>
> Mark McIntyre

Sorry, Mr. McIntyre, software is a precision art, not hand grenades or
horseshoes. It has a history of development that ought not be forgotten or
convoluted by future misrepresentations simply because the originating concept
is difficult to grasp.

IHMO, and HAND to you.

Keith Thompson

unread,
Jan 7, 2006, 9:13:37 PM1/7/06
to
Joseph Dionne <jdi...@hotmail.com> writes:
> Keith Thompson wrote:
>> Joseph Dionne <jdi...@hotmail.com> writes:
>> [...]
>>
>>>The *value* of a long is memory big enough to hold a define number
>>>data bits, same for the *value* of int, and char variables.
>> Ok. (One could question whether values are made of bits, but let's
>> not get into that.)
>>
>>>The *value* of a pointer variable is the number of bits needed to
>>>hold a memory address, a special purpose "integer" if you will.
>> No, I won't. Pointers are not integers. Pointers are pointers.
>>
>>>Admittedly, this duality is confusing.
>> The value of a pointer variable is a pointer value, also known as an
>> address. I don't know what duality you're referring to. Pointers and
>> integers are different things. One of the operations you can perform
>> on a pointer, dereferencing, happens to give you the value of what it
>> points to. As long as you keep this straight, it shouldn't be all
>> that confusing.
>
> I can increment the memory address of the pointer, or I can alter the
> memory to which the pointer points. This is not true for a privative
> long variable who can only have it data altered. That is the
> "duality" of which I speak.

I'm sorry, but I really have no idea what you mean by "a privative
long variable who can only have it data altered". Does "privative"
mean "private" or "primitive"? Does "long" refer to the standard
integer type by that name, or something else? I'm not aware of any
data type on which the only operation you can perform is to alter its
data; such a thing wouldn't be terribly useful.

Duality between what and what, exactly?

The language defines certain operations on pointers, including
dereferencing and a limited set of arithmetic operators. (Some other
languages don't support pointer arithmetic, but we're talking about
C.) The fact that you can perform arithmetic on pointers doesn't
imply that pointers are some kind of integers. They can be
implemented that way, but as far as the language is concerned a
pointer is a pointer and an integer is an integer; conversions between
the two are possible, but the results are implementation-defined.

[...]

> Using my strlen() example;
>
> int strlen(char *s)
> {
> int ii;
> for(ii=0;*s;ii++,s++) ;
> return(ii);
> }
>
> {
> char *t;
>
> strlen(t);
> }
>
> One would "think" the strlen call would be "strlen(&t)" but that is
> incorrect because the compiler "knows" t is already a pointer.

Why on Earth would one expect the strlen call to be strlen(&t)? The
function expects an argument of type char*, and t is an object of type
char*, so the call should be strlen(t). Don't make it more
complicated than it is.

> The same is true for this usage of a "pointer."
>
> {
> char a[32] = "hello world";
>
> strlen(a);
> }
>
> Again the compiler *considers* a a pointer even though in fact it is
> simple "label," as in assembler, to *mark* the start of a block of
> memory.

Don't think of it as a "label" as in assembler.

a is an array object. An expression of array type, in most contexts,
is implicitly converted to a pointer to its first element; the
exceptions are the operand of a unary "sizeof" or "&" operator and a
string literal used to initialize an array. So the expression a is of
type char*, which is the expected argument thpe for strlen. Once you
understand this, there's no real problem.

You might want to review sections 4, 5, and C of the comp.lang.c FAQ
at <http://www.c-faq.com/>.

>>>That is not to be confused that a pointer's value, the memory address
>>>of the data to which it points, can be passed by reference or by
>>>value, regardless of the syntax by which this is done.
>> The value of a pointer (an address) can be passed *by value*. You
>> can effectively pass a pointer value by reference if you pass a
>> pointer-to-pointer; then you're passing the pointer-to-pointer by
>> value.
>
> So, your definition of "pass by reference" would be if *not* passing a
> pointer to a pointer by value?

The term "pass by reference" can refer to two different things. One
is a language feature (that doesn't exist in C). The other is a
programming technique that can implemented in C by using pointers.
(It's been argued that this shouldn't be referred to as pass by
reference.)

You can't *directly* pass anything by reference in C. If you want to
emulate passing something by reference, the way to do that is to use a
pointer. In general, to emulate passing a FOO by reference, you do it
by passing a FOO* (a pointer-to-FOO) by value. It doesn't matter what
FOO is; you pass an int by reference by passing a pointer-to-int, you
pass a struct by reference by passing a pointer-to-struct, and you
pass a pointer-to-whatever by reference by passing a
pointer-to-pointer-to-whatever.

Keith Thompson

unread,
Jan 7, 2006, 9:17:54 PM1/7/06
to
Joseph Dionne <jdi...@hotmail.com> writes:
[...]
> And, the whole topic gets even more confusing because of privative
> arrays, i.e. int ii[5]. Here ii is "handled" as *both* a pointer and
> real memory storage.

No, it's an array, but its name is implicitly converted to a pointer
value in most contexts. (There is no pointer object involved.)

> Obviously one does not assign to the ii[] with
> "ii = 0" but uses a subscript to isolate one int's actually memory
> storage address, i.e. "ii[0] = 0". However to pass the ii[] to a
> function(int *), the call can be simply coded as "function((int *)ii)"
> with the cast only needed to fake out prototyping compilers.

Given the declaration
int ii[5];
the expression
ii
is already of type int*. Casting it to int* is unnecessary and
potentially dangerous.

All modern C compilers are "prototyping", if that means that they
support function prototypes. If you can show us an example where you
think it's necessary to "fake out" the compiler, we can probably
explain why it's unnecessary and/or a bad idea.

Keith Thompson

unread,
Jan 7, 2006, 9:28:10 PM1/7/06
to
Joseph Dionne <jdi...@hotmail.com> writes:
[...]
> No way! '&' is a bit wise logical AND, to get the contents of a
> pointer, one codes it as "&pointer" not "& pointer" which will
> generate an error.

I'm beginning to suspect that you may be a deliberate troll. Do you
seriously believe that what you've just written above is correct? I
don't mean to be insulting, but the number of fundamental errors in
that paragraph is astonishing.

There are two "&" operators in C, a binary operator (taking two
operand) that performs a bitwise logical AND, and a unary operator
(taking one operand) that yields the address of its operand.

The expressions "&pointer" and "& pointer" are precisely equivalent.
The amount of whitespace between the operator and the operand is not
significant. The compiler is able to distinguish between unary and
binary "&" by the context in which it appears.

The unary "&" operator doesn't yield the contents of a pointer; it
yields the address of an object.

I suggest you read a good C textbook (K&R2 is very good). You have a
lot of things to unlearn.

(Or if you're doing this deliberately, please please please go away;
it's not amusing.)

Chris Torek

unread,
Jan 7, 2006, 11:05:45 PM1/7/06
to
In article <9RVvf.3521$ZA2....@newsread1.news.atl.earthlink.net>
and numerous others, Joseph Dionne <jdi...@hotmail.com> wrote ...
well, a whole lot, not too much of it especially good, about whether
C has "pass by reference".

The key item that C lacks -- but C++ and Pascal have, that make
those two languages actually possess pass-by-reference -- is an
"implicit dereference".

In Pascal, we can write (where T is some type, either one predefined
by the language or one we have defined ourselves):

procedure foo(var n : T); begin
... operate on n ...
end;

In C++, we can write:

void foo(T & n) {
... operate on n ...
}

In both cases, we cannot, in foo(), "re-bind" n to refer to some
other variable. It always and forever -- or at least until foo()
returns, so that it ceases to exist -- refers to the parameter
supplied by the caller. This is a useful and common property of
language-provided pass-by-reference, but (I claim) not actually
necessary.

More importantly, in both cases, in order to change the caller's
variable, we do something like this in foo():

n = 42; /* for C++; in Pascal, use n := 42 */

Note that we do not adorn the variable name "n" with any special
punctuators or operators here. We use the same syntax we would
use if n were a local variable. (I include this second sentence
because in some languages, for which one might argue whether they
possess by-reference arguments, even ordinary local variables
require some sort of punctuation in order to assign values to
them.)

In both cases, the caller then does nothing to distinguish the
by-reference call from a by-value call:

foo(x); /* modifies x */
bar(x); /* does not modify x */

This means the programmer must know whether any given function or
procedure modifies any of its arguments. (It is not clear to me
that this last is a *required* property. If there were a language
in which the declaration and/or definition of foo() itself made it
clear that a parameter n was by-reference, but also forced callers
to acknowledge the by-reference call, would the language meet the
definition of "by reference" calls? I am not aware of any such
language, and without one, I think the question is moot.)

In C, by contrast, in order for a funtion foo() to change its
caller's variable, we must adorn not only the call:

foo(&x); /* permits foo to modify x */

but more importantly, we must decorate every use of "n" within
foo() itself:

void foo(T * n) {
... operate on *n ...
}

If, within foo(), we attempt to operate on "n" instead of "*n",
we "re-bind" n to point to some other object of type T. This is
impossible in Pascal and C++ (and Fortran at least through F77,
for that matter, although Fortran allows value-result instead
of by-reference).

Mr Dionne appears to believe that C's arrays are an exception, and
are passed by reference. While C's arrays *are* exceptional, this
is not where the exception occurs. C remains pass-by-value. The
gimmick is that the "value" of an array is a pointer to the array's
first element. In:

void f(void) {
char buf[100];
char *p;

p = buf;

we attempt to copy the "value" of buf -- an array -- to the pointer
variable p. The "value" of the array is a pointer to the array's
first element, so this sets p to point to &buf[0]. Likewise, if we
go on to call a function g() and pass the "value" of buf:

g(buf);
...
}

then g() receives, as its value, a pointer to the array's first
element -- a pointer to buf[0]. Within g(), as for any simulation
of by-reference in C, we have to use the unary "*" operator in
order to write to buf[0]:

void g(char * ptr) {
* ptr = 42;
...
}

and if we fail to prefix "ptr" with the unary "*" operator when
assigning, we will "re-bind" it so that it no longer points to
"buf" at all:

ptr = "oops";

Now *ptr is no longer 42 (in any current character set anyway):
ptr now points to the first element of an anonymous (unnamed) array
of 5 "char"s that are set to {'o','o','p','s','\0'} and must not
be changed (they may or may not actually be read-only, but the
effect of attempting to change them is undefined).

The sneaky part of this is that, given a pointer to buf[0] -- and
no reassignment of ptr itself, i.e., leave out the "oops" line --
we can use that pointer to access buf[1] through buf[99] as well.
That is why, in f() and g() both, we can do:

p[23] = 'x'; /* in f() */

or:

ptr[24] = 'y'; /* in g() */

None of this has much to do with calling mechanisms. The array /
pointer interconversion rules in C happen long before any concerns
with parameter-passing. It is merely the case that, because calls
*are* by-value and the "value" of an array is a pointer to its
first element, function calls are a very common point at which
the interconversion occurs.

The other syntactic gimmick that trips people up is that C allows
the programmer to lie about certain parameter types. If some
function receives a pointer of type "pointer to T", the programmer
is allowed to declare the formal parameter *as if* it had type
"array N of T". (The array size can be included or omitted.
Except for the new C99 meaning for "static", the size is not
used.) Hence, we can write the following:

#include <stdio.h>

void h(char paramvar[100]) {
char localvar[100];

printf("sizeof paramvar: %lu\n",
(unsigned long)sizeof paramvar);
printf("sizeof localvar: %lu\n",
(unsigned long)sizeof localvar);
}

Actually *executing* this function, however, is instructive:
the output is typically:

sizeof paramvar: 4 (or sometimes 2 or 8; rarely, 1)
sizeof localvar: 100 (always exactly 100)

In addition, we can demonstrate that "paramvar" actually has type
"char *" -- not "char [100]" -- by re-binding it:

void h(char paramvar[100]) {
char localvar[100];
char other[100];

printf("sizeof paramvar: %lu\n",
(unsigned long)sizeof paramvar);
printf("sizeof localvar: %lu\n",
(unsigned long)sizeof localvar);
paramvar = localvar; /* OK */
localvar = other; /* ERROR */
}

A diagnostic is required (and occurs) for the assignment to localvar,
because arrays are not modifiable lvalues (although the form of
the error message is not dictated by the standard and it is often
a bit peculiar). No diagnostic is required, and generally none
occurs, for the assignment to paramvar, because it is not an array;
its type is "char *", not "char [100]".

The Standard actually says that the type is to be rewritten by the
compiler:

... A
declaration of a parameter as ``array of type'' shall be
adjusted to ``pointer to type,'' and a declaration of a
parameter as ``function returning type'' shall be adjusted
to ``pointer to function returning type,'' as in 6.2.2.1.

(C99 draft, section 6.7.1). (The second part of the sentence above
means that you can define a function that takes another function,
instead of using the function-pointer syntax:

void operate(T f(args));

and

void operate(T (*f)(args));

mean the same thing in a prototype, and either version can be used
in the definition of the function "operate".)

Finally, it is worth pointing out that, in languages that have or
allow by-reference function calls, it may (or may not, depending on
the language definition) be possible to discover whether the compiler
actually uses by-reference, or simulates it with value-result. The
following C++ program fragment (though using printf() instead of cout)
illustrates a feature of by-reference:

int globalvar;

void f(int& x) {
x = 42;
printf("globalvar is now %d\n", globalvar);
x = 43;
}

int main(void) {
globalvar = 1;
f(globalvar);
printf("globalvar is now %d\n", globalvar);
}

The output of this program *must* be:

globalvar is now 42
globalvar is now 43

If this program is converted to Fortran 77 in the obvious way,
the effect of the program becomes undefined. Actually running it
may produce:

globalvar is now 1
globalvar is now 43

In this case, the compiler used value-result. This value-result
mechanism can be simulated in C as:

int globalvar;

void f(int *xp) {
int x = *xp;

x = 42;
printf("globalvar is now %d\n", globalvar);
x = 43;

*xp = x;
}

int main(void) {
globalvar = 1;
f(&globalvar);
printf("globalvar is now %d\n", globalvar);
}

The difference between by-reference and value-result is that, in
by-reference every occurrence of the apparently-ordinary variable
within a given function/procedure is -- at least before optimization
-- turned into an appropriate dereference. In the value-result
case, however, the value is passed to the callee, and the callee
returns a new result to be stored back in the original variable.
The effect is that there is a single dereference at entry to the
function/procedure, and a second one at exit. (Whether the copy
occurs in the callee, as in the C simulation, or the caller, is up
to the compiler -- the difference is not generally detectable.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.

Joseph Dionne

unread,
Jan 7, 2006, 11:51:47 PM1/7/06
to
Keith Thompson wrote:
> Joseph Dionne <jdi...@hotmail.com> writes:
> [...]
>
>>No way! '&' is a bit wise logical AND, to get the contents of a
>>pointer, one codes it as "&pointer" not "& pointer" which will
>>generate an error.
>
>
> I'm beginning to suspect that you may be a deliberate troll. Do you
> seriously believe that what you've just written above is correct? I
> don't mean to be insulting, but the number of fundamental errors in
> that paragraph is astonishing.
>
> There are two "&" operators in C, a binary operator (taking two
> operand) that performs a bitwise logical AND, and a unary operator
> (taking one operand) that yields the address of its operand.
>
> The expressions "&pointer" and "& pointer" are precisely equivalent.
> The amount of whitespace between the operator and the operand is not
> significant. The compiler is able to distinguish between unary and
> binary "&" by the context in which it appears.
>
> The unary "&" operator doesn't yield the contents of a pointer; it
> yields the address of an object.
>
> I suggest you read a good C textbook (K&R2 is very good). You have a
> lot of things to unlearn.
>
> (Or if you're doing this deliberately, please please please go away;
> it's not amusing.)
>

It is just as amusing as you assertion, backed by no well known authority of
the c language specification, that c does not support pass by reference.

Your continued reference to 'object' during replies proves my assertions --
recent OOP development (decades ago implemented recent, I mean) have
obfuscated the meaning of "pass by reference". I suspect this is due mostly
to the declining software knowledge, and skills, that has again raised the
acclaim and praise for "garbage collection" languages.

Show me any authority that shares you "opinion" that c does not "pass by
reference".

Joseph Dionne

unread,
Jan 8, 2006, 12:10:44 AM1/8/06
to
Chris Torek wrote:

[..]

Look who is being humorous. Sir, in you example, "buf" will never change is
memory value, even *if* you pass it by reference, "& buf". You might cause a
program error, but buf will forever point to the same memory address.


[..]

I think we all can agree the pascal and c++ support pass by reference by
different syntax. I assert the c uses yet another syntax to implement pass by
reference, nothing more or less.

Chuck F.

unread,
Jan 7, 2006, 11:45:29 PM1/7/06
to
Joseph Dionne wrote:
>
... big fat snip ...

>
> It has been twenty years since I coded pascal, I will dispute
> your pascal code other than to ask is "increment(1)"
> syntactically correct and will the pascal increment() increment
> memory address 0x0001?

No it isn't correct, and should provoke an error similar to
"Attempt to load the address of an expression".

In general pass by reference passes by referring to the thing to be
passed, not to its address. C does not do this. The caller has to
pass the address, often by an & operator. The user has the choice
of operating on that address (a no-no for pass by reference) or of
dereferencing it with the * operator.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>

Nelu

unread,
Jan 8, 2006, 12:21:58 AM1/8/06
to
On 2006-01-08, Joseph Dionne <jdi...@hotmail.com> wrote:
>
> It is just as amusing as you assertion, backed by no well known authority of
> the c language specification, that c does not support pass by reference.
>
> Your continued reference to 'object' during replies proves my assertions --
> recent OOP development (decades ago implemented recent, I mean) have
> obfuscated the meaning of "pass by reference". I suspect this is due mostly
> to the declining software knowledge, and skills, that has again raised the
> acclaim and praise for "garbage collection" languages.
>
> Show me any authority that shares you "opinion" that c does not "pass by
> reference".

Arguments are always passed by value in C function calls, meaning that local copies of the values of the arguments are passed to the routines. Changes that you may make to the arguments in the function are made only to the local copies of the arguments. Passing by reference means you can change the value of the argument outside the scope of your function, which doesn't happen. If you have a function like: void foo(char *a) you cannot change the value of the argument, but you can change the content of the memory that the address points to. Pass-by-xxxx refers to the way the arguments are passed to the function and, in C, it's always by value. The fact that the function can change the value at the address your pointer points to is just a side-effect and has nothing to do with how the arguments are passed.

I don't remember exatly and I don't have a copy of the book right now, but I think K&R says that arguments are always passed by value in C function calls. No one will say anything about pass by reference because there's no such thing in C.

JAVA is a languae where everything's a reference. JAVA also passes the arguments to functions by value *only* (if you don't believe me check the documentation), but you can change the elements of an array that's passed to a function and it doesn't mean that array was passed by reference.

If I remember correctly in C++:

void foo(int &i) {
i=2;
}
...
int i=0;
foo(i)
=> i=2

type is int, you send int, int is changed in the function. That's pass by reference.

in C:

void foo(int *i) {
*i=2;
}
...
int i=0;
foo(&i);
=> i=2

type is int, you send a pointer to int, int is changed in the function. The functions doesn't tell you that it needs an int to change an int. It tells you it needs a pointer to int that it can't change.
Although you can consider &int a reference to an int, the function doesn't ask for a reference but for a type which is called "pointer to int" and what you send is the value of a pointer to int type.

--
Ioan - Ciprian Tandau
tan...@freeshell.org

Joseph Dionne

unread,
Jan 8, 2006, 12:26:11 AM1/8/06
to
Nelu wrote:
> On 2006-01-08, Joseph Dionne <jdi...@hotmail.com> wrote:
>
>>It is just as amusing as you assertion, backed by no well known authority of
>>the c language specification, that c does not support pass by reference.
>>
>>Your continued reference to 'object' during replies proves my assertions --
>>recent OOP development (decades ago implemented recent, I mean) have
>>obfuscated the meaning of "pass by reference". I suspect this is due mostly
>>to the declining software knowledge, and skills, that has again raised the
>>acclaim and praise for "garbage collection" languages.
>>
>>Show me any authority that shares you "opinion" that c does not "pass by
>>reference".
>
>
> Arguments are always passed by value in C function calls, meaning that local copies of the values of the arguments are passed to the routines. Changes that you may make to the arguments in the function are made only to the local copies of the arguments. Passing by reference means you can change the value of the argument outside the scope of your function, which doesn't happen. If you have a function like: void foo(char *a) you cannot change the value of the argument, but you can change the content of the memory that the address points to. Pass-by-xxxx refers to the way the arguments are passed to the function and, in C, it's always by value. The fact that the function can change the value at the address your pointer points to is just a side-effect and has nothing to do with how the arguments are passed.
>
> I don't remember exatly and I don't have a copy of the book right now, but I think K&R says that arguments are always passed by value in C function calls. No one will say anything about pass by reference because there's no such thing in C.
>
> JAVA is a languae where everything's a reference. JAVA also passes the arguments to functions by value *only* (if you don't believe me check the documentation), but you can change the elements of an array that's passed to a function and it doesn't mean that array was passed by reference.
>
> If I remember correctly in C++:
>
> void foo(int &i) {
> i=2;
> }
> ...
> int i=0;
> foo(i)
> => i=2
>
> type is int, you send int, int is changed in the function. That's pass by reference.
>

It is pass by reference *because* i can and is modified. So to is i modified
in c, only the syntax has been changed to protect the innocent?

Nelu

unread,
Jan 8, 2006, 12:27:29 AM1/8/06
to
On 2006-01-08, Nelu <tan...@freeshell.org> wrote:
<something about pass by reference>

Really sorry for the last post. I switched, recently,
from google groups to slrn and I didn't know it
knows not how to cut long lines. It's the first time
I use it...
I'll remember this for the future.
Also, from slrn it's easier to understand why keeping
some context when repying is useful :-).

Nelu

unread,
Jan 8, 2006, 12:39:22 AM1/8/06
to
On 2006-01-08, Joseph Dionne <jdi...@hotmail.com> wrote:
> It is pass by reference *because* i can and is modified. So to is i modified
> in c, only the syntax has been changed to protect the innocent?
In the C function I posted &i is the argument not i.
The i outside the function is modified but that i is not
the same as the one in the function. Modifying the i in the function
has no effect on the i outside the function. The i outside the function
is modified by modifying something different in the function,
i.e. *i which is not the variable you passed to the function.
Even if this is a mechanism that allows for the implementation of
pass-by-reference, it's not the same thing. You can say that
pass-by-reference can hide a pass-by-value but not that a pass-by-value
hides a pass-by-reference (otherwise it means that making a change
to the copy automatically changes the original, which doesnt't happen),
so they are not the same thing.

Lew Pitcher

unread,
Jan 8, 2006, 12:30:11 AM1/8/06
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Joseph Dionne wrote:
> Keith Thompson wrote:
>
>> Joseph Dionne <jdi...@hotmail.com> writes:
>> [...]
>>
>>> No way! '&' is a bit wise logical AND, to get the contents of a
>>> pointer, one codes it as "&pointer" not "& pointer" which will
>>> generate an error.

Fortunately, the C language has rules that permit implementations to
distinguish between a "binary bitwise logical and" operator and a "unary
prefix address of" operator, even if they both share the same translation token.

Are you telling me that

{
int a = 7, b = 4, *c;

c = & a;
}

will result in a syntax error? I think not.

>> I'm beginning to suspect that you may be a deliberate troll.

[snip]


>> The unary "&" operator doesn't yield the contents of a pointer; it
>> yields the address of an object.

[snip]


>
> It is just as amusing as you assertion, backed by no well known
> authority of the c language specification, that c does not support pass
> by reference.

- From the C 9989-1999 proposed standard (and, IIRC, from previous C standards,
all the way back to K&R C and forward to the accepted C'99 standard)

6.5.2.2 Function Calls

4 An argument may be an expression of any object type. In preparing for a
call to the function, the arguments are evaluated, and each parameter is
assigned the value of the corresponding argument.

Sounds like the standard says "pass by value" to me. And it doesn't say "pass
by reference" anywhere in it.

Perhaps you've become fooled by the mechanics of pointer variables. Passing
pointers to functions can /look/ like "pass by reference" even though it is
actually "pass by value". Consider the following code fragments

void foo(int *a)
{
/* body of function foo */
*a = 8;
}

void bar(void)
{
int q = 6;
foo(&q);
}

In the above functions, you might think that "pass by reference" is being
used, but it is not.

In the context of the function call to foo() ( "foo(&q);" )
q is an object of type int.

&q is another object (a temporary one crafted by the language to serve as a
vehicle to pass data to a function) of type "pointer to int"

q has a value of 6
&q has a value of a pointer to q

Function foo() will receive the /value/ of the temporary object &q. It does
not receive a /reference/ to q (or even to the temporary &q). It's as if that
original function had been coded as
void bar(void)
{
int q = 6;
int *pq = &q;

foo(pq); /* still pass by value, just value of pq */
}

> Your continued reference to 'object' during replies proves my assertions
> -- recent OOP development (decades ago implemented recent, I mean)

Well, Keith is using the word "object" in the same manner (and apparently with
the same meaning) as the C standard (and it's predecessor documents) does.

- From the C 9989-1999 proposed standard document section 3 ("Terms, definitions
and Symbols"):

3.14
object
region of data storage in the execution environment, the contents of which
can represent values

C 9989-1999 goes on using the word "object" throughout it's text, in exactly
the context that Keith has used it. I'm afraid that you don't have any choice
but to accept this terminology, recent OOP usage or not.

> have
> obfuscated the meaning of "pass by reference". I suspect this is due
> mostly to the declining software knowledge, and skills, that has again
> raised the acclaim and praise for "garbage collection" languages.
>
> Show me any authority that shares you "opinion" that c does not "pass by
> reference".

I think that the C standards should be sufficient authority to confirm Keith's
"opinion".

- --
Lew Pitcher

Master Codewright & JOAT-in-training | GPG public key available on request
Registered Linux User #112576 (http://counter.li.org/)
Slackware - Because I know what I'm doing.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.7 (GNU/Linux)

iD8DBQFDwKNjagVFX4UWr64RAvDrAJ9JRNN/WaXaq0J4O4egJiuRwCtNiQCeN/y5
ou4vGFXt3wBzmmUDCwCz/+I=
=p6kP
-----END PGP SIGNATURE-----

Lew Pitcher

unread,
Jan 8, 2006, 12:38:29 AM1/8/06
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Nelu wrote:
> On 2006-01-08, Joseph Dionne <jdi...@hotmail.com> wrote:
>
>>It is just as amusing as you assertion, backed by no well known authority of
>>the c language specification, that c does not support pass by reference.
>>
>>Your continued reference to 'object' during replies proves my assertions --
>>recent OOP development (decades ago implemented recent, I mean) have
>>obfuscated the meaning of "pass by reference". I suspect this is due mostly
>>to the declining software knowledge, and skills, that has again raised the
>>acclaim and praise for "garbage collection" languages.
>>
>>Show me any authority that shares you "opinion" that c does not "pass by
>>reference".
>
>
> Arguments are always passed by value in C function calls, meaning that
> local copies of the values of the arguments are passed to the routines.

[snip]


> I don't remember exatly and I don't have a copy of the book right now,
> but I think K&R says that arguments are always passed by value in C function
> calls. No one will say anything about pass by reference because there's no
such thing in C.

You are correct.

K&R C (First edition) says

"In preparing for the call to a function, a copy is made of each actual
parameter; thus, all argument-passing in C is strictly by value."

(Appendix A: C Reference Manual, "The C Programming Language", Brian W.
Kernighan & Dennis M. Ritchie, Copyright 1978 by Bell Telephone Laboratories,
Incorporated, Published by Prentice-Hall, Inc.)


[snip]

- --
Lew Pitcher

Master Codewright & JOAT-in-training | GPG public key available on request
Registered Linux User #112576 (http://counter.li.org/)
Slackware - Because I know what I'm doing.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.7 (GNU/Linux)

iD8DBQFDwKVVagVFX4UWr64RAv9TAKC564WPjQqJmYXWaCQkRp3X3j3vCQCfXWPG
Jbi1XWwB3A3vCNa0SQTfGac=
=kjjN
-----END PGP SIGNATURE-----

Joseph Dionne

unread,
Jan 8, 2006, 12:53:59 AM1/8/06
to

The syntax difference in c++ is sexier, easier for those new to the language
to implement with less debug time, but is nothing more than using the
principle of passing a reference to a variable in order to modify the original
memory contents.

A custom c pre processor can simulate the same syntax, even support both
syntax, but that would most likely introduce more developer coding bugs not
less as desired.

I will only agree to disagree with the assertions made that "pass by
reference" is more about language syntax than language capability. Pass by
reference as a principle is well defined, and c complies with the definition.

Now this *troll* needs to get on with real world work, as some suggest I lack.

Cheers to all, the discussion was enlightening.

Richard Heathfield

unread,
Jan 8, 2006, 12:59:16 AM1/8/06
to
Joseph Dionne said:

> A pointer can be passed by value,

Yes, I know. In fact, that is the only way it can be passed directly as a
function argument.

> it that address of the memory storing an
> address to memory used for "data", or passed by reference to "hide" it
> memory address from the function called.

No, it can't be passed by reference.

>
> For example, using your allocstr() function called by value;
>
> {
> char *t;
>
> allocstr(t,10);
> }
>
> Will not have the desired result,

Gosh.

> char pointer t will remain pointing at
> it
> original ram address both before and after the call to allocstr().

Is that right?

> However, I can pass a reference to t, syntactically &s, that WILL have the
> desired result.

No, you can't, because it's the wrong type, and in any case passing *a*
reference is not the same as passing *by* reference.

Note for terminology bigots: "The technical term used in programming
languags for an address of a location in memory is a /reference/ because it
/refers/ to a memory location." - Bruce Maclennan, "Principles of
Programming Languages", p57). The C Standard does not appear to use the
word in this way, however; at least, neither the C89 draft nor N869.
(Searching a PDF is like searching your spam for email, so I didn't look in
C99 Final.)


> Further "by value" passing of pointers is strlen() implementation, for
> example;
>
> int strlen(char *s)

If that's how you implement strlen, remind me not to use your
implementation.

> {
> int ii;
>
> for(ii=0;*s;ii++);

Undefined behaviour when (not if) ii overflows. It will overflow for all
strings except the empty string.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

Richard Heathfield

unread,
Jan 8, 2006, 1:02:18 AM1/8/06
to
Keith Thompson said:

> Then we need to make it very clear to J Random Newbie that C doesn't
> support pass by reference as a languag construct.

Right.

> Don't say that the
> "*" means pass by reference; say that the "*" means you're passing a
> pointer value, which can be used to do the equivalent of pass by
> reference.

To a newbie, the two statements can seem equivalent, especially if he
doesn't know what "pass by reference" is and has to go and look it up. Why
use the phrase at all, when it doesn't add any value?

> Until J Random Newbie is able to hold that entire complex
> thought in his head, he's not going to be able to be an effective C
> programmer.

We can ease that journey by not giving him useless junk to remember.

> Pass by reference is a very common and useful programming technique,
> one that C supports quite well (though arguably a little more clumsily
> than some other languages do).

I know what you're saying, but I think that's an own-foot-shooting way to
say it.

Nejat AYDIN

unread,
Jan 8, 2006, 1:00:10 AM1/8/06
to
Joseph Dionne wrote:
[...]

>
> Show me any authority that shares you "opinion" that c does not "pass by
> reference".

"In preparing for the call to a function, a copy is made of each
argument; all argument-passing is strictly by value."
The C Programming Language, Second edition.
Brian W. Kernighan, Dennis M. Ritchie
A7.3.2 Function Calls (pages 201, 202)

Richard Heathfield

unread,
Jan 8, 2006, 1:06:48 AM1/8/06
to
Joe Wright said:

> Jordan Abel wrote:
>> [...] time() takes its argument by reference [as do many other
>> functions in time.h, for historical reasons] You are conflating a
>> generic concept with a specific feature C++ has that C does not.
>
> I may have to look this up because an exact example eludes me right now.

You needn't bother - Jordan is wrong about time() which does not in fact
take its argument by reference. It takes its parameter by value. The
argument is evaluated, and that value passed to time(). It's just like any
other parameter-taking C function in that regard.

Richard Heathfield

unread,
Jan 8, 2006, 1:15:59 AM1/8/06
to
Joseph Dionne said:

> No way! '&' is a bit wise logical AND, to get the contents of a pointer,
> one codes it as "&pointer" not "& pointer" which will generate an error.

Case closed, I think, as far as Mr Dionne is concerned.

Troll, idiot, or newbie. In this case, I don't really see the point in
trying to distinguish between them.

Richard Heathfield

unread,
Jan 8, 2006, 1:38:54 AM1/8/06
to
Joseph Dionne said:

> Look who is being humorous. Sir, in you example, "buf" will never change
> is
> memory value, even *if* you pass it by reference, "& buf".

That isn't passing buf by reference. It's passing the address of buf by
value.

Keith Thompson

unread,
Jan 8, 2006, 2:14:20 AM1/8/06
to
Joseph Dionne <jdi...@hotmail.com> writes:
> Keith Thompson wrote:
>> Joseph Dionne <jdi...@hotmail.com> writes:
>> [...]
>>>No way! '&' is a bit wise logical AND, to get the contents of a
>>>pointer, one codes it as "&pointer" not "& pointer" which will
>>>generate an error.
[...]

>> There are two "&" operators in C, a binary operator (taking two
>> operand) that performs a bitwise logical AND, and a unary operator
>> (taking one operand) that yields the address of its operand.
>> The expressions "&pointer" and "& pointer" are precisely equivalent.
>> The amount of whitespace between the operator and the operand is not
>> significant. The compiler is able to distinguish between unary and
>> binary "&" by the context in which it appears.
>> The unary "&" operator doesn't yield the contents of a pointer; it
>> yields the address of an object.
[...]

>> I suggest you read a good C textbook (K&R2 is very good). You have a
>> lot of things to unlearn.
>> (Or if you're doing this deliberately, please please please go away;
>> it's not amusing.)
>
> It is just as amusing as you assertion, backed by no well known
> authority of the c language specification, that c does not support
> pass by reference.

I didn't say that C doesn't support pass by reference. I said that C
doesn't *directly* support pass by reference, but that a programmer
can *implement* pass by reference using the features of the language.

> Your continued reference to 'object' during replies proves my assertions --
> recent OOP development (decades ago implemented recent, I mean) have
> obfuscated the meaning of "pass by reference". I suspect this is due
> mostly to the declining software knowledge, and skills, that has again
> raised the acclaim and praise for "garbage collection" languages.

What does my use of the term "object" have to do with anything? The C
standard defines an "object" as a "region of data storage in the


execution environment, the contents of which can represent values"

(C99 3.14). I wasn't using the term in the sense of object-oriented
programming. (The C++ standard's definition of "object" is similar.)

> Show me any authority that shares you "opinion" that c does not "pass
> by reference".

C99 6.5.2.2p4:

An argument may be an expression of any object type. In preparing
for the call to a function, the arguments are evaluated, and each
parameter is assigned the value of the corresponding argument. 79)

Footnote 79:

A function may change the values of its parameters, but these
changes cannot affect the values of the arguments. On the other
hand, it is possible to pass a pointer to an object, and the
function may change the value of the object pointed to. A
parameter declared to have array or function type is adjusted to
have a pointer type as described in 6.9.1.

Which is what I've been saying all along.

Keith Thompson

unread,
Jan 8, 2006, 2:37:27 AM1/8/06
to
Richard Heathfield <inv...@invalid.invalid> writes:
> Keith Thompson said:
>> Then we need to make it very clear to J Random Newbie that C doesn't
>> support pass by reference as a languag construct.
>
> Right.
>
>> Don't say that the
>> "*" means pass by reference; say that the "*" means you're passing a
>> pointer value, which can be used to do the equivalent of pass by
>> reference.
>
> To a newbie, the two statements can seem equivalent, especially if he
> doesn't know what "pass by reference" is and has to go and look it up. Why
> use the phrase at all, when it doesn't add any value?
>
>> Until J Random Newbie is able to hold that entire complex
>> thought in his head, he's not going to be able to be an effective C
>> programmer.
>
> We can ease that journey by not giving him useless junk to remember.
>
>> Pass by reference is a very common and useful programming technique,
>> one that C supports quite well (though arguably a little more clumsily
>> than some other languages do).
>
> I know what you're saying, but I think that's an own-foot-shooting way to
> say it.

Ok, I see your point. I suppose it depends on the kind of newbie.

Personally, I learned Pascal before I learned C, so I already knew
about pass-by-value and pass-by-reference. From that perspective,
understanding that passing a pointer is the way to emulate
pass-by-reference in C was very important. Things might be different
for a non-programmer learning C.

On the other hand, I'm not sure that C is a good choice for a first
language. In any case, a programmer should *eventually* understand
the concepts of pass-by-value and pass-by-reference. And I tend to
think that it's at least as important to use C (or any language) as a
vehicle for learning about programming as it is to learn the details
of the language itself.

Netocrat

unread,
Jan 8, 2006, 3:59:41 AM1/8/06
to
On Sun, 08 Jan 2006 07:14:20 +0000, Keith Thompson wrote:
[...]

> I didn't say that C doesn't support pass by reference. I said that C
> doesn't *directly* support pass by reference, but that a programmer
> can *implement* pass by reference using the features of the language.

[...]


> C99 6.5.2.2p4:
>
> An argument may be an expression of any object type. In preparing
> for the call to a function, the arguments are evaluated, and each
> parameter is assigned the value of the corresponding argument. 79)
>
> Footnote 79:
>
> A function may change the values of its parameters, but these
> changes cannot affect the values of the arguments. On the other
> hand, it is possible to pass a pointer to an object, and the
> function may change the value of the object pointed to. A
> parameter declared to have array or function type is adjusted to
> have a pointer type as described in 6.9.1.
>
> Which is what I've been saying all along.


- in both debates it's often argued that "C does not support the
concept directly, but supports its implementation trivially". In the case
of multi-dimensional arrays, the Standard contradicts this argument since
it explicitly describes a C array declared with more than one index as
multi-dimensional.

In the case of pass by reference, the opposite seems to be true: both
the Standard and its predecessor, K&R, explicitly describe C's parameter
passing as by value.

I think it's reasonable though to refer to C's simulation of this concept
as "pass by reference" (quote marks included) as a shortcut for a longer
expression similar to "pass the object's address to the function so that
the object's value may be modified", when it's clear that the writer is
not referring to the concept as supported more directly by languages like
C++ and Pascal.

--
http://members.dodo.com.au/~netocrat

Netocrat

unread,
Jan 8, 2006, 4:13:24 AM1/8/06
to
On Sun, 08 Jan 2006 08:59:41 +0000, Netocrat wrote:
[slip-of-the-finger posted an article still being drafted; try again]

> On Sun, 08 Jan 2006 07:14:20 +0000, Keith Thompson wrote:
> [...]
>> I didn't say that C doesn't support pass by reference. I said that C
>> doesn't *directly* support pass by reference, but that a programmer can
>> *implement* pass by reference using the features of the language.

You've written something very similar in the past about multidimensional
arrays. On that occasion I disagreed because the Standard contradicts it.
On this occasion, I agree with your analysis as it seems to be supported
by both the Standard and K&R.

[omit wafflier wordage of draft post]

--
http://members.dodo.com.au/~netocrat

Chuck F.

unread,
Jan 8, 2006, 6:19:20 AM1/8/06
to
Nelu wrote:
>
... snip ...

>
> type is int, you send a pointer to int, int is changed in the function. The functions doesn't tell you that it needs an int to change an int. It tells you it needs a pointer to int that it can't change.
> Although you can consider &int a reference to an int, the function doesn't ask for a reference but for a type which is called "pointer to int" and what you send is the value of a pointer to int type.

Please fix your right hand margin. Lines must never exceed 80
chars according to standards, and prefereably should not exceed
about 65 or so (to allow for quote marks).

Chuck F.

unread,
Jan 8, 2006, 6:30:04 AM1/8/06
to
Keith Thompson wrote:
>
... snip ...

>
> Personally, I learned Pascal before I learned C, so I already
> knew about pass-by-value and pass-by-reference. From that
> perspective, understanding that passing a pointer is the way to
> emulate pass-by-reference in C was very important. Things might
> be different for a non-programmer learning C.
>
> On the other hand, I'm not sure that C is a good choice for a
> first language. In any case, a programmer should *eventually*
> understand the concepts of pass-by-value and pass-by-reference.
> And I tend to think that it's at least as important to use C (or
> any language) as a vehicle for learning about programming as it
> is to learn the details of the language itself.

Fortunately for JRN the use of pass-by-name has virtually
disappeared. In fact fortunately for most of us, IMO.

Jordan Abel

unread,
Jan 8, 2006, 2:04:14 PM1/8/06
to
On 2006-01-08, Richard Heathfield <inv...@invalid.invalid> wrote:
> Joe Wright said:
>
>> Jordan Abel wrote:
>>> [...] time() takes its argument by reference [as do many other
>>> functions in time.h, for historical reasons] You are conflating a
>>> generic concept with a specific feature C++ has that C does not.
>>
>> I may have to look this up because an exact example eludes me right now.
>
> You needn't bother - Jordan is wrong about time() which does not in fact
> take its argument by reference. It takes its parameter by value.

It takes a time_t by reference. You are once again refusing to recognize
the existence of the programming technique called "pass by reference" -
if someone started talking about linked lists in here, you wouldn't
object that C doesn't support those, despite the fact that they (unlike
pass by reference) are not used at all by the interface to the standard
library.

It is loading more messages.
0 new messages