c / c++ : is it end of era ?

M

Mark McIntyre

Mark McIntyre a écrit :
Knowing the length is necessary for so many situations that in MOST
cases you will end up calling strlen explicitely or implicitely

I disagree. You're once again generalising from your own extremely
limited experience to make wild sweeping statements about everyone
else's experience.
In many cases you need to pass the string to another function.
In most cases you need to pass the length or the called function must
call strlen.

This doesn't follow even slightly. Stop putting up spurious arguments.
To know if a string fits in a buffer you must know its length.

No, you need merely know that it cannot be larger than the buffer. I
don't expect you to understand the difference.
It is obvious that you can keep the length to avoid this
problems as heathfield says. But... if you need to keep the
length why not use a counted strings package anyway???

If you need to handle div/0 sometimes, why always perform the check?
??? Maybe a typo? You mean 1e+0 probably.

Buy a new calculator.
Maybe, anything can be exaggerated by did you find that code
crashing with division by zero?

Dur, it was impossible for it to crash with a div/0 error.
Maybe, but it doesn't hurt so much to be careful in
high reliability code...

In point of fact it hurt considerably because our pricing calculator
was slower than everyone else's to the extent that we missed deals.
Yes, it may be 0.0001% less efficient but maybe he did not see
"efficiency" as a higher goal than SECURITY!!!

Now you're being silly. Only an idiot makes remarks like that.
Never said otherwise

Actually, you have repeatedly said exactly that.
You misunderstand. I was saying the usage of normal C functions in
contrast to operator overloading the '+' operation.

Ah, right, so you mean in some other language which has operator
overload. I thought you were talking about C.
Maybe.
1) lcc-win32 allows you to test for overflow, and the speed diffeerence
is almost zero when the compiler does it.

"almost zero". Mhm. Multiply by 10e12. Still almost zero?
2) I am improving the operator overloading part, allowing inline and
assembly modules, so basically you will be able to do the overflow
test with almost no overhead.

I have no problem with you doing this, but don't call it C please.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
M

Mark McIntyre

Richard Heathfield a écrit :

I AM FORCED to used them.

What, someone is standing over you with a gun, compelling you to type
trigraphs whenever you want to type a brace? Don't be more asinine
than you need to be.
If I want it or not, the
translation will be done by the compiler without any user
intervention!

If you mean your compiler has to support them, sure. But this does NOT
compel you to use them anywhere.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
?

=?ISO-8859-1?Q?Jo=E3o_Jer=F3nimo?=

Random832 said:
What would it's complaint be? How's GCC supposed to know that he's
trying to create an object when the actual code he writes is a mere
typedef?

I think you don't quite understand in what situation he's saying he
doesn't get an error.

I don't get an error if I try to produce an object (or assembly code)
from a C file that has *only* that typedef...

The goal was only see if it gives an error...

JJ
 
?

=?ISO-8859-1?Q?Jo=E3o_Jer=F3nimo?=

Random832 said:
What would it's complaint be? How's GCC supposed to know that he's
trying to create an object when the actual code he writes is a mere
typedef?

I think you don't quite understand in what situation he's saying he
doesn't get an error.

The "object" I was talking about in the above sentence is a file with
relocatable machine code (before linking)...


It was only to see if GCC would produce any error when compiling
something like that, so I didn't need to link (and in fact couldn't link
that, because it lacked the main() function)...

JJ
 
?

=?ISO-8859-1?Q?Jo=E3o_Jer=F3nimo?=

Richard said:
C doesn't require implementations to allocate space on any kind of "stack",
but the type must be complete before you can define an object of that type.

