when to use C and when to use C++

F

Frederick Gotham

Mark McIntyre:
In what way is int array[8] not an array?

In the following context:

void Func(int array[8])
{
sizeof array;
}

int main(void) { return 0; }
 
R

Richard Heathfield

jacob navia said:
Richard said:
jacob navia said:

All this would be unnecessary if I could declare:

int fn(int array[253]);

and have the expected semantics.


For those who have read K&R2, the expected semantics is "pointer to an
int" - and that's exactly what you get.

The expected semantics are that sizeof(array) is 253*sizeof(int).

Not to anyone who has read K&R2 or any decent C reference book, nor to
anyone sufficiently competent in C to write or maintain a C compiler
properly. Presumably that includes you.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: normal service will be restored as soon as possible. Please do not
adjust your email clients.
 
F

Frederick Gotham

Richard Heathfield:
Not to anyone who has read K&R2 or any decent C reference book, nor to
anyone sufficiently competent in C to write or maintain a C compiler
properly. Presumably that includes you.


Seeing as how Jacob is fully aware that an array cannot be passed by value,
I think he is arguing that C should be more intuitive, i.e. that you should
be able to figure stuff out by yourself without having to consult a book.
It's debateable how far this view can be taken.

The following snippet a load of cod's wallop in my opinion; I don't know
why C ever allowed the presence of the redundant array dimension in there:

void Func(int array[8]) {}

It looks, sounds, smells like an array, but it's a pointer. At least with
the following snippet, you know things aren't quite straight-forward:

void Func(int array[]) {}

, but again, it's debateable as to whether array syntax should have been
allowed at all. I myself always opt for the pointer syntax, i.e.:

void Func(char **p) {}

instead of:

void Func(char *p[]) {}

It's more honest in my opinion.
 
K

Keith Thompson

jacob navia said:
Richard said:
jacob navia said:
All this would be unnecessary if I could declare:

int fn(int array[253]);

and have the expected semantics.
For those who have read K&R2, the expected semantics is "pointer to
an int" - and that's exactly what you get.

The expected semantics are that sizeof(array) is 253*sizeof(int).

No, the *expected* semantics are that sizeof array == sizeof(int*), at
least to anyone who understands that particular aspect of the C
language. I would certainly expect anyone who works on a C compiler
to understand that, and I'm sure you do. I think that rather than
"expected semantics", you really mean "desired semantics", i.e., the
semantics that *you* want.
Obviously C has a different opinion about this, what I find is a
big problem for the language. Arrays are not first class objects.

This is not a matter of opinion, it's a matter of definition.

I'm not sure what "first class objects" are, but I certainly agree
that array types are not first class types in C. That's just the way
it is.

The fact that "int array[235]" in a parameter declaration really means
"int *array" is, in my opinion, an annoyance. The fact that the 235
is silently ignored is particularly counterintuitive. I dislike this
particular feature of C. Having said that, I move on and deal with
the language as it is, and I rarely use that particular feature (I'd
just declare the parameter as "int *array").

If your point is that C is imperfect, I don't think anyone is going to
disagree with you. If your point is that this particular imperfection
makes the language useless, this is refuted by the fact that plenty of
people actually use it.

It would be nice if array types were more nearly first-class in C, but
I don't believe it's possible to make that happen without breaking
existing code. If you can manage to design such a language change,
I'll be very impressed.

If you want first-class arrays, use a different language, and discuss
it in a different newsgroup.
 
K

Keith Thompson

jacob navia said:
Frederick Gotham wrote: [...]
To say, in this context, that the expected semantics for "sizeof
array" is to be equal to "253*sizeof(int)", is an expectation whose
foundation is ignorance.
Now, since _when_ can we make arguments based upon ignorance?
Applying sizeof to a pointer type yields the size of the
pointer. Applying sizeof to an array type yields the size of the
array. If you don't like it, then tough -- but don't use ignorance
as an excuse to imply fault in the C programming language.

This is obvious. If I do not like some feature of the language, I am
an ignorant since I should know that "C is like that".

jacob, please make up your mind about what you're trying to say.

If you do not like some feature of the language, that's perfectly
fine. I don't like that particular feature myself.

Context: we're talking about a parameter declaration, something like:

void func(int array[253]);

The phrase "expected semantics" implies, at least to me and I think to
most of us, that you *expect* "sizeof array", evaluated inside func,
to yield 253*sizeof(int). It doesn't, and the standard is perfectly
clear on that point. I'm sure your own lcc-win32 handles this in
accordance with the C standard.

