strange warning

K

Kenny McCormack

I meant an application type. Its implementation in whatever primitive type
construct the language provides would be irrelevant.

If you wanted for some reason to represent the three r, g, b values of some
image pixels as an array: char[3], and had a bunch of pixel-processing
routines to work on such a type, would you bother to pass the 3 as an extra
argument to each?[/QUOTE]

What makes this newsgroup so much fun is how much at cross-purposes the
two groups are. People like BartC & Malcolm are talking about taking trips
to the market and such, while others like Kiki and his buddies just wanna
talk about things like carburetors, cylinders, spark plugs, valves,
pistons, and so on.

And they want us to know, over and over and over again, just how many of
each a typical engine has.
 
K

Kenny McCormack

So in fact you are making the "mistake". You've given a sensible
justification, unlike some other people I don't make the assumption that
anyone who disagrees with me is stupid or inexperienced, or knows nothing
about C outside of their own little world.

An excellent summary of CLC reg behavior.

Definitely a keeper.

As Han From China so adroitly pointed out, the first ones to start
insulting people are always the regs - and then when people respond in
kind, they act all hurt and complain about being insulted.
 
J

James Kuyper

On 5/12/14, 1:20 PM, James Kuyper wrote: ....

The standard may talk about the memory acquiring an "effective type" on
access, but conceptually the array existed beforehand. ...

That concept may in fact be useful, but it is not part of C as currently
defined.
... Arithmetic on
pointer values are defined in terms of arrays and their elements (and
non-array object are considered to be arrays of 1 element), and the size
of that array affects the validity of the operations.

We don't need to actually make the memory take on the "effective type"
for us to be able to do the pointer arithmetic, ...

In principle, yes, we do need it. C pointer arithmetic is defined in
terms of an array, which is an object type; an object with no declared
type and no effective type cannot have an array type - even though it's
perfectly clear how that situation should be dealt with.

That strikes me as a weakness in the current definition. I don't think
it's ever likely to be a real-world problem, but the description of
pointer arithmetic should be modified to be meaningful when applied to a
pointer to an object that has no declared type, which has not yet
acquired an effective type (or which has acquired one that is different
from the pointed-at type).
... so this isn't needed to
"create" the array. I also find no wording that would allow the
implementation to claim undefined behavior if you do pointer arithmetic
on one type, even if you have given the memory a different effective
type via an access.

The behavior is undefined ".. by the omission of any explicit definition
of behavior ..." (4p2). The only definition for the behavior of pointer
arithmetic is in terms of positions in an array of objects of the
pointed-at type, and the pointer points at a object which is not such an
array, so that definition does not apply.
 
M

Malcolm McLean

That's not "more precise" at all. It's over complicated gibberish that
would get you a slap in most design meetings.

People KNOW what an array is in C.
I've muddied the waters by saying that if you declare

int postcount[10]; /* number of posts user has made to each account */
int Naccounts = 5; /* number of accounts held by user, note max 10 */

and fill up the data somehow, you've got an array of five integers and a
buffer of 10 integers.

Usually you don't need to make that distinction because it's obvious from
context which you mean, also because C doesn't make it - it's a higher
level concept that doesn't map easily to C's way of doing things.
In C++, however, people are usually very clear on the difference between
vector::size() and vector::capacity().
 
D

David Brown

So in fact you are making the "mistake".

No, that would not be making any sort of mistake.
You've given a sensible justification,
unlike some other people I don't make the assumption that anyone who
disagrees with me is stupid or inexperienced, or knows nothing about C
outside of their own little world.

I don't think you are either stupid or inexperienced (nor do I think you
think that of others), but I do think you don't pay due consideration to
C outside your own little world.
strlen() should in my view scale gracefully to any string length, until you hit
fundamental limits like the sizes of integers.

That is your view, and it is not unreasonable in many cases. It is also
the view supported by the standards, as far as I can see. But the point
is that this is not the /only/ view, and it is not necessarily the
/best/ view. I gave a list of possibilities regarding strlen
limitations - some are limits imposed due do practical limitations, and
some are improvements over the standard version (when used in
appropriate contexts).
We've often got to assume
that an "int" can represent any integer that we want, because trying to
code simple variables with arbitrary precision is just too difficult and time
consuming, outside of specialised mathematical software. That's just a
limitation of current processors that we have to accept, it's not something
we're happy about.

Why not put in a sanity test, if you know that no string will go over 1K?

Sanity test, especially compile-time ones, are always a good idea.
It's not a completely stupid idea, but things like that have a way of persisting
well after the reason has gone away.

That's always true. There are several ways of handling such situations
- good documentation and commenting, clear separation of the limiters
and the implementation (such as putting the limits as #define's within
the modules header, rather than buried in the implementation code), and
being explicit about the limitations.