But afaik it requires the functions to be reentrant (does it require?
I'm not sure, but suppose so...), and allocating local variables in a
stack seems the only way to achieve this...

JJ
 
?

=?ISO-8859-1?Q?Jo=E3o_Jer=F3nimo?=

Richard said:
Fine, but eventually people will say "why does C have this
guaranteed-to-be-exactly-8-bits type? Nobody has used 8-bit bytes for
*decades*!" And we will not even have the excuse of "historical reasons",
since C started off *without* such a type.

I don't believe that people would say "why does C have this
guaranteed-to-be-exactly-8-bits type?", because today many people ask
"How can I guarantee that this type will be a x-bit integer?"...

Not exactly in user space, but, as I said below, in hardware-imposed
patterns...
...which is why C leaves the exact size of types up to the implementor.

I thought this was done to increase portability...
No, they just let you create a new name for an existing type.

It's in the c.l.c FAQ:
http://c-faq.com/decl/int16.html
I can give you one, because it's one that I have written C code for: the
Analog SHARC DSP (used in set-top boxes, e.g. DVD players, Web TV, that
sort of thing), which has 32-bit bytes. So sizeof(long), sizeof(short),
sizeof(int), and sizeof(char) are all the same: 1.

No doubt others here can tell you about other DSPs with 16- or 32-bit bytes.
They're hardly rare. Also, various dinosaurs have had very weird byte
sizes, e.g. 9, 36, and I believe there was once a 24 (BICBW).

All that C guarantees is that your bytes will be *at least* 8 bits wide, and
*exactly* CHAR_BIT bits wide, where the value of CHAR_BIT is set by the
implementation.


Thanks, I thought all that strange machines were already dinosaurs...

JJ
 
A

av

If I ask you to keep track of thousands and thousands of memory areas
and never make a mistake when releasing the allocated memory you
WILL make a mistake even if you claim here that it will never
happen to you.

it is possible this is an error too but it seems
now memory leak not happen to me, and i presume 99% of out of bound
array rewriting too using my modificating version of malloc and free
 
A

av

Knowing the length is necessary for so many situations that in MOST
cases you will end up calling strlen explicitely or implicitely
(line in strcat)

In many cases you need to pass the string to another function.
In most cases you need to pass the length or the called function must
call strlen. To avoid an extra argument, most programmers will just
pass the string, forcing again a call to strlen. This is a horrible
waste with C string since in text handling programs, strings are passed
from function to function calling strlen for the same string over
and over.

this depends on functions that write the arrays if
0) we have an array "char a[59];"
1) if a function change "a" and return its new len
or if i change "a" i know the new len
we know always the new len of "a"

in c there are function that modify array but not return the len
bugged from definition
 
R

Richard Heathfield

João Jerónimo said:
I don't believe that people would say "why does C have this
guaranteed-to-be-exactly-8-bits type?", because today many people ask
"How can I guarantee that this type will be a x-bit integer?"...

They do? I rarely see anyone asking that question. And it's rarer still for
someone to ask that question with good reason.
Not exactly in user space, but, as I said below, in hardware-imposed
patterns...


I thought this was done to increase portability...

Yes. The two statements are equivalent.


The FAQ says, rightly, "if you truly need control over exact type sizes,
this is the right approach." And as it strongly hints, you almost certainly
don't *really* need control over exact type sizes after all.
Thanks, I thought all that strange machines were already dinosaurs...

In terms of byte sizes, you ain't seen nuffin' yet.
 
J

jacob navia

Mark McIntyre a écrit :
I disagree. You're once again generalising from your own extremely
limited experience to make wild sweeping statements about everyone
else's experience.

And you are speaking about something you do not know at all: me.
Where is your data about me? Where you know what experience I have or
not?

You don't. Period. The one making sweeping statements is you.
This doesn't follow even slightly. Stop putting up spurious arguments.

No?

How do you pass the length of the string then?

No, you need merely know that it cannot be larger than the buffer. I
don't expect you to understand the difference.

Gosh! You are clever. And how can I know if the given string
is bigger than the buffer without at least trying to measure
the length?

int fn(char *str)
{
char tmpbuf[512];
/* Here I have to start scanning the string.
At least 511 bytes must be scanned before
I realize that the length of the string is bigger
than tmpbuf. For bigger buffers a bigger WASTE
*/
}
If you need to handle div/0 sometimes, why always perform the check?

