segfault w/ block, but not file scope

J

Jordan Abel

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).

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.
 
J

Joseph Dionne

Keith said:
Joseph Dionne said:
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.
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.

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.
 
J

Joseph Dionne

Keith 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. 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".
 
M

Mark McIntyre

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
 
K

Keith Thompson

Joseph Dionne said:
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.
 
J

Joseph Dionne

Joseph said:
Keith said:
Joseph Dionne said:
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.
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.

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.

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.
 
J

Joseph Dionne

Mark said:
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?
 
K

Keith Thompson

Joseph Dionne said:
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.
 
M

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?

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

Mark McIntyre
 
J

Joseph Dionne

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




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




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.
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.
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?
 
J

Joseph Dionne

Keith said:
Joseph Dionne said:
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.
 
J

Joseph Dionne

Mark said:
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.
 
K

Keith Thompson

Joseph Dionne said:
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 said:
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.
 
K

Keith Thompson

Joseph Dionne said:
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.
 
K

Keith Thompson

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.

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.)
 
C

Chris Torek

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.)
 
C

Chuck F.

Joseph said:
.... 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/>
 
J

Joseph Dionne

Keith said:
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".
 
J

Joseph Dionne

Chris Torek wrote:

[..]
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).

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.
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top