A doubly linked-list in C

K

Keith Thompson

arnuld said:
okay, I got it. Arrays and pointers are different things with two
exceptions:

Close, but arrays and pointers are different things, period. (Or
"full stop" if you prefer.)
1) passing an array as an argument to a function. In that case, you never
access the array but the pointer to the first element and then you use
pointer arithmetic to access the array elements.

2) when a pointer is assigned the value of an array (even when we are not
talking about function arguments) then we can access the array using
pointer arithmetic. In fact, C, implicitly converts a into p + i where
p &a[0], C always index into array using pointers.


1 and 2 are just special cases of a more general rule.

Any expression of array type (which could, for example, be the name of
an array object) is implicitly converted to a pointer to the array's
first element *unless* the array expression is the operand of a unary
"sizeof" or "&" operator, or is a string literal used to initialize an
array.

An array object name appearing as a function argument, or on the right
hand side of an assignment, or in an initializer, as long as it's not
one of the three cases I mentioned, is converted to a pointer to the
first element. So in func(array_obj), array_obj isn't converted to a
pointer because it's being passed to a function; it's converted to a
pointer because it's an expression of array type.

The [] operator always takes a pointer operand and an integer operand;
very often the pointer operand is the result of implicitly converting
an array expression.

And one more piece of the puzzle: If a function parameter is declared
as an array:
void foo(int param[]);
it's really a pointer, not an array. There's no conversion here; in
this context, "int param[]" *means* "int *param".
 
I

Ian Collins

CBFalconer said:
BartC wrote:
.... snip ...

That's pretty accurate. The point, that nobody seems to make, is
that a system (not C) that can pass by reference generally has no
way of accessing that 'pointer' equivalent that was actually
passed.

Because the 'pointer' equivalent is passed by value?
 
K

Keith Thompson

Phil Carmody said:
You can retract that assertion, I never put the phrase in quotes.
I simply said that they mention passing by reference by virtue
of passing parameters by means of what they call references, with
the implication that I consider passing references to be passing
by reference.

I put it in quotation marks because I was quoting you.

[...]
If there's some other wording in the
standard that refers to passing arrays by their address, please cite
it. (If there is, it's probably just an informal statement, possibly
even an error.)

Well, not "passing arrays by their address", but certainly "passing
[something]" where you and I know, and anyone conversant with C too,
that the value actaully passed isn't what follows the word "pass",
and which I believe you ought to object to, given your prior stance.

I expected you to provide section numbers rather than just disjointed
quotations. Ok, I can do a search.
... then passes the array as a single argument ...

7.15.1.4p6. It's an example, and therefore non-normative. Using
informal language in such a context isn't too bad, though I'd still
prefer that it be re-worded.
... passes the string pointed to ...

7.20.4.6p2, describing the system() function. With more context:

If string is not a null pointer, the system function passes the
string pointed to by string to that command processor to be
executed in a manner which the implementation shall document [...]

It's not referring to passing an argument to a C function.
I'm guessing you simply searched for 'pass', too, didn't you, and
didn't detect the 'third person' 'singular' clue above? Then again,
if you don't use 'passed' too, you'll miss in the search/sort
functions, where of course objects are passed via their address:

You wrote
Ah, I see we have a third person who's singularly stuborn.
That was supposed to be a clue? Are you trying to communicate, or
just showing off?
... objects are passed more than once to the comparison function ...

7.20.5p4. Yes, that's imprecisely worded. It's also imprecisely
quoted; it's "When the same objects (consisting of size bytes,
irrespective of their current positions in the array) are passed more
than once to the comparison function ...". I had to search for a
subset of your quoted string to find it.

Are you deliberately making me do extra work here to figure out what
you're talking about?

[snip]

Ok, fine, the standard refers in some places to passing arrays as
function arguments. And if you had simply provided a section number
in the first place, this discussion would have been unnecessary.
 
A

arnuld

Any expression of array type (which could, for example, be the name of
an array object) is implicitly converted to a pointer to the array's
first element *unless* the array expression is the operand of a unary
"sizeof" or "&" operator, or is a string literal used to initialize an
array.


wait, things are getting a little bit clear:

char arrc[] = "comp.lang.c";


sizeof() does not apply here but I am using a string literal to
initialize the array. In this case what will happen ? S


func("Dennis M. Ritchie");

this is the literal string passed to a funcion. What will happen here ?


Here is FAQ 6.2:

char a[] = "hello";
car *p = "world";


FAQ says that in both cases a[3] or p[3] , the value is same but compiler
gets there differently. Now I have seen my friend using char *p = "world"
notation (for using it as ab array of const characters). Is it fine or
dangerous. Myself, I do const char a[] = "wordl" all the time, I never
ever use char* p notation to point to some literal but I want to know
whether char *p is a good idea or not.
 
