strange warning

M

Malcolm McLean

Malcolm McLean wrote:



Bullshit. But do know what, and how useful, a fixed length array is.
Car mechanics tend to be people who use words like "bullshit", Ian. They tend to
be arrogant and overbearing and dismissive, because they haven't been exposed
much outside of their own little world, which they falsely think is the "real world".

Wise up. There are some extremely high qualified, educated, intelligent programmers
posting on this group. You could learn a lot from them.
That's not to say that they'll always be right and you'll always be wrong, but usually
even if they're wrong there's a reasoning behind the mistake, so try to be polite and
respectful.
 
I

Ian Collins

Malcolm said:
Car mechanics tend to be people who use words like "bullshit", Ian.

No, they tend to use words like "f-off".

Insulted programmers use "bullshit",
Wise up. There are some extremely high qualified, educated, intelligent programmers
posting on this group. You could learn a lot from them.

I have learned from *them*. There are also condescending plonkers here
as well.
That's not to say that they'll always be right and you'll always be wrong, but usually
even if they're wrong there's a reasoning behind the mistake, so try to be polite and
respectful.

Pot, kettle?
 
M

Malcolm McLean

Pot, kettle?
I always try to be nice to people. But occasionally someone takes a technical point as a
personal insult, because they do the opposite in their own work. Then they retaliate by
demeaning the individual who is making the point. Eventually patience wears thin.
 
I

Ian Collins

Malcolm said:
I always try to be nice to people. But occasionally someone takes a technical point as a
personal insult, because they do the opposite in their own work. Then they retaliate by
demeaning the individual who is making the point. Eventually patience wears thin.

I took your derogatory car mechanic analogy as the personal insult.

I didn't mind your condescending comment regarding rigourous methods...
 
M

Malcolm McLean

Malcolm McLean wrote:

I took your derogatory car mechanic analogy as the personal insult.
It was a personal insult. Because I felt you'd been persistently disparaging.

However let's drop it now. I may or may not be right about fixed-size
arrays being a sign of bad design, but that's nothing to do with personalities.
I'm right or wrong on the issues.
 
D

David Brown

It was a personal insult. Because I felt you'd been persistently disparaging.

However let's drop it now. I may or may not be right about fixed-size
arrays being a sign of bad design, but that's nothing to do with personalities.
I'm right or wrong on the issues.

You are wrong on the issues.

There are times when dynamic sizes make sense, but plenty of occasions
where fixed sizes are appropriate. When you can stick with fixed sizes,
the result is more efficient code, better compile-time error checking,
more consistent run-time behaviour, and fewer possibilities of run-time
errors or abnormal behaviour.

Therefore, /if/ you can afford the resources (typically memory), then it
is almost always better to use fixed sizes that are determined at
compile time. A statically allocated array of fixed size is better in
almost every way than a dynamically malloc'ed array, except that you
cannot (easily) reuse the same memory for other purposes, and you need
to know the sizes at compile time.

This is the reason why high reliability and safety-critical systems
usually ban any sort of dynamic memory. And that is precisely the sort
of system that requires /real/ rigorous development methods, and /real/
good design. When you start using "dynamic this" and "general that",
you end up with a system that cannot be analysed and characterised
properly, and consequently has much greater risks for reliability.

Look around your office. Count the number of processors you have around
you. You probably have something like 20 to 50, of which only one or
two are in PC's or smartphones. Most of the rest will be embedded
microcontrollers, mostly programmed in C, and almost all with fixed
sizes for everything.

(Note that having compile-time fixed sizes does not mean that the sizes
are hard-coded into the algorithms. I think perhaps you have a
fundamental misunderstanding here.)


Now, stop pontificating as though you know how all programming is done,
and don't insult people who do a job that you apparently know nothing
about. I'm sure you are great at /your/ job, and I'm sure you do a
better job by keeping everything dynamic - but don't think that applies
to the rest of the C programming world. It's bigger that you are.
 
M

Malcolm McLean

On 12/05/14 14:30, Malcolm McLean wrote:

Therefore, /if/ you can afford the resources (typically memory), then it
is almost always better to use fixed sizes that are determined at
compile time. A statically allocated array of fixed size is better in
almost every way than a dynamically malloc'ed array, except that you
cannot (easily) reuse the same memory for other purposes, and you need
to know the sizes at compile time.