Because you never know when software will change and a constant
becomes a variable...
Buy a new calculator.
??? You mean 1+e^x in C?

Or you mean pow(e,x)+1 ?
Dur, it was impossible for it to crash with a div/0 error.




In point of fact it hurt considerably because our pricing calculator
was slower than everyone else's to the extent that we missed deals.

Ahh and it was slower because of the division by zero tests?

I would like to see the data that supports that hypothesis.
With today's machines, a test for zero is so fast that to slow
down a calculator so that a human being notices the tests must have
been done in an incredible fashion, and probably there are
thousands of OTHER factors that come into the slowdown first.
Now you're being silly. Only an idiot makes remarks like that.

Obvious coming from you. Only idiots make remarks like

"efficiency" is not a higher goal than SECURITY.

Yes. Only an idiot can do a remark like that.

This finishes it. You, you are not AN IDIOT!
 
M

Mark McIntyre

And you are speaking about something you do not know at all: me.

Au contaire, cheri.
Where is your data about me? Where you know what experience I have or
not?

You've demonstrated your experience in this newsgroup on numerous
occasions. If you have different experience to that which you display
here, then show it.
You don't. Period. The one making sweeping statements is you.

I'm not the one making sweeping statements claiming that it is
essential to know the length of a string.
How do you pass the length of the string then?

With correct design, you don't need to .
Gosh! You are clever. And how can I know if the given string
is bigger than the buffer without at least trying to measure
the length?

By knowing its length already, of course.
int fn(char *str)
{
char tmpbuf[512];
/* Here I have to start scanning the string.
At least 511 bytes must be scanned before
I realize that the length of the string is bigger
than tmpbuf. For bigger buffers a bigger WASTE
*/
}

Is it /my/ fault if you have a badly designed programme? Where did
"str" come from? How did you create it? Did you define its length when
you did so?

To put you out of your misery, the app in question read strings into
fixed length buffers, padded them with blanks and null-terminated
them. Thus the strings were /always/ exactly N characters long, no
more and no less. This removed any need at all anywhere to calculate
how long the strings were, because we already knew.
Because you never know when software will change and a constant
becomes a variable...

Two points here
a) constants have nothing to do with it.
b) designing an application for a series of unknown future changes for
unguessable purposes by maintenance droids of unknown quality is both
inefficient and foolish.
I also strongly suspect you're not a follower of XP. They'd shoot you
for doing that sort of thing. :)
Ahh and it was slower because of the division by zero tests?

Yes. How do I know? I measured it. Next question.
I would like to see the data that supports that hypothesis.

Sure. Get yourself employed by my former employer, and you can look at
my project post-implementation report. Its in the files of the
Technology Dept somewhere.
With today's machines, a test for zero is so fast

And you've proved this beyond all doubt on Vax/VMS, Vax/OSF,
Sun/Solaris, Windows NT/PIII, all of which were targets.
that to slow
down a calculator so that a human being notices the tests must have
been done in an incredible fashion,

Or incredibly often. You apparently have no experience of numerical
pricing techniques either. Ever heard of monte-carlo simulation?
Obvious coming from you.

The point you miss is that security and efficiency are not mutually
exclusive, nor is one axiomatically more important than the other.
Again you generalise unacceptably.
This finishes it. You, you are not AN IDIOT!

I'm glad we agree I'm not an idiot. I know that of course.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
K

Keith Thompson