But it is also worth remembering that for a lot of embedded code, the
code is written for a specific purpose on specific hardware. The reason
for the limitation never goes away, because it is part of the system.
Maybe a project would have a strlen() function limited to 20 characters,
because the screen only has space for 20 characters. When the "reason"
goes away, you are using different hardware - it is a different system,
and the code changes or is re-written to suit.

There is always a balance between general, flexible, re-usable code and
dedicated, constraint, efficient and specific code. Dedicated code is
often the right choice.
 
M

Malcolm McLean

Sanity test, especially compile-time ones, are always a good idea.
I was adding support for .puz files to my crossword program the other day.
They store the width and height of the crossword as single bytes.

Why, why, why, why why?

It would be interesting to see how my grid-filling routines scale up.
Pre-computer, it would have been totally impractical to print a
crossword that big. But the university has acquired a "wall" of screens.
They're intended for viewing medical images, but the temptation to
put a giant crossword on it is there.
 
K

Keith Thompson

Malcolm McLean said:
The snag is that if we do
#define CHESSBOARDWIDTH 8

we have to be very careful that all the code reacts properly when we replace
8 with another value. For a chess program, that's likely difficult.

Why do we have to do that? The point of the #define is to make the
code clearer; without it, it's not obvious what a given instance of
8 means. If there's no requirement for the code to deal with a width
other than 8, why waste time implementing that unneeded flexibility?
(In some cases it's going to be easier to write code that doesn't
care what the specific value of CHESSBOARDWIDTH is, but in other
cases it might not be.)
 
D

David Brown

Well, yes, it's surprising that such a simple claim generates such
a huge amount of discussion.

The biggest surprise is that you have spent such a long time using terms
in a way that made no sense to anyone else, rather than trying to get to
the real issue.

And yes, Ben, there are /many/ experienced programmers who write
programs that use a fixed size rather than passing the size as a
parameter. Referring to Malcolm's snakes and ladders program, there are
plenty of situations where:

void DoMove(SQUARE board[NSQUARES], int playerid, int diceroll);

is a far better choice than:

void DoMove(SQUARE *board, int Nsquares, int playerid, int diceroll);


In most of my C programming, the first version is going to be the
preference - the size of my boards are fixed at compile-time, so I want
to take advantage of that knowledge to write source clearer code, get
better compile-time checking, generate smaller and faster object code,
and avoid any hint of dynamic memory allocation.
 
D

David Brown

The snag is that if we do
#define CHESSBOARDWIDTH 8

we have to be very careful that all the code reacts properly when we replace
8 with another value. For a chess program, that's likely difficult.

That's why static assertions were invented. (And they have existed for
a long time - C11 just made them neater.) When your implementation code
makes use of the assumption that CHESSBOARDWIDTH is 8, just write

static_assert(CHESSBOARDWIDTH == 8, "The code currently supports 8x8
chess boards only");
 
K

Kenny McCormack

David Brown said:
The biggest surprise is that you have spent such a long time using terms
in a way that made no sense to anyone else, rather than trying to get to
the real issue.

I understand what Malcolm is talking about [*]. So, you claim of "anyone" is,
of course, false.

[*] And so would you if you got that stick out of your a**.

--
Modern Christian: Someone who can take time out from
complaining about "welfare mothers popping out babies we
have to feed" to complain about welfare mothers getting
abortions that PREVENT more babies to be raised at public
expense.
 
K

Keith Thompson

BartC said:
I meant an application type. Its implementation in whatever primitive type
construct the language provides would be irrelevant.

The phrase "application type" doesn't make the distinction you're trying
to make either. I think I understand what you're getting at, but you're
not expressing it clearly.

[...]
 
K

Keith Thompson

Malcolm McLean said:
I've muddied the waters by saying that if you declare

int postcount[10]; /* number of posts user has made to each account */
int Naccounts = 5; /* number of accounts held by user, note max 10 */

and fill up the data somehow, you've got an array of five integers and a
buffer of 10 integers.

Yes, you have. Does that mean you're going to stop muddying the waters?
 
B

Ben Bacarisse

David Brown said:
The biggest surprise is that you have spent such a long time using terms
in a way that made no sense to anyone else, rather than trying to get to
the real issue.

And yes, Ben, there are /many/ experienced programmers who write
programs that use a fixed size rather than passing the size as a
parameter.

But that's not what I said! I write such programs too, but, generally,
I try to write functions that don't know array sizes. If you actually
find it a contentious claim, then we can agree to differ, but I'll note
that I am a little surprised.

(Maybe I expressed it badly. To me "generally" does not mean "almost
always" or even "more often than not". It just means in the general
case where there are no specifics that can alter what I consider a
default choice.)
Referring to Malcolm's snakes and ladders program, there are
plenty of situations where:

void DoMove(SQUARE board[NSQUARES], int playerid, int diceroll);

is a far better choice than:

void DoMove(SQUARE *board, int Nsquares, int playerid, int diceroll);

In most of my C programming, the first version is going to be the
preference - the size of my boards are fixed at compile-time, so I want
to take advantage of that knowledge to write source clearer code, get
better compile-time checking, generate smaller and faster object code,
and avoid any hint of dynamic memory allocation.

Hmm. I don't follow some of these points. Parameterising the function
by size does not, to me, hint at dynamic allocation, and I can't see why
the code would be significantly clearer in either case. And I might be
missing what you mean about better compile-time checking too, possibly
by not having used compilers with the kind of checks you have in mind.

As a result, the specific here would probably not cause me to change my
default -- I go with what I do in general and add the size as a
parameter -- but the compile-time checks might make me change my mind if
I knew what they were.
 
K

Kenny McCormack

Malcolm McLean said:
I've muddied the waters by saying that if you declare

int postcount[10]; /* number of posts user has made to each account */
int Naccounts = 5; /* number of accounts held by user, note max 10 */

and fill up the data somehow, you've got an array of five integers and a
buffer of 10 integers.

Yes, you have. Does that mean you're going to stop muddying the waters?

Another failing grade handed down by Headmaster Kiki.

How will you ever explain this to Mom?

--
(This discussion group is about C, ...)

Wrong. It is only OCCASIONALLY a discussion group
about C; mostly, like most "discussion" groups, it is
off-topic Rorsharch [sic] revelations of the childhood
traumas of the participants...
 
K

Kenny McCormack

The phrase "application type" doesn't make the distinction you're trying
to make either. I think I understand what you're getting at, but you're
not expressing it clearly.

Another failing grade handed down by Headmaster Kiki.

How will you ever explain this to Mom?

--
Here's a simple test for Fox viewers:

1) Sit back, close your eyes, and think (Yes, I know that's hard for you).
2) Think about and imagine all of your ridiculous fantasies about Barack Obama.
3) Now, imagine that he is white. Cogitate on how absurd your fantasies
seem now.