This is the reason why high reliability and safety-critical systems
usually ban any sort of dynamic memory. And that is precisely the sort
of system that requires /real/ rigorous development methods, and /real/
good design. When you start using "dynamic this" and "general that",
you end up with a system that cannot be analysed and characterised
properly, and consequently has much greater risks for reliability.
The Turing machine running out of tape is a fundamental theoretical problem,
I agree.
You're mixing up "dynamic memory" with "non-fixed-size arrays". That's because C
doesn't enforce a rigorous distinction between an array and a buffer. C
programmers tend to say

char line[1024];
fgets(line, 1024, fp) ;

"Ok, I've got an array of 1024 bytes".
They don't. They've got a buffer of 1024 bytes, an array of however many characters
fgets happened to read, plus the nul.
Dynamic memory and algorithms which scale in N are obviously linked ideas, but
they're not quite the same thing. If we call strlen() on line, we'd expect strlen to
scale gracefully to any line length. That's obvious, few people would make the mistake
of hardcoding strlen() to a limited buffer size of 1024. But when it's less obvious,
people do often write dependencies into code that they shouldn't.

It's usually the other way round, by the way. Big machines tend to use dynamic memory,
it's the small systems where you have to compromise by using fixed buffers. If we're
allocating, say, 1K to hold a string, on a machine with 2GB installed, then the allocation
can only fail if it happens to straddle the 2GB / over 2GB boundary. That's desperately
unlikely, you're getting into "the computer is more likely to blow a fuse".
 
K

Keith Thompson

Dr Nick said:
Sorry - it's a language matter. Read that as "If we had only
something..."

Ok, that makes more sense, but I still don't understand the point.

calloc isn't all that different from malloc. It takes two arguments,
and it zeros the allocated memory, but it still just allocates a
specified number of bytes.

C pointer arithmetic is defined in terms of arrays objects (and array
indexing is defined in terms of pointer arithmetic). How could arrays
be unnecessary?
 
K

Keith Thompson

Malcolm McLean said:
The person who wrote the kernel headers has decided to define the interface
as raw structures and a fixed size, abstracted a bit by a hash define.

A clear case of micro-optimisation. But not necessarily a bad
decision, given the limitations of current systems, or maybe the fact
that the kernel is a legacy system that has been continuously
developed back from the days when 640k was enough for anybody.

Writing code whose structure directly reflects the real-world
entity that it models is not micro-optimization. In this case,
the real-world entity is most directly modeled by fixed-size arrays.
Writing more general code that can deal with varying sizes would not
be good design; it would be excessive abstraction for its own sake.

I think you mentioned chess boards earler in this thread. If you're
writing a chess program, there's not much point in allowing for a
board size other than 8 by 8.
 
M

Malcolm McLean

I think you mentioned chess boards earler in this thread. If you're
writing a chess program, there's not much point in allowing for a
board size other than 8 by 8.
A chess board, yes.
But a snakes and ladders board is usually 10x10. However you don't change
anything fundamental in the game by making it another size. So most of
your routines should take M and N as board dimensions. Probably you should
be loading in the board from an external datafile, until the very last stages
of development, when you might want to hardcode them as C source files
containing data about ladder positions and so on.
There might be some exceptions. The display hardware might not easily
scale to a board of arbitrary dimensions, so you might have to hardcode the
assumption that the board is 10x10 there. But you do that reluctantly.
 
K

Keith Thompson

Malcolm McLean said:
The Turing machine running out of tape is a fundamental theoretical
problem, I agree.

Since nobody else mentioned Turing machines, it's hard to tell what you
"agree" with.
You're mixing up "dynamic memory" with "non-fixed-size arrays". That's
because C doesn't enforce a rigorous distinction between an array and
a buffer. C programmers tend to say

char line[1024];
fgets(line, 1024, fp) ;

"Ok, I've got an array of 1024 bytes".
They don't. They've got a buffer of 1024 bytes, an array of however
many characters fgets happened to read, plus the nul.

line is an array of 1024 bytes, used to implement a buffer.

You've mentioned this array vs. buffer distinction before. Can you
define "array" and "buffer" in unambiguous terms? If C had both
array types and "buffer" types, how exactly would they differ?