João Jerónimo said:
But afaik it requires the functions to be reentrant (does it require?
I'm not sure, but suppose so...), and allocating local variables in a
stack seems the only way to achieve this...

It's easy to create C functions that aren't reentrant (e.g., if they
use variables that have static storage duration). The requirement is
that functions must be callable recursively, which is different from
being reentrant.

Local variables (more precisely, objects with automatic storage
duration) must be allocated and deallocated in a stack-like manner
(though a compiler may be able to avoid this if it can prove that the
function is never called recursively). But what most people mean by
"the stack" is a contiguously allocated region of memory indexed by a
"stack pointer" (which is typically a CPU register), that grows in a
specific direction in memory. Many (most?) C implementations use this
kind of "stack", but it's not required. An implementation could, for
example, use malloc() or something similar to allocate local variables
for each function call, and free() or something similar to deallocate
them.
 
M

Mark McIntyre

It is high time to PLONK this thread. Enjoy your war.

I agree, its been fun but EOT for me.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
R

Richard Bos

jacob navia said:
Mark McIntyre a écrit :

Knowing the length is necessary for so many situations that in MOST
cases you will end up calling strlen explicitely or implicitely
(line in strcat)

Since you are eager to claim this just about every time you advertise
your Pascal-strings scheme, against the advice of nearly everybody who,
unlike you or I, actually _is_ an expert, I'm sure you have done
extensive research on this issue and have lots of real world data to
prove that the experts are wrong and you are right. I qould suggest that
you show this data.
problems as heathfield says. But... if you need to keep the

His name, unlike yours (as stated in your own headers), starts with a
capital. Common decency is free.
??? Maybe a typo? You mean 1e+0 probably.

Not at all. 1e+0 is merely a very stupid way to write 1 in C. 1+e^x is
not a C expression but a maths one, and if you remember the range of
your exponents, it is easy to figure out why a zero check for it is
silly.
Maybe, anything can be exaggerated by did you find that code
crashing with division by zero?

Ignoring the wonky grammar, I think you'll find (if you read the
expression quoted above correctly) that Mark could easily prove that
there would be no crash.
It wazs a principle thing, and I do not find that bad. Why should be
strncpy less efficient than strcpy???

Yes, it may be 0.0001% less efficient

You have measured this? You have even done the maths? Others have.
Never said otherwise but really, you are showing us cases that
are more or less exceptional. The repeated use of strlen over and over
the same string is obvious MUCH MORE COMMON than the cases you mention.

Again: data, please. _Real_ data, not your personal code.
You misunderstand. I was saying the usage of normal C functions in
contrast to operator overloading the '+' operation.

You cannot overload the '+' operation. Unless you think you're in
comp.lang.c++, which is the next door down the corridor.


Basically, jacob, you're arguing against _real_ experts, and basing your
arguments on suppositions and loose sand. That's no way to be taken
seriously.

Richard
 
?

=?ISO-8859-1?Q?Jo=E3o_Jer=F3nimo?=

Keith said:
It's easy to create C functions that aren't reentrant (e.g., if they
use variables that have static storage duration). The requirement is
that functions must be callable recursively, which is different from
being reentrant.

Ok, but apart from code that is explicitly non-reentrant (because it
allocates data with limited scoop in a statical fashion), C code will be
reentrant, meaning that any function can call any function, including
itself, without having the functions' "instances" conflicting with each
other...

JJ
 
K

Keith Thompson

João Jerónimo said:
Ok, but apart from code that is explicitly non-reentrant (because it
allocates data with limited scoop in a statical fashion), C code will be
reentrant, meaning that any function can call any function, including
itself, without having the functions' "instances" conflicting with each
other...

Yes, C functions are reentrant unless they're not.

More seriously, the automatic objects declared within a function
(including the parameters) are guaranteed to be distinct for each call
to that function. This is subject to the "as-if" rule; a compiler is
allowed to optimize the code as long as the code can't tell tell the
difference (more or less).
 
D

Dave Vandervies

Mark McIntyre a écrit :

Knowing the length is necessary for so many situations that in MOST
cases you will end up calling strlen explicitely or implicitely
(line in strcat)

In many cases you need to pass the string to another function.
In most cases you need to pass the length or the called function must
call strlen. To avoid an extra argument, most programmers will just
pass the string, forcing again a call to strlen. This is a horrible
waste with C string since in text handling programs, strings are passed
from function to function calling strlen for the same string over
and over.