J

James Kuyper

....
I think he's referring to this recent post by Kaz ....


I recommend watercolor, or /washable/ crayons.

Ah! I missed that one. I'd thought rkiesling was using a metaphor. Sorry
for the confusion! :-}
 
J

James Kuyper

arnuld said:
Any expression of array type (which could, for example, be the name of
an array object) is implicitly converted to a pointer to the array's
first element *unless* the array expression is the operand of a unary
"sizeof" or "&" operator, or is a string literal used to initialize an
array.


wait, things are getting a little bit clear:

char arrc[] = "comp.lang.c";


sizeof() does not apply here but I am using a string literal to
initialize the array. In this case what will happen ? S

This is just a special shorthand notation that doesn't fit in with the
other uses of string literals. It's meaning is equivalent to

char arrc[] =
{'c', 'o', 'm', 'p', '.', 'l', 'a', 'n', 'g', '.', 'c', '\0'};
func("Dennis M. Ritchie");

this is the literal string passed to a funcion. What will happen here ?

This is a string literal not used to initialize an array. Therefore, a
piece of memory sufficiently long to store the string, including the
terminating null character, will be set aside by the implementation. The
string literal will be implicitly converted into a pointer to the first
element of that array, and that pointer value will be passed to func().
Here is FAQ 6.2:

char a[] = "hello";
car *p = "world";


FAQ says that in both cases a[3] or p[3] , the value is same but compiler
gets there differently. Now I have seen my friend using char *p = "world"
notation (for using it as ab array of const characters). Is it fine or
dangerous.

Every C construct is dangerous, if used improperly. Both constructs are
useful, but since their meanings are different, the contexts in which
they are useful are different. The proper way to use them also differs.
If, for instance, you want to modify the string, you need to use 'a',
because the statement

p[3] = 'p';

has undefined behavior. On the other hand, if you want to change which
string you're using, you need to use 'p', since the statement

a = "goodbye";

is a constraint violation.
 
I

Ian Collins

arnuld said:
Here is FAQ 6.2:

char a[] = "hello";
car *p = "world";


FAQ says that in both cases a[3] or p[3] , the value is same but compiler
gets there differently. Now I have seen my friend using char *p = "world"
notation (for using it as ab array of const characters). Is it fine or
dangerous. Myself, I do const char a[] = "wordl" all the time, I never
ever use char* p notation to point to some literal but I want to know
whether char *p is a good idea or not.
No, it is not because attempting to modify a string literal gives you
undefined behaviour. Use const char *p.
 
K

Keith Thompson

rkiesling said:
I think the "implementation defined" buzzword was already
covered a few ways back, in the manner in which an argument
passing mechanism can actually transfer a value as an
argument, and then refer to it within a function (the actual
name of the parameter is yet *another* reference, nobody
seems to have noticed).

What is it about the argument passing mechanism that's
implementation-defined? Can you provide an example?

And what exactly do you mean by "reference"? An object name could be
thought of as a "reference", in the sense that it's something that
refers to something, but later you say that a "references" are memory
addresses.
So, compilers can use references in all possible cases,
except when an operator (like &) supposedly doesn't allow
it. The compiler yet needs to make certain that ambiguous
semantics don't cause a program to crash, and yet produce
output that is usable in actual programs, and where the
memory actually is, is not the user's business. The
compiler yet needs to DTRT for all possible contexts,
semantics, architectures, and optimization levels. It's not
exactly a win, if you're aiming for portability.

What ambiguous semantics? Can you provide an example?

[...]
 
C

CBFalconer

Ian said:
Because the 'pointer' equivalent is passed by value?

No, because the referencing system passes the value by 'pointer'.
That passed 'pointer' effectively has a * permanently prepended,
and you can't remove it. Note that I am talking about the
referencing system, not about C.

This has the disadvantage that the passed value must be in a
'location' that can be accessed. It may allow reading, writing, or
both. But you can't pass in a constant that way.

This is usually controlled by the declaration of the parameter in
the function. For example, in Pascal, a reference parameter is
declared as "VAR parmeter : type", while a value parameter omits
the VAR. Other languages can specify more detail; Ada can specify
read, write, or both in place of the VAR. The C replacement
(passing a pointer) can prevent writing with a const. But you can
beat it.

I hope this makes sense to you. My explanations are sometimes
easily misread.
 
C

CBFalconer

Ian said:
It probably does!

I doubt it. C (not C++) allows you to bypass the const by copying
the pointer elsewhere and ignoring the error. This wouldn't work
if the pointer pointed to a const object. Bringing in C++ code
leads easily to misunderstanding.
 