See? That wasn't hard, was it?
 
K

Kenny McCormack

[email protected] (Kenny McCormack) said:
David Brown said:
The biggest surprise is that you have spent such a long time using terms
in a way that made no sense to anyone else, rather than trying to get to
the real issue.

I understand what Malcolm is talking about [*]. So, you claim of "anyone" is,
of course, false.

[*] And so would you if you got that stick out of your a**.

Personally I think Malcolm misrepresented what he really meant. And,
lets face it, the claim that 99%, or whatever it was, of the time you
dont need or should not use fixed length arrays is clearly bunkum.

The fact is that I can see where he's coming from. I can see the context
from which he is speaking and how what he says makes sense in that context.

Here's the thing: If, when you [rhetorical "you", not you specifically]
read a post on Usenet, that doesn't make sense to you in your own context,
if. instead of continuing to insist that your own context is the only
possible one (and thus, responding accordingly, as Kiki and others do here),
you made some effort to re-arrange your prejudices so that the post does
make sense, you'll find two things to be true:

1) Usenet will make a lot more sense.
2) It will be a lot less fun.

The "standards jockeys" here (and we know who they are, don't we...) are,
of course, the worst in terms of absolutely refusing to ever even consider
re-arranging their prejudices. This makes them, incidentally, good school
masters, but little else...
But it's always good to see the regs throw in the "anyone else" or "we"
statements to suggest a higher echelon frowning down on Malcolm's
"ignorance".

Indeed. Quite so.

And another failing grade received from the committee above...

--
Windows 95 n. (Win-doze): A 32 bit extension to a 16 bit user interface for
an 8 bit operating system based on a 4 bit architecture from a 2 bit company
that can't stand 1 bit of competition.

Modern day upgrade --> Windows XP Professional x64: Windows is now a 64 bit
tweak of a 32 bit extension to a 16 bit user interface for an 8 bit
operating system based on a 4 bit architecture from a 2 bit company that
can't stand 1 bit of competition.
 
D

David Brown

But that's not what I said!

Perhaps I misread, or misinterpreted you.
I write such programs too, but, generally,
I try to write functions that don't know array sizes. If you actually
find it a contentious claim, then we can agree to differ, but I'll note
that I am a little surprised.

I don't disagree (I certainly don't disagree about the functions /you/
write!) - for lots of types of programming, you don't know the sizes at
compile time. My point is that there are also lots of types of
programming in which you /do/ know the sizes at compile time - or
perhaps you know maximum sizes at compile time and want to fix that in
the code.
(Maybe I expressed it badly. To me "generally" does not mean "almost
always" or even "more often than not". It just means in the general
case where there are no specifics that can alter what I consider a
default choice.)
Referring to Malcolm's snakes and ladders program, there are
plenty of situations where:

void DoMove(SQUARE board[NSQUARES], int playerid, int diceroll);