If you're trying to say that you'd *prefer* "sizeof array" to yield
253*sizeof(int), that's perfectly reasonable, but it's not what you've
been saying. The word "expected" implies a belief about what the
expression actually does yield, not a desire for it to behave
differently than it really does.

I wonder if this is partly a language problem (French vs. English).
 
J

jacob navia

Keith said:
jacob navia said:
Frederick Gotham wrote:
[...]
To say, in this context, that the expected semantics for "sizeof
array" is to be equal to "253*sizeof(int)", is an expectation whose
foundation is ignorance.
Now, since _when_ can we make arguments based upon ignorance?
Applying sizeof to a pointer type yields the size of the
pointer. Applying sizeof to an array type yields the size of the
array. If you don't like it, then tough -- but don't use ignorance
as an excuse to imply fault in the C programming language.

This is obvious. If I do not like some feature of the language, I am
an ignorant since I should know that "C is like that".


jacob, please make up your mind about what you're trying to say.

If you do not like some feature of the language, that's perfectly
fine. I don't like that particular feature myself.

Context: we're talking about a parameter declaration, something like:

void func(int array[253]);

The phrase "expected semantics" implies, at least to me and I think to
most of us, that you *expect* "sizeof array", evaluated inside func,
to yield 253*sizeof(int). It doesn't, and the standard is perfectly
clear on that point. I'm sure your own lcc-win32 handles this in
accordance with the C standard.

If you're trying to say that you'd *prefer* "sizeof array" to yield
253*sizeof(int), that's perfectly reasonable, but it's not what you've
been saying. The word "expected" implies a belief about what the
expression actually does yield, not a desire for it to behave
differently than it really does.

I wonder if this is partly a language problem (French vs. English).

Yes, I meant obviously that it should be 253*sizeof(int)...

I KNOW that the standard says otherwise and I have implemented it like
that and I have used it like that for the 20+ years I have been
programming in C, but still, after all this time, I think it is
a mistake. Arrays should KEEP its size information so that it can
be checked at run-time, and sizeof() should be a run-time function
that returns the stored size...

BUT

It would mean quite a lot of changes to the language.
 
K

Keith Thompson

Mark McIntyre said:
Frederick said:
int array[5];

That is an array only in very special situations... In most cases it
will "decay" into a pointer to int.

Actually the wrong way round. Its a pointer in very special
situations, vis when you pass it as an argument to a function.
[...]

The implicit conversion of an array expression to a pointer value has
nothing to do with function arguments. A function argument merely
happens to be one of the many contexts in which the conversion take
place. For example, given:

void func(int *p);
int foo[10];
...

func(foo);

the expression "foo" is converted to a pointer value, but *not*
because it's being passed to a function.

There are two rules to remember:

1. An expression of array type is implicitly converted to a pointer to
the array's first element *unless* the expression is the operand of
a unary "&" or "sizeof" operator, or is a string literal used to
initialize an array. (C99 6.3.2.1p3).

2. A parameter declaration of an array type is adjusted to a pointer
type. This is not a conversion; in a parameter declaration,
"int array[5]" really *means* "int *array". (C99 6.7.5.3p7)

If you look at the history of the language, these two rules exist for
similar reasons, but they're really completely independent of each
other; neither follows from the other.

People often try to re-state these rules in other terms. The result
is almost always either needlessly complex or needlessly imprecise.
 
J

jacob navia

Frederick said:
Mark McIntyre:

In what way is int array[8] not an array?


In the following context:

void Func(int array[8])
{
sizeof array;
}

int main(void) { return 0; }
Yes, that's precisely my point.

Arrays become just pointers, and any size information
must be passed to the function in an extra parameter
by the programmer, with all the associated error possibilities.

jacob
 
S

Skarmander

Frederick said:
Skarmander:



OK, I'm with you so far...




Indeed, as a Westerner, I might find it quite strange that Malingua's
showers look like cars.
But here, of course, the analogy breaks down readily: Malingua, as we
presume it to exist, isn't man-made, and isn't meant to serve a purpose. And
even then, Malinguans familiar with cars may concede that it doesn't make a
whole lot of sense to them either.
What can I do about it? Well, before travelling to Malingua, I can say,
"OK, I going to disregard everything I learned in Ireland, and I'm going to
start afresh in Malingua without making any presumptions as to how things
work."
That is humanly impossible. Only computers can work without presumptions,
and that only because they cannot presume in the first place.
Is this a viable choice? No, not when talking about going to a different
country.
OK, I'm with you so far. :)
However, we're talking about a programming language. When you're learning a
new programming language, you can't really build on past experience. You
need to confirm and clarify everything.
Says who? The language? No. So what, then? Experience? Sure. Experience
tells us we cannot rely on our previous experience, but you see how that
only goes so far.