C

CBFalconer

Ian said:
arnuld said:
Here is FAQ 6.2:

char a[] = "hello";
car *p = "world";

FAQ says that in both cases a[3] or p[3] , the value is same but
compiler gets there differently. Now I have seen my friend using
char *p = "world" notation (for using it as ab array of const
characters). Is it fine or dangerous. Myself, I do const char a[]
= "wordl" all the time, I never ever use char* p notation to point
to some literal but I want to know whether char *p is a good idea
or not.

No, it is not because attempting to modify a string literal gives
you undefined behaviour. Use const char *p.

No, that doesn't help. In either case you can't write into the
string. That 'const' only gives you the help of having the
compiler emit an error message (probably) when you try to write
into the string.

You get the same effect on gcc by using -Wwrite-strings.

The reason for this is to avoid disturbing old code.
 
P

Phil Carmody

Richard Heathfield said:
Phil Carmody said:


Nothing, except that it's irrelevant to the discussion.

Pfft! Tou're funny. Tragicomedy, alas.
The point is
that i itself is not being passed. Therefore, it is not being
passed by reference. Neither is &i is being passed by reference. It
is being passed by value. So what is it, precisely, that you
imagine is being passed by reference?

For about teh 5th time, when a reference to i is passed, i is
passed by reference.

Phil
 
K

Keith Thompson

Phil Carmody said:
For about teh 5th time, when a reference to i is passed, i is
passed by reference.

Repeating that doesn't make it true.

If I send you a piece of paper with my home address written on it, I'm
not sending you my house.
 
P

Phil Carmody

Richard Heathfield said:
Phil Carmody said:


Repetition is not proof. When a reference (a pointer) to i is
passed, it is the value of the reference that is passed, and *not*
i (which is not passed *at all*).

Proof: 3.3.2.2 (C89) or 6.5.2.2 (C99) Function calls: "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."

This clearly and unequivocally supports my view. Do you have a
citation from the Standard that clearly and unequivocally supports
your view?

I'm discussing English usage, the standard is written in English.
You can't with a straight face deny the ambiguity of the word
"pass". Actually, you appear to be able to. Others aren't.

Phil
 
A

Antoninus Twink

I hope this makes sense to you. My explanations are sometimes easily
misread.

That's because they're invariably poorly expressed, and frequently
completely wrong.
 
K

Keith Thompson

CBFalconer said:
Ian said:
arnuld said:
Here is FAQ 6.2:

char a[] = "hello";
car *p = "world";

FAQ says that in both cases a[3] or p[3] , the value is same but
compiler gets there differently. Now I have seen my friend using
char *p = "world" notation (for using it as ab array of const
characters). Is it fine or dangerous. Myself, I do const char a[]
= "wordl" all the time, I never ever use char* p notation to point
to some literal but I want to know whether char *p is a good idea
or not.

No, it is not because attempting to modify a string literal gives
you undefined behaviour. Use const char *p.

No, that doesn't help.

Yes, it certainly does.
In either case you can't write into the
string.

Correct (where "can't" covers both constraint violations and undefined
behavior).
That 'const' only gives you the help of having the
compiler emit an error message (probably) when you try to write
into the string.

Yes, that's exactly the point.
You get the same effect on gcc by using -Wwrite-strings.

gcc's -Wwrite-strings option makes it non-conforming.
The reason for this is to avoid disturbing old code.

Yes, that's the reason string literals aren't const. But a pointer
that points to a string literal, as in:
char *p = "world";
*should* be declared const, so the compiler (any conforming compiler,
not just gcc) will warn you if you accidentally try to modify it.
 
K

Keith Thompson

CBFalconer said:
I doubt it.

On what basis?
C (not C++) allows you to bypass the const by copying
the pointer elsewhere and ignoring the error. This wouldn't work
if the pointer pointed to a const object. Bringing in C++ code
leads easily to misunderstanding.

The code snippet being discussed is specifically C++ (which was being
used to illustrate a point about C). I strongly suspect that a C++
compiler would generate code that passes the address of a location in
which the value 5 is stored.

Getting back to C, what exactly do you mean by "copying the pointer
elsewhere and ignoring the error"? You can use a cast to drop the
const qualification, or you can use some kind of type punning to
override it, but I don't think that's what you're talking about. Can
you clarify?
 
P

Phil Carmody

Keith Thompson said:
Repeating that doesn't make it true.

If I send you a piece of paper with my home address written on it, I'm
not sending you my house.

That's what's known as a straw man.

You can do better, surely? Given that you backed down earlier
in the face of incontrovertable evidence, is Richard's last gasp
still spurring you on? Is it time for the chair to be broken over
the referee's head yet?

Phil
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top