If knowing the length of strings is that important, can you explain
how counted strings would have made this code easier to write, clearer,
or less error-prone?
(This is the least-trivial string processing code I've written in recent
memory, so it's as close to a representative example as I can give.)

For anybody else who's following along, commentary and suggestions about
the code itself is also welcome. (It does require an ASCII system,
which seemed like a suitable restriction since the data it works with is
defined to be ASCII. The character set dependency could be eliminated
if necessary by writing the ASCII code points and case conversion into
the code instead of using character constants and toupper, and I think
that if that were done this code could be inserted into a strictly
conforming C program without affecting its strictly-conforming-ness
modulo translation limits.)


/* -8<--Code starts here--8<- */
#include <assert.h>
#include <ctype.h>
#include <string.h>

/*Verify checksum (if present) and split fields in a NMEA sentence.
Inputs:
sentence is a string containing the NMEA sentence.
This string IS MODIFIED on successful completion.
fields is an array of char *. On successful return, fields
contains a pointer to the ith field of the sentence (fields[0]
is the sentence identifier and fields[ret-1] is the last data
field).
nfields is the maximum number of fields to unpack.
Return value:
If sentence does not contain a correctly formatted NMEA sentence or
contains a sentence with an incorrect checksum, returns 0 and does
not modify sentence or fields.
If nfields is too small, returns negative value such that -ret is the
number of fields needed and does not modify sentence or fields.
On success, returns the number of fields unpacked, and modifies
sentence by replacing all field separators (commas and the '*' or
'\r' following the data) with '\0' to allow fields to point
into the original string.
Correctly formatted NMEA sentences have the form
"$TTSSS,comma,separated,fields*CC\r\n" for checksummed sentences or
"$TTSSS,comma,separated,fields\r\n" for non-checksummed sentences.
The contents (other than commas) of the fields between the initial '$'
and the terminating '*' or '\r', and any characters after the checksum
or after the '\r' for sentences without a checksum, are ignored here.
The sentence need not start at the beginning of the string. If the
string contains more than one sentence, all but the first will be
ignored.
*/
int unpack_nmea(char *sentence,char **fields, int nfields)
{
static char *hexdigits="0123456789ABCDEF";
int needed;
char *start,*ptr;
char cksum=0;
int i;

ptr=start=strchr(sentence,'$');
if(!ptr)
{
/*No '$' to start sentence*/
return 0;
}

/*First pass: Check checksum and count fields*/
ptr++;
needed=1;
while(*ptr && *ptr!='*' && *ptr!='\r')
{
if(*ptr==',')
{
needed++;
}
cksum^=*ptr;
ptr++;
}

/*Now we can check whether the input is well-formed...*/
if(*ptr=='0')
{
/*Not a well-formed sentence (no terminator)*/
return 0;
}
if(*ptr=='*')
{
/*Checksummed sentence, verify checksum*/
if(toupper(ptr[1])!=hexdigits[cksum>>4]
|| toupper(ptr[2])!=hexdigits[cksum&0xf])
{
/*Checksum error*/
return 0;
}
}

/*...and whether we have enough space to pack the output*/
if(needed>nfields)
return -needed;

/*Now we just have to split up the string and pack fields[]*/
ptr=start;
for(i=0;i<needed;i++)
{
ptr++;
fields=ptr;
ptr+=strcspn(ptr,",*\r");
assert(*ptr==',' || *ptr=='*' || *ptr=='\r');
*ptr=0;
}

return needed;
}
/* -8<--Code ends here--8<- */


dave
 
J

jacob navia

Dave Vandervies a écrit :
If knowing the length of strings is that important, can you explain
how counted strings would have made this code easier to write, clearer,
or less error-prone?


/* -8<--Code starts here--8<- */
#include <assert.h>
#include <ctype.h>
#include <string.h>

int unpack_nmea(char *sentence,char **fields, int nfields)
{
static char *hexdigits="0123456789ABCDEF";
int needed;
char *start,*ptr;
char cksum=0;
int i;

ptr=start=strchr(sentence,'$');
-------
In the strchr call above, a counted strings implementation can
safely replace a strchr with memchr, that doesn't check at each
character the terminating zero but just makes a bounded
memory scan
---------
if(!ptr)
{
/*No '$' to start sentence*/
return 0;
}

/*First pass: Check checksum and count fields*/
ptr++;
needed=1;
while(*ptr && *ptr!='*' && *ptr!='\r')
{
--------
Here the string library provides
Strfind_firstof(String, setOfChars);
--------
if(*ptr==',')
{
needed++;
}
cksum^=*ptr;
ptr++;
}

/*Now we can check whether the input is well-formed...*/
if(*ptr=='0')
-------
Are you sure you are testing for the character zero ('0') and
not for the terminating zero ( 0 ) ?????????
-------
{
/*Not a well-formed sentence (no terminator)*/
return 0;
}
if(*ptr=='*')
{
/*Checksummed sentence, verify checksum*/
if(toupper(ptr[1])!=hexdigits[cksum>>4]
|| toupper(ptr[2])!=hexdigits[cksum&0xf])
{
/*Checksum error*/
return 0;
}
}

/*...and whether we have enough space to pack the output*/
if(needed>nfields)
return -needed;

/*Now we just have to split up the string and pack fields[]*/
ptr=start;
for(i=0;i<needed;i++)
{
ptr++;
fields=ptr;
ptr+=strcspn(ptr,",*\r");

---------
The counted strcspn version needs NOT to test for a terminating zero
but just for the pattern being searched
---------
assert(*ptr==',' || *ptr=='*' || *ptr=='\r');
*ptr=0;
}

return needed;
}
/* -8<--Code ends here--8<- */


dave


But I may disappoint you since in the implementation of lcc-win32 the
strings are probably much slower than they ought to be since the
main thrust of the package is to provide more security and not speed.

I will start a faster version soon.

As you can see, the main advantages are the obviating for the tests
for the zero byte.

jacob
 
R

Richard Heathfield

jacob navia said:
Dave Vandervies a écrit :
-------
In the strchr call above, a counted strings implementation can
safely replace a strchr with memchr, that doesn't check at each
character the terminating zero but just makes a bounded
memory scan

Whilst that *is* an improvement, it's a micro-optimisation, since each
character in turn is being examined anyway.

Here the string library provides
Strfind_firstof(String, setOfChars);

*The* string library is the set of functions provided as part of any hosted
C implementation, and it doesn't supply any function of the name specified.
If you mean some third-party library of your own creation, you'd be wise to
specify this, to avoid confusion.

Incidentally, *THE* string library provides strcspn and strpbrk.


A reasonable question. Watch what you're doing with all those question
marks, though...


Again, whilst this *is* an improvement, it is merely a micro-optimisation,
of little or no real consequence. It's not as if you're reducing the time
complexity of the algorithm.
But I may disappoint you since in the implementation of lcc-win32 the
strings are probably much slower than they ought to be since the
main thrust of the package is to provide more security and not speed.

I will start a faster version soon.

As you can see, the main advantages are the obviating for the tests
for the zero byte.

If that's the main advantage, you may as well throw it away, since it isn't
*enough* of an advantage to make it worth doing.

The main advantages of my own string library are:

1) it caches string lengths, thus allowing fast len, cat and cpy operations;
2) it resizes buffers when necessary, without troubling the user, and keeps
extra space around so that it doesn't need to go to the well every time;
3) it contains several useful string functions not provided by the standard
library;
4) it is written in ISO C and doesn't depend on any particular compiler
features.

The first of these has genuine and significant time complexity reduction
benefits. The second takes a load off the programmer's shoulders. The third
is basically a sack of nice toys. And the fourth is essential if the code
is to remain viable in the long term.
 

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,813
Messages
2,569,696
Members
45,483
Latest member
TedDvb6626

Latest Threads

Top