If I read

c = a + b;

it is not possible and not helpful for me to pretend that these are
meaningless symbols barring an explicit definition in a language standard
somewhere that will explain to me what exactly this sequence of symbols
means, if anything.

For sure, the language standard *is* the only authority on it. I cannot
*rely* on my assumptions about the statement's semantics, and a good many
may be wrong. I cannot with any definite justification shout "that's wrong"
if it shouldn't match my expectation. However, if "c = a + b;" turned out to
mean "perform a low-level format of all attached disk drives", I would have
reason to complain nonetheless, however formally precise and consistent the
definition might be.
The simple fact of the matter is that you have to be in the know when it
comes to a programming language. Some people may presume that you can pass
an array by value, but alas they're wrong. Was their intuition flawed to
think they could simply write:

void Func(int arr[5]) {}

Maybe, maybe not.

As long as we're willing to concede the possibility, that's enough. It's not
a black and white issue, and that's my point. "It's standard C so there's no
point criticizing it for what it isn't" is a reasonable attitude for writing
programs (indeed, the only reasonable attitude), but not when the point
precisely is criticism of C's design.

Is the intuition flawed? Consider this: in C, everything that can be passed
is passed by value, but arrays cannot be passed as values. This is not
reflected in the most intuitive attempt at doing it, since that is not an
error, but instead implements quite different semantics.

There are two separate issues here. First, should C have included passing
arrays by value? There are obvious and understandable reasons why it does
not (though whether they are sufficiently good reasons is a completely
different matter, which I will not go into here). Second, since C does not
include passing arrays by value, should it have included the syntax form
that it does, with the semantics that has? The latter decision is much
harder to defend.
At the end of the day though, the C Standard is the C
Standard. You can either come to terms with the fact (however much you
dislike it) that Malingua's showers look like cars, or you can rant on
about how backwards Malingua is.
Or, indeed, you can do both. Nobody said coming to terms meant keeping your
peace hereafter. What would become of activism? :)
This reminds me of the argument posed recently whereby the following was
deemed to be bad style:
Style is a lot murkier than even intuition.
SomeAggregateType obj = {0};

in place of:

SomeAggregateType obj;
memset(&obj,0,sizeof obj);

(Let's forget for the moment that the latter form is only guaranteed to
work with integer types.)

The argument posed was that the former form wasn't explicit enough, i.e.
that the programmer wasn't expected to know that all the members/elements
would be default-initialised.

This, in my own humble opinion, is BS. The semantics of the former form are
perfectly well defined by the Standard, and that's good enough for me. One
shouldn't censor one's code because they think a particular feature might
be a little too advanced for some people.
There are no clear insights on how intuition works, so these matters remain
thoroughly debatable. However, in my opinion, this is still quite a bit
removed from the opinion that it's counterintuitive that