In this particular example, using 1024 as a fixed size is a
compromise, designed to be long enough to hold most reasonable input
lines. It's going to cause problems, or at least greater complexity,
if an input line is longer than what can fit in the array.

There are ways to avoid arbitrary bounds like this. C doesn't
provide a standard library function to read an arbitrarily long input
line, but it certainly provides the tools to write such a function
(for example, I'm fairly sure the POSIX getline() function can be
implemented in standard C.)

This has very little to do with Ian's situation, where the size of
the fixed array is specifically imposed by the real-world entity
the code is dealing with.

[...]
 
K

Keith Thompson

Noob said:
Osmium said:
When C sees
int a[10];
it goes into a little dance. It sets aside room for 10 ints in one place
and in another place it creates a variable named 'a'. They set a to point
at the first int in the space set aside. Bill's problem originates with the
variable named 'a'. Thus my answer to him.

You might be thinking of this kind of definition:

char *s1 = "abcdefg";

Contrast with

char s2[] = "abcdefg";

I think Osmium is thinking about array definitions. He just doesn't
understand them. Given "int a[10];", the pointer variable he refers
to doesn't exist.
 
K

Keith Thompson

Malcolm McLean said:
A chess board, yes.
But a snakes and ladders board is usually 10x10. However you don't change
anything fundamental in the game by making it another size. So most of
your routines should take M and N as board dimensions. Probably you should
be loading in the board from an external datafile, until the very last stages
of development, when you might want to hardcode them as C source files
containing data about ladder positions and so on.
There might be some exceptions. The display hardware might not easily
scale to a board of arbitrary dimensions, so you might have to hardcode the
assumption that the board is 10x10 there. But you do that reluctantly.

Ian is not, as far as I know, implementing snakes and ladders.

Of course there are situations where fixed-size arrays are in
appropriate. What you refuse to acknowledge is that there are other
situations where fixed-size arrays are the most reasonable way to model
the problem domain.
 
K

Keith Thompson

Keith Thompson said:
Of course there are situations where fixed-size arrays are in
appropriate. What you refuse to acknowledge is that there are other
situations where fixed-size arrays are the most reasonable way to model
the problem domain.

An accidentally inserted space may have obscured my meaning.
What I meant to write was:

Of course there are situations where fixed-size arrays are
*inappropriate*. What you refuse to acknowledge is that there
are other situations where fixed-size arrays are the most
reasonable way to model the problem domain.
 
M

Malcolm McLean

Ian is not, as far as I know, implementing snakes and ladders.

Of course there are situations where fixed-size arrays are in
appropriate. What you refuse to acknowledge is that there are other
situations where fixed-size arrays are the most reasonable way to model
the problem domain.
I gave you the example of a chess board where fixed-size arrays are appropriate.
So in some situations, like chess programs, it does make sense to code all
the routines to take a fixed 8x8 board. In other situations, e.g. snakes and
ladders games, it doesn't, it's better to paramaterise the board dimensions.

The reason is that adding or subtracting a row from a chess board would
radically change the logic for all but the simplest of chess-playing algorithms,
Also if the chess federation decides to introduce different board sizes, you can
be sure of getting plenty of notice.
Football - a team consists of 11. But if you add a twelfth player, you don't change
anything drastic in the game, and children's games often play with an extra man
or two. Then a man can always be sent off, so you have to handle N = 10 anyway.
it doesn't make sense to support games with more than two teams, however,
that should be hardcoded.
Snakes and ladders and football are more typical than chess. Some things
change fundamentally as you alter N, but most things don't.

On buffers and arrays, it's quite simple. Arrays always have data in them, buffers
don't necessarily.
 
M

Malcolm McLean

Whereupon its a fixed size array once again...
Here are two code fragments.

typedef struct
{
int ladderto; /* index of square we have a ladder to, -1 if none */
int snaketo; /* index of square we have snake to, -1 if none */
int player; /* index into player array, -1 if no player on square */
} SQUARE;

#define NSQUARES 100

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