is a far better choice than:

void DoMove(SQUARE *board, int Nsquares, int playerid, int diceroll);

In most of my C programming, the first version is going to be the
preference - the size of my boards are fixed at compile-time, so I want
to take advantage of that knowledge to write source clearer code, get
better compile-time checking, generate smaller and faster object code,
and avoid any hint of dynamic memory allocation.

Hmm. I don't follow some of these points. Parameterising the function
by size does not, to me, hint at dynamic allocation, and I can't see why
the code would be significantly clearer in either case. And I might be
missing what you mean about better compile-time checking too, possibly
by not having used compilers with the kind of checks you have in mind.

Parameterising the size does not /require/ dynamic allocation, but it
often goes together. Dynamic allocation typically implies parameterized
size, even though the opposite is not required.

I feel that the version with the "SQUARE board[NSQUARES]" parameter is
clearer because we are talking about an array of a specific size, not
just a pointer to some SQUARE's somewhere. And the compiler may be able
to check accesses to the array better, because it knows the size of the
array. The information can also be used to generate more optimal code.

But some of this is surely just personal preference. Perhaps because of
the kind of work I do, I prefer to deal in more concrete and fixed
objects - I am more comfortable with a fixed size data type than a more
abstract pointer-to-something. Another effect is that debugging can
often be easier, as the debugger can show the whole array sensibly.
As a result, the specific here would probably not cause me to change my
default -- I go with what I do in general and add the size as a
parameter -- but the compile-time checks might make me change my mind if
I knew what they were.

I don't think there would be much to be gained by compile-time checks or
optimisations in this case, but sometimes there can be. For example, in
the case of a chess board with N by N squares, checks could be made
about the ranges and the knowledge that N is 8 (or whatever it is
#define'd to) could easily lead to faster code for accessing the two
dimensional array.
 
J

James Kuyper

The language should tighten up the distinction between a buffer and
an array.
A buffer is a region of memory which may or may not contain
data, and typically has a few unused bytes at the end. An array is
a set of data that can be indexed in O constant time by an integer
subscript.

A C array with either automatic or allocated storage duration starts out
uninitialized unless explicitly initialized or created by calloc(). I
presume that when you say "contain data" you're not referring to the
indeterminate values represented by uninitialized memory. Therefore,
your definition of "array" is quite different from the one provided by
the C standard.
To avoid confusion, I'll refer to the things that you refer to as
"arrays" as McLean-arrays.

It just occurred to me to wonder: do you consider buffers and
McLean-arrays to be conflicting or non-overlapping sets? Specifically,
do you think that buffers cannot "be indexed in 0 constant time by an
integer subscript"?
C arrays should obviously only allow subscripts from 0 to N-1 and
with no facilities for gaps or sparse arrays. There are serious questions
about how to best handle multi-dimensional arrays.

Let's consider a version of C which was modified to "tighten up the
distinction between a buffer and a [McLean-]array.". Does this mean that
you would impose this rule only for McLean-arrays, and not for buffers?
If so, what should happen when indexed a buffer with a negative value,
or one >=N?
Until those are
answered, it's hard to say what sorts of pointer conversions should
be considered "sloppy".

If C were tightened up as you suggest, what distinctions should the
standard make between the conversions allowed for pointers to buffers
and pointers to McLean-arrays?
 
B

Ben Bacarisse

David Brown said:
David Brown <[email protected]> writes:
void DoMove(SQUARE board[NSQUARES], int playerid, int diceroll);

is a far better choice than:

void DoMove(SQUARE *board, int Nsquares, int playerid, int diceroll);
I feel that the version with the "SQUARE board[NSQUARES]" parameter is
clearer because we are talking about an array of a specific size, not
just a pointer to some SQUARE's somewhere. And the compiler may be
able to check accesses to the array better, because it knows the size
of the array.

As an aside, C99 allows the same information to be conveyed in the
second case like so:

void DoMove(SQUARE board[Nsquares], int Nsquares, int playerid, int diceroll);

(This is particularly useful when dealing with 2D (and higher) arrays as
the information enables you to index the arrays in a natural way.)

<snip>
 
I

Ike Naar

As an aside, C99 allows the same information to be conveyed in the
second case like so:

void DoMove(SQUARE board[Nsquares], int Nsquares, int playerid, int diceroll);

(This is particularly useful when dealing with 2D (and higher) arrays as
the information enables you to index the arrays in a natural way.)

Shouldn't 'int Nsquares' come before 'board[Nsquares]' in order for this
to work? Like

void DoMove(int Nsquares, SQUARE board[Nsquares], int playerid, int diceroll);
 

Ask a Question

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

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

Ask a Question

Members online

Forum statistics

Threads
474,075
Messages
2,570,542
Members
47,197
Latest member
NDTShavonn

Latest Threads

Top