void func(int arr[5]) {
...

does not declare 'arr' to be a parameter of type "array of five ints", and
that indeed what looks like a dimension is actually meaningless.

Both these things rely on intuition, and both can be chalked up to
inappropriate extrapolation: you thought it meant one thing based on what
you saw earlier, but you were wrong. How obviously jarring you might find
either is subjective, of course, but I do think most people would agree that
confusion about passing arrays is more "natural" than confusion about struct
initializers.
It is the implication of a flaw in C that I was dismissing.
It *is* a flaw in C. The syntax is confusing, and pointlessly so. The
language would be better if it did not include this particular syntax form
at all, and if array parameters looked as what they are: pointers.

Of course, the question of whether arrays should be first-class citizens
instead (which would be an alternate way of solving the problem) is a whole
'nother bag of beans, as it involves a lot more arguments and being a lot
more explicit about design goals.

And, obviously, now that the language is what it is there is no sense in
arguing that it should be different, as the mass of existing code is now a
very strong argument against. But then, that's not the argument in question
either.

S.
 
F

Frederick Gotham

jacob navia:
Arrays become just pointers, and any size information
must be passed to the function in an extra parameter
by the programmer, with all the associated error possibilities.


While I agree with the meaning, I don't agree with your language. An array
doesn't "just become" a pointer any more than a double "just becomes" an int.
It's an implicit conversion.
 
K

Keith Thompson

Frederick Gotham said:
jacob navia:



And we'd probably end up with something like C++...

C++ has the same array/pointer conversion rules as C (though it also
has STL vectors and so forth).
 
C

CBFalconer

jacob said:
Frederick said:
Mark McIntyre:
In what way is int array[8] not an array?

In the following context:

void Func(int array[8])
{
sizeof array;
}

int main(void) { return 0; }

Yes, that's precisely my point.

Arrays become just pointers, and any size information
must be passed to the function in an extra parameter
by the programmer, with all the associated error possibilities.

Not necessarily. You can always create a completely passable array
by embedding it in a struct. In fact, by using the "struct hack"
or C99 open arrays you can even make those variable length.

typedef struct vlgharr {
size_t maxsize;
char arrproper[1];
} vlgharr, *pvlgharr;

pvlgharr vlacreate(size_t sz) {
pvlgharr pv;
size_t needed;

if (!sz) return NULL;
needed = offsetof(arrproper, vlgharr) + sz;
if (pv = malloc(needed)) pv->maxsize = sz;
return pv;
} /* untested */

and you can now pass either pv or *pv as function parameters. You
should probably create a corresponding "vladestroy(pvlgharr pv);"
function.
 
C

CBFalconer

Skarmander said:
.... snip ...

It *is* a flaw in C. The syntax is confusing, and pointlessly so. The
language would be better if it did not include this particular syntax
form at all, and if array parameters looked as what they are: pointers.

So all you have to do is write your function prototypes to specify
pointers, rather than the confusing array format. It's your own
fault.
 
B

Ben Bacarisse

CBFalconer said:
jacob said:
Frederick said:
Mark McIntyre:

In what way is int array[8] not an array?

In the following context:

void Func(int array[8])
{
sizeof array;
}

int main(void) { return 0; }

Yes, that's precisely my point.

Arrays become just pointers, and any size information
must be passed to the function in an extra parameter
by the programmer, with all the associated error possibilities.

Not necessarily. You can always create a completely passable array
by embedding it in a struct. In fact, by using the "struct hack"
or C99 open arrays you can even make those variable length.

typedef struct vlgharr {
size_t maxsize;
char arrproper[1];
} vlgharr, *pvlgharr;

pvlgharr vlacreate(size_t sz) {
pvlgharr pv;
size_t needed;

if (!sz) return NULL;
needed = offsetof(arrproper, vlgharr) + sz;
if (pv = malloc(needed)) pv->maxsize = sz;
return pv;
} /* untested */

and you can now pass either pv or *pv as function parameters. You
should probably create a corresponding "vladestroy(pvlgharr pv);"
function.

Well I am sure I'll shot down in flames, but that really surprises
me. Passing pv, OK (setting aside the legality of the hack in the
first place) but I can't see how most implementations have a hope of
passing *pv correctly.

C99 regularised this by giving the implementation a way to know the
object's size.
 
R

Random832

2006-11-14 said:
jacob said:
Frederick said:
Mark McIntyre:

In what way is int array[8] not an array?

In the following context:

void Func(int array[8])
{
sizeof array;
}

int main(void) { return 0; }

Yes, that's precisely my point.

Arrays become just pointers, and any size information
must be passed to the function in an extra parameter
by the programmer, with all the associated error possibilities.

Not necessarily. You can always create a completely passable array
by embedding it in a struct. In fact, by using the "struct hack"
or C99 open arrays you can even make those variable length.

Doing this precludes passing the "whole" struct by value. You can only
pass up to the single element that is actually declared for arrproper[],
and possibly by accident a bit extra that's present as padding.

I have no idea what "variably modified types" are or whether they are
useful for getting around this.

I have no idea what happens if you pass a struct with a flexible array
member in c99. probably an error message.
 
R

Richard Heathfield

Frederick Gotham said:

it's debateable as to whether array syntax should have been
allowed at all.

As a matter of fact, I agree with you (with regard to function parameters) -
but it's historical baggage from the days when [] actually /did/ mean
"pointer", and historical baggage tends to decay into tradition.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: normal service will be restored as soon as possible. Please do not
adjust your email clients.
 
R

Richard Heathfield

Frederick Gotham said:
jacob navia:



And we'd probably end up with something like C++...

....and we already have C++, if we want it. It's over there somewhere. So
there's no need to change C to be like it. Otherwise we'd have two C++s,
which would be silly.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: normal service will be restored as soon as possible. Please do not
adjust your email clients.
 

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
474,436
Messages
2,571,696
Members
48,796
Latest member
Greg L.
Top