for(i=0;i<NSQUARES;i++)
if(board[i[.player == playerid)
break;
if(i == NSQUARES)
/* player not found, some sort of internal error */
to = i + diceroll;
if(to >= NSQUARES)
/* player can't move because he's going over the board edge */
}
or

void DoMove(SQUARE *board, int Nsquares, int playerid, int diceroll)
{
for(i=0;i<Nsquares;i++
if(board.plyerid == playerid)
break;
if(i == Nsquares)
/* player not found, some sort of internal error */
to = i + diceroll;
if(to >= Nsquares)
/* player can't move because he's going over the board edge */
}

Now I'm arguing for method 2. Pass the N parameter wherever possible, even
if in fact we know that all boards are going to be 10x10.
 
J

James Kuyper

On 5/11/14, 3:21 PM, Dr Nick wrote: ....

The fact that malloc works with a raw byte count is irrelevant to
whether it creates a specific object or not. By allocating the space and
assigning a T* pointer to that space does "create" and array of T, with
the number of elements based on the size of T and the space allocated.

Assignment to a T* pointer is not the relevant event. It's only when
that pointer is used to access that memory that it acquires an effective
type; and I believe that it is only the part actually accessed that
acquires that type. Two pointers to different types pointing at the same
block of dynamically allocated memory can be used to give different
parts of that block different effective types.
 
K

Keith Thompson

Malcolm McLean said:
I gave you the example of a chess board where fixed-size arrays are
appropriate. So in some situations, like chess programs, it does make
sense to code all the routines to take a fixed 8x8 board.

And do you acknowledge that, in the case of the code Ian is working on,
fixed-size arrays are also appropriate, and are not merely a
"micro-optimization"?
In other situations, e.g. snakes and
ladders games, it doesn't, it's better to paramaterise the board dimensions.
[...]

On buffers and arrays, it's quite simple. Arrays always have data in
them, buffers don't necessarily.

Then perhaps you could come up with a term other than "arrays" to
describe array-like data structures that "always have data in them".
The word "array" already has a meaning, and it's inconsistent with the
way you're using it.
 
M

Malcolm McLean

And do you acknowledge that, in the case of the code Ian is working on,
fixed-size arrays are also appropriate, and are not merely a
"micro-optimization"?
I haven't seen the code, so it's silly to say whether they are appropriate or not.
I explained how to remove dependencies from code with operated on
fixed system headers, and what the advantage was in so doing, but I also
made the proviso that it wasn't a magic bullet. For example, if you need to
set member a to non-zero, wait until it goes zero again, then extract a byte
from variable b which represents init from some device or other, and you need
do this extremely quickly to avoid losing input, then trying to force that
particular section of the code into a "manipulate then synchronise" model
would be silly. That doesn't mean that the basic idea of separating bit shuffling
from IO isn't sound.
Then perhaps you could come up with a term other than "arrays" to
describe array-like data structures that "always have data in them".
The word "array" already has a meaning, and it's inconsistent with the
way you're using it.
"Here's an array of ten integers".
"OK, can you tell me their values?"
"42, 3, 62, 100, 1234 and, er, the last five are undefined".
"How do you know that the last five are undefined?"
"Well we allow up to ten accounts per user, but this particular
user has only five. So Naccounts = 5, and he's made that many
posts from each account".
"Ok, so you've got an array of five integers, you've got a buffer
which holds up to ten integers".

That's normal usage.
 
B

Ben Bacarisse

Malcolm McLean said:
"Here's an array of ten integers".
"OK, can you tell me their values?"
"42, 3, 62, 100, 1234 and, er, the last five are undefined".
"How do you know that the last five are undefined?"
"Well we allow up to ten accounts per user, but this particular
user has only five. So Naccounts = 5, and he's made that many
posts from each account".
"Ok, so you've [not] got an array of five integers, you've got a buffer
which holds up to ten integers".

(I'm assuming my edit of adding "not" is correct, otherwise I don't
follow what you are saying.)
That's normal usage.

I've never encountered it. Neither have I seen "fixed size arrays" used
to refer to arrays whose size is not passed to functions. The term
usually means arrays whose size is fixed by the declaration (or creation
or whatever the languages does).

In my experience, "buffer" most often means a temporary storage area,
usually between a producer and a consumer, and "array" refers to an
indexed collection of data (with O(1) access), regardless of whether
every index position is used or not.

As a result, I could not make out what it was you were trying to say.
It turns out, you are simply advocating parameterising functions by the
size of the data the operate on. I'd surprised if there is any
experienced programmer here who disagrees that this is generally the
right thing to do, or who does not have very good reasons for not doing
when they don't.
 

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,562
Members
47,197
Latest member
NDTShavonn

Latest Threads

Top