Discussion:
Some ideas about c?
Add Reply
Vassilis Spiliopoulos
2017-05-17 20:23:15 UTC
Reply
Permalink
Raw Message
Well I am a newbie yet I have not decided yet if I should start c or c++
Please tell me your ideas

---
This email has been checked for viruses by AVG.
http://www.avg.com
Ian Collins
2017-05-17 20:40:04 UTC
Reply
Permalink
Raw Message
Post by Vassilis Spiliopoulos
Well I am a newbie yet I have not decided yet if I should start c or c++
In part it depends what you want to do. If you are just learning, learn
both so you can form your own opinions.
--
Ian
GOTHIER Nathan
2017-05-17 21:00:15 UTC
Reply
Permalink
Raw Message
On Wed, 17 May 2017 23:23:15 +0300
Post by Vassilis Spiliopoulos
Well I am a newbie yet I have not decided yet if I should start c or c++
Please tell me your ideas
Nobody write true C++ programs since nobody really master C++.

Just compare how bloated C++ (~1300 pages by ~50 lines) is Vs C (~700 pages
by ~45 lines).

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

The C++ language ripped off the C language with the addition of bad concepts
like Apple ripped off free BSD code to sell PC and phones to retards including
its BadOS.

Really nobody should ruine his entire life to master C++.

Just quickly learn C and be creative! ;-)
s***@casperkitty.com
2017-05-17 21:59:35 UTC
Reply
Permalink
Raw Message
Post by GOTHIER Nathan
Just compare how bloated C++ (~1300 pages by ~50 lines) is Vs C (~700 pages
by ~45 lines).
Compare either of those to a 1974 C reference manual (31 pages)

https://www.bell-labs.com/usr/dmr/www/cman.pdf

Although there have been a few useful changes since then, I'm not sure that
the language has become 50 times as useful as the 1974 version.
GOTHIER Nathan
2017-05-17 22:08:55 UTC
Reply
Permalink
Raw Message
On Wed, 17 May 2017 14:59:35 -0700 (PDT)
Post by s***@casperkitty.com
Post by GOTHIER Nathan
Just compare how bloated C++ (~1300 pages by ~50 lines) is Vs C (~700 pages
by ~45 lines).
Compare either of those to a 1974 C reference manual (31 pages)
https://www.bell-labs.com/usr/dmr/www/cman.pdf
Although there have been a few useful changes since then, I'm not sure that
the language has become 50 times as useful as the 1974 version.
The C Reference Manual by Dennis RITCHIE doesn't include the C Standard Library
definition. I'm pretty sure even these days some people think the C language is
more than 20 times as useful as the 1974 version thanks to the library like
some people think the C++ language is more than twice as useful as C thanks to
the STL.
s***@casperkitty.com
2017-05-18 05:09:36 UTC
Reply
Permalink
Raw Message
Post by GOTHIER Nathan
The C Reference Manual by Dennis RITCHIE doesn't include the C Standard Library
definition. I'm pretty sure even these days some people think the C language is
more than 20 times as useful as the 1974 version thanks to the library like
some people think the C++ language is more than twice as useful as C thanks to
the STL.
Parts of the standard libraries are useful, but many parts are just plain
horribly designed. Further, there are many application fields where only
small portions of the standard libraries get used at all, and relatively
few parts would be indispensable. Having sets of common libraries is
helpful, but trying to have a one-size-fits-all approach that ignores
features that are available on many systems and needed for many applications
(e.g. character-at-a-time console input) is not particularly helpful.

A key feature of the 1974 C which set it apart from other languages of
the time was that given access to just a few OS primitives or abilities,
almost everything in the Standard library could be accomplished entirely
in C code. Nowadays some compiler writers have an attitude that programmers
shouldn't expect to be able to use memory as one type and then recycle it
for use as another without using malloc/free or other such functions, but
reading K&R it would seem one of the things Ritchie was really proud of was
that his language allowed programmers to do precisely that (I've not seen
a Pascal book describe how to do such a thing in Pascal, for example).

IMHO, C would be much better if it were somewhat better subdivided into a
core language with a variety of optional features. Many features should be
expected in almost any quality implementation, but implementations that are
subject to extreme resource constraints or other such considerations would
not be required to support them all. Failure to acknowledge features that
are supported by many but not all implementations fragments the language far
more than would recognition that there should be more than two kinds of
implementation.
Ian Collins
2017-05-18 06:22:14 UTC
Reply
Permalink
Raw Message
Post by s***@casperkitty.com
Post by GOTHIER Nathan
The C Reference Manual by Dennis RITCHIE doesn't include the C Standard Library
definition. I'm pretty sure even these days some people think the C language is
more than 20 times as useful as the 1974 version thanks to the library like
some people think the C++ language is more than twice as useful as C thanks to
the STL.
Parts of the standard libraries are useful, but many parts are just plain
horribly designed.
That's because they weren't designed, they evolved :)
--
Ian
GOTHIER Nathan
2017-05-18 10:36:45 UTC
Reply
Permalink
Raw Message
On Wed, 17 May 2017 22:09:36 -0700 (PDT)
Post by s***@casperkitty.com
Parts of the standard libraries are useful, but many parts are just plain
horribly designed. Further, there are many application fields where only
small portions of the standard libraries get used at all, and relatively
few parts would be indispensable. Having sets of common libraries is
helpful, but trying to have a one-size-fits-all approach that ignores
features that are available on many systems and needed for many applications
(e.g. character-at-a-time console input) is not particularly helpful.
That's even worse with the generic programming paradigm pushed by the STL.
Generic programming aims at being universal but lacks the effiency of a well
designed solution. Once more, the programmer is forced to adapt his approach to
fit the generic logic without any added value.
Post by s***@casperkitty.com
A key feature of the 1974 C which set it apart from other languages of
the time was that given access to just a few OS primitives or abilities,
almost everything in the Standard library could be accomplished entirely
in C code. Nowadays some compiler writers have an attitude that programmers
shouldn't expect to be able to use memory as one type and then recycle it
for use as another without using malloc/free or other such functions, but
reading K&R it would seem one of the things Ritchie was really proud of was
that his language allowed programmers to do precisely that (I've not seen
a Pascal book describe how to do such a thing in Pascal, for example).
Indeed. I assume that's why C provides the linkage notion bound to the a scope
in the hope that programmers could reuse every piece of memory.
Post by s***@casperkitty.com
IMHO, C would be much better if it were somewhat better subdivided into a
core language with a variety of optional features. Many features should be
expected in almost any quality implementation, but implementations that are
subject to extreme resource constraints or other such considerations would
not be required to support them all. Failure to acknowledge features that
are supported by many but not all implementations fragments the language far
more than would recognition that there should be more than two kinds of
implementation.
Although a standard library give a powerful impulse to the adoption of regular
features, however its extension is problematic.

In my eyes, the C standard shouldn't include a standard library in order to
concentrate all the effort on the true language definition. I would prefer the
C standard library to be a side project with a modular approach such as
different parts of the library can optionally be implemented and extended over
the time with a global scheme in mind.
Malcolm McLean
2017-05-18 10:53:29 UTC
Reply
Permalink
Raw Message
Post by GOTHIER Nathan
That's even worse with the generic programming paradigm pushed by the STL.
Generic programming aims at being universal but lacks the effiency of a well
designed solution. Once more, the programmer is forced to adapt his approach to
fit the generic logic without any added value.
Templates are efficient.
The problem is that when a type is templated, you don't know what symbols
ans operations the type needs to support. This isn't such a problem with STL -
once you know you need a default constructor and a copy constructor and
a move constructor for heavyweight objects, you know. But when non-standard
library programmers create their own generics, it becomes a big problem.
Post by GOTHIER Nathan
In my eyes, the C standard shouldn't include a standard library in order to
concentrate all the effort on the true language definition. I would prefer the
C standard library to be a side project with a modular approach such as
different parts of the library can optionally be implemented and extended over
the time with a global scheme in mind.
The malloc family of functions are special. A pure function may need to call
malloc and free. Any other subroutines can be supplied or folded into the
main function.
But really you want standard math functions and a few standard string handling
functions, the first because they are a pain to write, the second because otherwise
everyone has their own version of strcpy() which accepts parameters in a different
order or copies to and from dynamic memory or takes a length parameter. Any
of those things you can build a case for, but it's best to stick to a standard.
GOTHIER Nathan
2017-05-18 12:24:01 UTC
Reply
Permalink
Raw Message
On Thu, 18 May 2017 03:53:29 -0700 (PDT)
Post by Malcolm McLean
Templates are efficient.
The problem is that when a type is templated, you don't know what symbols
ans operations the type needs to support. This isn't such a problem with STL -
once you know you need a default constructor and a copy constructor and
a move constructor for heavyweight objects, you know. But when non-standard
library programmers create their own generics, it becomes a big problem.
Templates are as efficient as a generic logic can be but a specifically
designed interface is way more efficient. It's like pretending a general
purpose circuit such as a microprocessor is the only way to process all kind of
data but why do so many people buy graphic cards?

The only reason for the STL to be is to lower the bar for unskilled
programmers.
Post by Malcolm McLean
The malloc family of functions are special. A pure function may need to call
malloc and free. Any other subroutines can be supplied or folded into the
main function.
But really you want standard math functions and a few standard string handling
functions, the first because they are a pain to write, the second because otherwise
everyone has their own version of strcpy() which accepts parameters in a different
order or copies to and from dynamic memory or takes a length parameter. Any
of those things you can build a case for, but it's best to stick to a standard.
I doubt that all C programmers need float, complex type or even string utilities.

Once more, if it's difficult to write it doesn't mean it needs to be standard
but only you need a library to avoid the pain.

Do we need GTK+ to be included in the C standard? I don't think so.
Jerry Stuckle
2017-05-18 12:37:41 UTC
Reply
Permalink
Raw Message
Post by GOTHIER Nathan
On Thu, 18 May 2017 03:53:29 -0700 (PDT)
Post by Malcolm McLean
Templates are efficient.
The problem is that when a type is templated, you don't know what symbols
ans operations the type needs to support. This isn't such a problem with STL -
once you know you need a default constructor and a copy constructor and
a move constructor for heavyweight objects, you know. But when non-standard
library programmers create their own generics, it becomes a big problem.
Templates are as efficient as a generic logic can be but a specifically
designed interface is way more efficient. It's like pretending a general
purpose circuit such as a microprocessor is the only way to process all kind of
data but why do so many people buy graphic cards?
The only reason for the STL to be is to lower the bar for unskilled
programmers.
No, STL is like any other library - including the standard C libraries.
It is there so that people don't have to keep rewriting the same code
over and over again.

You could also code a more optimized version of printf() every time you
need to output something. Or more efficient versions of malloc() and
free() for your specific memory allocation needs. But do you?
Post by GOTHIER Nathan
Post by Malcolm McLean
The malloc family of functions are special. A pure function may need to call
malloc and free. Any other subroutines can be supplied or folded into the
main function.
But really you want standard math functions and a few standard string handling
functions, the first because they are a pain to write, the second because otherwise
everyone has their own version of strcpy() which accepts parameters in a different
order or copies to and from dynamic memory or takes a length parameter. Any
of those things you can build a case for, but it's best to stick to a standard.
I doubt that all C programmers need float, complex type or even string utilities.
I would say every serious C programmer needs floating point numbers and
string utilities at some point. Complex type, not so much.
Post by GOTHIER Nathan
Once more, if it's difficult to write it doesn't mean it needs to be standard
but only you need a library to avoid the pain.
Do we need GTK+ to be included in the C standard? I don't think so.
There are lots of special purpose libraries I find handy but don't need
to necessarily be part of the standard. IMHO GTK+ falls into that category.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Malcolm McLean
2017-05-18 12:47:00 UTC
Reply
Permalink
Raw Message
Post by Jerry Stuckle
I would say every serious C programmer needs floating point numbers and
string utilities at some point. Complex type, not so much.
I usually test out a new graphics system by writing a Mandelbrot set browser
for it. But the only complex numbers I use for real are in Fourier transforms,
where you an't actually store them as complex, at least not easily, because
of the way the transform shuffles data for you.
Post by Jerry Stuckle
Post by GOTHIER Nathan
Do we need GTK+ to be included in the C standard? I don't think so.
There are lots of special purpose libraries I find handy but don't need
to necessarily be part of the standard. IMHO GTK+ falls into that category.
GTK+ is like Baby X. A general purpose library for writing graphical user
interfaces. But to include it a) blows up the size of the C standard and
b) triggers UI wars with the major manufacturers seeing your standard as
a threat to their brand equity in their own operating systems.
GOTHIER Nathan
2017-05-18 13:20:58 UTC
Reply
Permalink
Raw Message
On Thu, 18 May 2017 08:37:41 -0400
Post by Jerry Stuckle
No, STL is like any other library - including the standard C libraries.
It is there so that people don't have to keep rewriting the same code
over and over again.
Wrong. The STL is by definition standard, thus any C++ implementation is forced
to provide the STL that's why C++ is so much bloated.
Post by Jerry Stuckle
You could also code a more optimized version of printf() every time you
need to output something. Or more efficient versions of malloc() and
free() for your specific memory allocation needs. But do you?
Whenever I use printf() or any kind of predefined function, it is only because
it fit my requirements. If I need a better elaborated function, I write my own.
Post by Jerry Stuckle
I would say every serious C programmer needs floating point numbers and
string utilities at some point. Complex type, not so much.
Do you suggest C programmers on limited hardware aren't serious? ...
Post by Jerry Stuckle
There are lots of special purpose libraries I find handy but don't need
to necessarily be part of the standard. IMHO GTK+ falls into that category.
IMHO the C standard library too.
Malcolm McLean
2017-05-18 13:28:29 UTC
Reply
Permalink
Raw Message
Post by GOTHIER Nathan
Post by Jerry Stuckle
I would say every serious C programmer needs floating point numbers and
string utilities at some point. Complex type, not so much.
Do you suggest C programmers on limited hardware aren't serious? ...
"Serious" is a bad word. A program can be extremely simple, just controlling an
led or a thermostat, but still serious. The thermostat might be attached to a
medical device which needs to be kept at the exact temperature if the
patient is to survive.
Scott Lurndal
2017-05-18 13:56:00 UTC
Reply
Permalink
Raw Message
Post by GOTHIER Nathan
On Thu, 18 May 2017 08:37:41 -0400
Post by Jerry Stuckle
No, STL is like any other library - including the standard C libraries.
It is there so that people don't have to keep rewriting the same code
over and over again.
Wrong. The STL is by definition standard, thus any C++ implementation is forced
to provide the STL that's why C++ is so much bloated.
We get it. You hate C++. Give the rest of us a break
and keep it to yourself.
GOTHIER Nathan
2017-05-18 14:30:00 UTC
Reply
Permalink
Raw Message
On Thu, 18 May 2017 13:56:00 GMT
Post by Scott Lurndal
We get it. You hate C++. Give the rest of us a break
and keep it to yourself.
Wrong. You're a C++ cheerleader but feel frustrated that the STL can't
solve automagically your incompetence. I can garantee you C too.
Thiago Adams
2017-05-18 14:45:49 UTC
Reply
Permalink
Raw Message
Post by GOTHIER Nathan
On Thu, 18 May 2017 13:56:00 GMT
Post by Scott Lurndal
We get it. You hate C++. Give the rest of us a break
and keep it to yourself.
Wrong. You're a C++ cheerleader but feel frustrated that the STL can't
solve automagically your incompetence. I can garantee you C too.
I have some difficulties with C that I don't have with C++.

Sample:

typedef struct Node
{
...
} Node;

I do by hand a function called Node_Destroy used it
to free any resource from Node. (destructor)
And Node_Delete(p) that call Node_Destroy and then free(p);

The problem is that I need to create the same function
again and again for each type. The same for Swap.
In C++ this can be resolved by template and overriding.

Destroy(Node*p)
Destroy(Other*p)

template<class T>
void Delete(T*p)
{
Destroy(p);
free(p);
}
The same happens for containers.


What do you do?

"inline code by hand" can solve the problem

Node *p ;
...
Node_Destroy(p);
free(p);


The same for Create:

Node * p = Node_Create();

"inline code by hand"

Node* p = malloc(sizeof * p);
if (p)
{
*p = NODE_INIT;
}

So the problem is do a lot of lines or write the same code again and again.
Richard Heathfield
2017-05-18 15:08:51 UTC
Reply
Permalink
Raw Message
Post by Thiago Adams
Post by GOTHIER Nathan
On Thu, 18 May 2017 13:56:00 GMT
Post by Scott Lurndal
We get it. You hate C++. Give the rest of us a break
and keep it to yourself.
Wrong. You're a C++ cheerleader but feel frustrated that the STL can't
solve automagically your incompetence. I can garantee you C too.
I have some difficulties with C that I don't have with C++.
typedef struct Node
{
...
} Node;
I do by hand a function called Node_Destroy used it
to free any resource from Node. (destructor)
And Node_Delete(p) that call Node_Destroy and then free(p);
If Node_Destroy() has to release resources that are specific to Node,
you have to write that Node-specific releasing code /somewhere/. And if
it doesn't, why have it in the first place?
Post by Thiago Adams
The problem is that I need to create the same function
again and again for each type.
If it's the same function, use the same function. If it's not the same
function, the differences have to be programmed /somewhere/.
Post by Thiago Adams
The same for Swap.
In C++ this can be resolved by template and overriding.
Destroy(Node*p)
Destroy(Other*p)
template<class T>
void Delete(T*p)
{
Destroy(p);
free(p);
}
The same happens for containers.
Yes, but Destroy(p) is a NOP. That is, you haven't shown code for it, so
what are we to assume about it but that it's empty?
Post by Thiago Adams
What do you do?
"inline code by hand" can solve the problem
Node *p ;
...
Node_Destroy(p);
free(p);
Node * p = Node_Create();
"inline code by hand"
Node* p = malloc(sizeof * p);
if (p)
{
*p = NODE_INIT;
}
So the problem is do a lot of lines or write the same code again and again.
You have to write the code somewhere. The overhead of writing a malloc
call and brace pair in a "constructor" is very often trivial in
comparison to the effort involved in writing a typical initialisation
block, so this smacks of premature (and pointless) optimisation.

By the way, for some people at least, typing "boilerplate" code can be a
relaxing way to keep the fingers occupied while one is thinking about
what to put between the braces.

Molehill, thy name is Everest.
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
Malcolm McLean
2017-05-18 15:15:45 UTC
Reply
Permalink
Raw Message
Post by Richard Heathfield
Yes, but Destroy(p) is a NOP. That is, you haven't shown code for it, so
what are we to assume about it but that it's empty?
In C++ you normally use stl "containers" for non-scalar members, which
95% of the time means std::vectors, but can also be things like unique_ptrs
if you need to build a graph. (The unique_ptr is like a C pointer which "owns"
a memory allocation). When the object's lifetime ends, it is automatically
destroyed. But the code is in the C++ standard library, you rarely have to
write a destructor by yourself.

In fact virtually all the complexity of C++ comes down to automatic destructors.
It's the one thing C can't imitate with a bit of different syntax and boilerplate
code.
Jerry Stuckle
2017-05-18 15:46:47 UTC
Reply
Permalink
Raw Message
Post by Malcolm McLean
Post by Richard Heathfield
Yes, but Destroy(p) is a NOP. That is, you haven't shown code for it, so
what are we to assume about it but that it's empty?
In C++ you normally use stl "containers" for non-scalar members, which
95% of the time means std::vectors, but can also be things like unique_ptrs
if you need to build a graph. (The unique_ptr is like a C pointer which "owns"
a memory allocation). When the object's lifetime ends, it is automatically
destroyed. But the code is in the C++ standard library, you rarely have to
write a destructor by yourself.
In fact virtually all the complexity of C++ comes down to automatic destructors.
It's the one thing C can't imitate with a bit of different syntax and boilerplate
code.
This is one of the things I like about C++. For instance, right now I'm
using collection classes like std::vector. This is a self-sizing array
and elements can be accessed with standard array notation. I'm also
using std::map, which is like vector except the index can be anything -
not just an integer.

Within them I have struct equivalents which contain string data. String
lengths can vary anywhere from a few characters (or a null string) to
hundreds of characters - the strings are read in, so there's no
predicting the length. Rather than use char[2000] for every message and
waste huge amounts of memory, in C I would dynamically allocate the
lengths I need.

But then I have to ensure all of that is cleaned up when it is no longer
needed. This is exactly the type of operation which leads to memory
leaks. In C++, it's automatic. If I delete an element of the vector or
map, all memory associated with it is deleted automatically. And if I
delete the entire vector or map, all elements are deleted automatically.

Now all of this automated processing does have its downsides - it is
slower than the equivalent in C. The generated code is also larger.
These two reasons alone make C a better solution in many instances than
C++, and why I still write a fair amount of C code. OTOH, the code is
cleaner with fewer lines, and therefor less prone to errors.

But both languages have their advantages and disadvantages, and both
languages have their uses.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Vassilis Spiliopoulos
1970-01-01 00:00:00 UTC
Reply
Permalink
Raw Message
Post by Jerry Stuckle
Post by Malcolm McLean
Post by Richard Heathfield
Yes, but Destroy(p) is a NOP. That is, you haven't shown code for it, so
what are we to assume about it but that it's empty?
In C++ you normally use stl "containers" for non-scalar members, which
95% of the time means std::vectors, but can also be things like unique_ptrs
if you need to build a graph. (The unique_ptr is like a C pointer which "owns"
a memory allocation). When the object's lifetime ends, it is automatically
destroyed. But the code is in the C++ standard library, you rarely have to
write a destructor by yourself.
In fact virtually all the complexity of C++ comes down to automatic destructors.
It's the one thing C can't imitate with a bit of different syntax and boilerplate
code.
This is one of the things I like about C++. For instance, right now I'm
using collection classes like std::vector. This is a self-sizing array
and elements can be accessed with standard array notation. I'm also
using std::map, which is like vector except the index can be anything -
not just an integer.
Within them I have struct equivalents which contain string data. String
lengths can vary anywhere from a few characters (or a null string) to
hundreds of characters - the strings are read in, so there's no
predicting the length. Rather than use char[2000] for every message and
waste huge amounts of memory, in C I would dynamically allocate the
lengths I need.
But then I have to ensure all of that is cleaned up when it is no longer
needed. This is exactly the type of operation which leads to memory
leaks. In C++, it's automatic. If I delete an element of the vector or
map, all memory associated with it is deleted automatically. And if I
delete the entire vector or map, all elements are deleted automatically.
Now all of this automated processing does have its downsides - it is
slower than the equivalent in C. The generated code is also larger.
These two reasons alone make C a better solution in many instances than
C++, and why I still write a fair amount of C code. OTOH, the code is
cleaner with fewer lines, and therefor less prone to errors.
But both languages have their advantages and disadvantages, and both
languages have their uses.
--
==================
Remove the "x" from my email address
Jerry Stuckle
==================
So ummm I should learn both and decide what is more useful?
--
----Android NewsGroup Reader----
http://usenet.sinaapp.com/
Jerry Stuckle
2017-05-18 19:29:38 UTC
Reply
Permalink
Raw Message
Post by Vassilis Spiliopoulos
So ummm I should learn both and decide what is more useful?
There is no "more useful". Each language has its advantages and
disadvantages. Some projects will work better in C, some in C++ (and
some in an entirely different language).
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
GOTHIER Nathan
2017-05-18 23:23:15 UTC
Reply
Permalink
Raw Message
On Thu, 18 May 2017 21:33:48 +0300 (GMT+03:00)
Post by Vassilis Spiliopoulos
So ummm I should learn both and decide what is more useful?
No, just learn real programming (your d*ck with your knife) in C and let C++
cheerleaders wasting their time to adapt their buggy code to generic programming
with the STL.

If you want to be true programmer you have to embrace difficulties learning from
them and building your own portfolio of solutions called "skills". If you don't
want to solve problems you shouldn't be a programmer but a code user like a lot
a pretending C++ programmers. Using a machine gun won't make you a true hunter.
Thiago Adams
2017-05-19 01:12:12 UTC
Reply
Permalink
Raw Message
Post by GOTHIER Nathan
On Thu, 18 May 2017 21:33:48 +0300 (GMT+03:00)
Post by Vassilis Spiliopoulos
So ummm I should learn both and decide what is more useful?
No, just learn real programming (your d*ck with your knife) in C and let C++
cheerleaders wasting their time to adapt their buggy code to generic programming
with the STL.
If you want to be true programmer you have to embrace difficulties learning from
them and building your own portfolio of solutions called "skills". If you don't
want to solve problems you shouldn't be a programmer but a code user like a lot
a pretending C++ programmers. Using a machine gun won't make you a true hunter.
I don´t use reference counter.
What was trying to compare is two lines of "inline code" versus a function that is almost the same for
each type. (C++ makes easy to create just one template)

Type* p = malloc(sizeof * p);
if (p)
{
*p = TYPE_INIT;
}

Type_Destroy(p);
free(p);

versus:

Type* p = Type_Create();

Type_Delete(p);

One advantage of Type_Create is
if a have memory leak I can check in
debug using a counter.

static int Type_Instances = 0;

Type* Type_Create()
{
...
Type_Instances++;
}

void Type_Delete(Type* p)
{
Type_Instances--;
}

At the end of program
ASSERT(Type_Instances == 0);

Without to find-replace each malloc for Type*.
The disadvantage is to write many times the same code
_Create and Delete changing only the type.
Thiago Adams
2017-05-18 17:08:51 UTC
Reply
Permalink
Raw Message
Post by Richard Heathfield
Post by Thiago Adams
Post by GOTHIER Nathan
On Thu, 18 May 2017 13:56:00 GMT
Post by Scott Lurndal
We get it. You hate C++. Give the rest of us a break
and keep it to yourself.
Wrong. You're a C++ cheerleader but feel frustrated that the STL can't
solve automagically your incompetence. I can garantee you C too.
I have some difficulties with C that I don't have with C++.
typedef struct Node
{
...
} Node;
I do by hand a function called Node_Destroy used it
to free any resource from Node. (destructor)
And Node_Delete(p) that call Node_Destroy and then free(p);
If Node_Destroy() has to release resources that are specific to Node,
you have to write that Node-specific releasing code /somewhere/. And if
it doesn't, why have it in the first place?
Post by Thiago Adams
The problem is that I need to create the same function
again and again for each type.
If it's the same function, use the same function. If it's not the same
function, the differences have to be programmed /somewhere/.
Post by Thiago Adams
The same for Swap.
In C++ this can be resolved by template and overriding.
Destroy(Node*p)
Destroy(Other*p)
template<class T>
void Delete(T*p)
{
Destroy(p);
free(p);
}
The same happens for containers.
Yes, but Destroy(p) is a NOP. That is, you haven't shown code for it, so
what are we to assume about it but that it's empty?
This is the pattern I use in C:

typedef struct Node
{
String Name;
};
#define NODE_INIT {STRING_INIT}

//Init is when I use C++ or C < C99

//With C99 I could use
//#define NODE_INIT (Node) {STRING_INIT}
//*p = NODE_INIT;

void Node_Init(Node* p)
{
Node temp = NODE_INIT;
*p = temp;
}

void Node_Destroy(Node* p)
{
String_Destroy(&p->Name);
}


void Node_Swap(Node* a, Node* b)
{
Node temp = *a;
*a = *b;
*b = temp;
}

Node* Node_Create(p)
{
Node* p = malloc(sizeof * p);
if (p)
{
Node_Init(p);
}
}


void Node_Delete(Node* p)
{
if (p)
{
Node_Destroy(p);
free(p);
}
}

Basically, the repeated code is Create, Delete and Swap.
I see some advantages of using Create instead of two lines.
For instance, let's say I have some leak. I can create a counter
in Create and Delete for each type or a global one.
(Of course I don't this all the time, but sometimes is useful)

Beside this, I also have repeated code for containers.
GOTHIER Nathan
2017-05-18 22:39:29 UTC
Reply
Permalink
Raw Message
On Thu, 18 May 2017 07:45:49 -0700 (PDT)
Post by Thiago Adams
I have some difficulties with C that I don't have with C++.
I'm afraid you're blinded by your C++ approach which prevent you to do the
right thing in C.

It's not that difficult to write a generic structure in C that can be managed
by a constructor/destructor with a reference counter and pointers. That's what
is done by the STL but it's not the best way to manage any specific problem
without similarities.
Vassilis Spiliopoulos
2017-05-19 11:27:32 UTC
Reply
Permalink
Raw Message
Post by GOTHIER Nathan
On Thu, 18 May 2017 07:45:49 -0700 (PDT)
Post by Thiago Adams
I have some difficulties with C that I don't have with C++.
I'm afraid you're blinded by your C++ approach which prevent you to do the
right thing in C.
It's not that difficult to write a generic structure in C that can be managed
by a constructor/destructor with a reference counter and pointers. That's what
is done by the STL but it's not the best way to manage any specific problem
without similarities.
---
This email has been checked for viruses by AVG.
http://www.avg.com
Thank you everyone for your help.I signed up for C Associate Programmer
course at the C++ Institute.
David Brown
2017-05-19 11:41:22 UTC
Reply
Permalink
Raw Message
Post by Vassilis Spiliopoulos
Post by GOTHIER Nathan
On Thu, 18 May 2017 07:45:49 -0700 (PDT)
Post by Thiago Adams
I have some difficulties with C that I don't have with C++.
I'm afraid you're blinded by your C++ approach which prevent you to do the
right thing in C.
It's not that difficult to write a generic structure in C that can be managed
by a constructor/destructor with a reference counter and pointers. That's what
is done by the STL but it's not the best way to manage any specific problem
without similarities.
---
This email has been checked for viruses by AVG.
http://www.avg.com
Thank you everyone for your help.I signed up for C Associate Programmer
course at the C++ Institute.
So rather than deciding between learning C from C programmers, or
learning C++ from C++ programmers, you compromised on learning C from
C++ programmers?

Well, good luck anyway.
Richard Heathfield
2017-05-19 12:04:48 UTC
Reply
Permalink
Raw Message
Post by David Brown
Post by Vassilis Spiliopoulos
Post by GOTHIER Nathan
On Thu, 18 May 2017 07:45:49 -0700 (PDT)
Post by Thiago Adams
I have some difficulties with C that I don't have with C++.
I'm afraid you're blinded by your C++ approach which prevent you to do the
right thing in C.
It's not that difficult to write a generic structure in C that can be managed
by a constructor/destructor with a reference counter and pointers. That's what
is done by the STL but it's not the best way to manage any specific problem
without similarities.
---
This email has been checked for viruses by AVG.
http://www.avg.com
Thank you everyone for your help.I signed up for C Associate Programmer
course at the C++ Institute.
So rather than deciding between learning C from C programmers, or
learning C++ from C++ programmers, you compromised on learning C from
C++ programmers?
It beats the hell out of learning C++ from C programmers!
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
Keith Thompson
2017-05-19 17:00:28 UTC
Reply
Permalink
Raw Message
[...]
Post by David Brown
Post by Vassilis Spiliopoulos
Thank you everyone for your help.I signed up for C Associate Programmer
course at the C++ Institute.
So rather than deciding between learning C from C programmers, or
learning C++ from C++ programmers, you compromised on learning C from
C++ programmers?
I'm not sure I'd read too much into the fact that the organization is
called the "C++ Institute". It's entirely possible that the course is a
perfectly good one.

But that's not the way I'd bet. Here's some discussion about a
different course offered by the same organization:
https://www.quora.com/Are-C++-certificates-offered-by-CPP-Institute-worth-it

Vassilis: Are you referring to this course?
https://www.netacad.com/courses/cla-programming-c/

I presume it's not possible to see the contents of the course without
paying for it, so I can't offer a direct opinion on how good it is
(and I had never heard of the "C++ Institute" until a few minutes ago).
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
GOTHIER Nathan
2017-05-19 12:14:39 UTC
Reply
Permalink
Raw Message
On Fri, 19 May 2017 14:27:32 +0300
Post by Vassilis Spiliopoulos
Thank you everyone for your help.I signed up for C Associate Programmer
course at the C++ Institute.
Good luck in debugging bad C practices with C++ monkeys... you'll learn to
write good C from a lot of broken code. :o)
Jerry Stuckle
2017-05-18 15:33:19 UTC
Reply
Permalink
Raw Message
Post by GOTHIER Nathan
On Thu, 18 May 2017 08:37:41 -0400
Post by Jerry Stuckle
No, STL is like any other library - including the standard C libraries.
It is there so that people don't have to keep rewriting the same code
over and over again.
Wrong. The STL is by definition standard, thus any C++ implementation is forced
to provide the STL that's why C++ is so much bloated.
That is correct. And the string functions, I/O functions (printf(),
etc.) and lots of other functions are defined in the C standard. All
standard C implementations are required to provide them.

But you don't have to use STL, just like you don't have to use the
standard C libraries.
Post by GOTHIER Nathan
Post by Jerry Stuckle
You could also code a more optimized version of printf() every time you
need to output something. Or more efficient versions of malloc() and
free() for your specific memory allocation needs. But do you?
Whenever I use printf() or any kind of predefined function, it is only because
it fit my requirements. If I need a better elaborated function, I write my own.
Which is exactly why you should use STL.
Post by GOTHIER Nathan
Post by Jerry Stuckle
I would say every serious C programmer needs floating point numbers and
string utilities at some point. Complex type, not so much.
Do you suggest C programmers on limited hardware aren't serious? ...
Nope, but they don't do *only* limited hardware, and quite a bit of
limited hardware does support floating point numbers. Plus all I know
of support string functions.
Post by GOTHIER Nathan
Post by Jerry Stuckle
There are lots of special purpose libraries I find handy but don't need
to necessarily be part of the standard. IMHO GTK+ falls into that category.
IMHO the C standard library too.
So, you aren't forced to use it. You can write your own version of
every function in the C library.

Personally, I'd rather make more productive use of my time than to
repeatedly reinvent the wheel. The same is true for programmers on any
project I manage.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Malcolm McLean
2017-05-18 15:47:46 UTC
Reply
Permalink
Raw Message
Post by Jerry Stuckle
So, you aren't forced to use it. You can write your own version of
every function in the C library.
Personally, I'd rather make more productive use of my time than to
repeatedly reinvent the wheel. The same is true for programmers on any
project I manage.
If you ask a programmer for milk in your coffee he'll go and set up a
dairy farm.
s***@casperkitty.com
2017-05-18 15:48:39 UTC
Reply
Permalink
Raw Message
Post by Jerry Stuckle
Nope, but they don't do *only* limited hardware, and quite a bit of
limited hardware does support floating point numbers. Plus all I know
of support string functions.
Zero-terminated strings are an okay choice for read-only strings, but not
really for code that needs to actively manipulate strings. Doing any kind
of string manipulation requires keeping track of the length, and if one is
keeping track of the length the terminating zero is just a wasted byte.

There are times when floating-point can be useful, but for many kinds of
applications on smaller systems, the time required for an implementer to
provide floating-point support could likely be better spent on other things
like efficient computations of the form int8*int16/int8, int8*int16>>8,
etc. along with variations that support rounding.
Malcolm McLean
2017-05-18 16:02:38 UTC
Reply
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Jerry Stuckle
Nope, but they don't do *only* limited hardware, and quite a bit of
limited hardware does support floating point numbers. Plus all I know
of support string functions.
Zero-terminated strings are an okay choice for read-only strings, but not
really for code that needs to actively manipulate strings. Doing any kind
of string manipulation requires keeping track of the length, and if one is
keeping track of the length the terminating zero is just a wasted byte.
Depends what you are doing. Strings have to mean something, and if
scanning the string for the nul byte to get the length is going to make the
difference, how many strings do you have in your program and how were they
generated? (As a bioinformatician of course one possible answer is "genetic
data")
s***@casperkitty.com
2017-05-18 17:52:46 UTC
Reply
Permalink
Raw Message
Post by Malcolm McLean
Post by s***@casperkitty.com
Zero-terminated strings are an okay choice for read-only strings, but not
really for code that needs to actively manipulate strings. Doing any kind
of string manipulation requires keeping track of the length, and if one is
keeping track of the length the terminating zero is just a wasted byte.
Depends what you are doing. Strings have to mean something, and if
scanning the string for the nul byte to get the length is going to make the
difference, how many strings do you have in your program and how were they
generated? (As a bioinformatician of course one possible answer is "genetic
data")
General-purpose code to safely append data to a string buffer (a rather
common operation) needs to know three things: (1) where the buffer is;
(2) how long a string is; (3) how big the buffer is. Zero-terminated
strings allow #2 to be derived from #1, slowly, and do nothing to assist
with #3. Prefixed strings, by contrast, make it possible to have use
multiple string representations including a structure like e.g.

struct STRING_DESCRIPTOR {
char header_byte; // Will be e.g. 255 for string descriptor
char descriptor_subtype;
char *data;
size_t length, size; };

and then have code which expects a string look at the header byte and
either use the data following it (if it isn't 255) or else interpret
its address as a STRING_DESCRIPTOR* and use the data indicated thereby.
Such an approach would make it possible to have a function like sprintf
automatically sense the size of its destination and, depending upon the
descriptor_subtype, do things like realloc() the destination storage as
needed.
Jerry Stuckle
2017-05-18 19:35:49 UTC
Reply
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Jerry Stuckle
Nope, but they don't do *only* limited hardware, and quite a bit of
limited hardware does support floating point numbers. Plus all I know
of support string functions.
Zero-terminated strings are an okay choice for read-only strings, but not
really for code that needs to actively manipulate strings. Doing any kind
of string manipulation requires keeping track of the length, and if one is
keeping track of the length the terminating zero is just a wasted byte.
If you want to use the string libraries, you will use null-terminated
strings. No separate length field (more than one byte if the string is
Post by s***@casperkitty.com
255 characters) needed, and no need to ensure the length field is
always synchronized with the actual string.

And the string libraries work as well as anything for manipulating
strings, even without a length field.

But I might suggest you switch to PASCAL. It keeps track of the length
of strings (and most implementations require at least two bytes per
string for the length field).
Post by s***@casperkitty.com
There are times when floating-point can be useful, but for many kinds of
applications on smaller systems, the time required for an implementer to
provide floating-point support could likely be better spent on other things
like efficient computations of the form int8*int16/int8, int8*int16>>8,
etc. along with variations that support rounding.
If the compiler supports the C standard, it will include floating point
support (either in hardware or software). If it doesn't, it's not
standards compliant.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
s***@casperkitty.com
2017-05-18 21:01:34 UTC
Reply
Permalink
Raw Message
Post by Jerry Stuckle
If you want to use the string libraries, you will use null-terminated
strings. No separate length field (more than one byte if the string is
Post by s***@casperkitty.com
255 characters) needed, and no need to ensure the length field is
always synchronized with the actual string.
On 1980s Macintosh C compilers, a string literal starting with "\p"
would be preceded by a length byte. An absolutely essential extension
when writing Macintosh applications, since the OS functions all expected
pointers to length-prefixed strings.

Functions which needed to operate on strings longer than 256 bytes generally
used handles to objects which the OS could relocate as needed so as to avoid
fragmentation.
Post by Jerry Stuckle
And the string libraries work as well as anything for manipulating
strings, even without a length field.
They're pretty terrible for most purposes. If one wants to concatenate
two strings and doesn't knows the lengths, memcpy() will be faster and in
pretty much every way better than strcat(). If one doesn't know the
lengths, but somehow knows that the destination is big enough, strcat()
might be usable I suppose, but using strlen on strings whose length isn't
known, ensuring that adequate space exists, and then using memcpy, seems
like a better approach than giving the strings to strcat and hoping nothing
blows up.
Post by Jerry Stuckle
But I might suggest you switch to PASCAL. It keeps track of the length
of strings (and most implementations require at least two bytes per
string for the length field).
There are some things 1980s C could do better than 1980s Pascal, but many
others where Pascal was better.
Post by Jerry Stuckle
Post by s***@casperkitty.com
There are times when floating-point can be useful, but for many kinds of
applications on smaller systems, the time required for an implementer to
provide floating-point support could likely be better spent on other things
like efficient computations of the form int8*int16/int8, int8*int16>>8,
etc. along with variations that support rounding.
If the compiler supports the C standard, it will include floating point
support (either in hardware or software). If it doesn't, it's not
standards compliant.
True, because the Standard imposes requirements that make some
implementations less suitable for their intended purpose than they
otherwise would be. Given that the Standard doesn't require that a
freestanding implementation be capable of *any* observable behavior,
requiring that such implementations pass floating-point variadic
arguments using a type with a 40+-bit significant doesn't seem very
helpful.
Jerry Stuckle
2017-05-18 21:38:26 UTC
Reply
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Jerry Stuckle
If you want to use the string libraries, you will use null-terminated
strings. No separate length field (more than one byte if the string is
Post by s***@casperkitty.com
255 characters) needed, and no need to ensure the length field is
always synchronized with the actual string.
On 1980s Macintosh C compilers, a string literal starting with "\p"
would be preceded by a length byte. An absolutely essential extension
when writing Macintosh applications, since the OS functions all expected
pointers to length-prefixed strings.
So, who cares what non-compliant compilers did? A properly designed C
library would handle the specific OS requirement without breaking
conformance.
Post by s***@casperkitty.com
Functions which needed to operate on strings longer than 256 bytes generally
used handles to objects which the OS could relocate as needed so as to avoid
fragmentation.
See above.
Post by s***@casperkitty.com
Post by Jerry Stuckle
And the string libraries work as well as anything for manipulating
strings, even without a length field.
They're pretty terrible for most purposes. If one wants to concatenate
two strings and doesn't knows the lengths, memcpy() will be faster and in
pretty much every way better than strcat(). If one doesn't know the
lengths, but somehow knows that the destination is big enough, strcat()
might be usable I suppose, but using strlen on strings whose length isn't
known, ensuring that adequate space exists, and then using memcpy, seems
like a better approach than giving the strings to strcat and hoping nothing
blows up.
C is not a great language for handling strings. But adding a length to
the string wouldn't make it any better.

And memcpy does not add the trailing null character.
Post by s***@casperkitty.com
Post by Jerry Stuckle
But I might suggest you switch to PASCAL. It keeps track of the length
of strings (and most implementations require at least two bytes per
string for the length field).
There are some things 1980s C could do better than 1980s Pascal, but many
others where Pascal was better.
So, I would suggest you program in PASCAL.
Post by s***@casperkitty.com
Post by Jerry Stuckle
Post by s***@casperkitty.com
There are times when floating-point can be useful, but for many kinds of
applications on smaller systems, the time required for an implementer to
provide floating-point support could likely be better spent on other things
like efficient computations of the form int8*int16/int8, int8*int16>>8,
etc. along with variations that support rounding.
If the compiler supports the C standard, it will include floating point
support (either in hardware or software). If it doesn't, it's not
standards compliant.
True, because the Standard imposes requirements that make some
implementations less suitable for their intended purpose than they
otherwise would be. Given that the Standard doesn't require that a
freestanding implementation be capable of *any* observable behavior,
requiring that such implementations pass floating-point variadic
arguments using a type with a 40+-bit significant doesn't seem very
helpful.
The standard never defines HOW an operation is performed. Just WHAT the
operation is.

We all know you don't like C. So why don't you find a language you do
like and stop wasting bandwidth bitching about C? No one here cares.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
s***@casperkitty.com
2017-05-18 22:54:32 UTC
Reply
Permalink
Raw Message
Post by Jerry Stuckle
Post by s***@casperkitty.com
On 1980s Macintosh C compilers, a string literal starting with "\p"
would be preceded by a length byte. An absolutely essential extension
when writing Macintosh applications, since the OS functions all expected
pointers to length-prefixed strings.
So, who cares what non-compliant compilers did? A properly designed C
library would handle the specific OS requirement without breaking
conformance.
The Standard allows compilers to add additional backslash escapes as an
extension. The implementation came with bundled libraries for file I/O,
but and I think its OS interface libraries included some functions that
would convert C strings to Pascal strings and then perform an OS request
(e.g. to render a string onto a GrafPort using its current selected font)
but calling a function which would copy a C string to a separate buffer
and then pass that to the OS was slower than simply using Pascal strings
when communicating with OS code that needed them.
Post by Jerry Stuckle
Post by s***@casperkitty.com
Functions which needed to operate on strings longer than 256 bytes generally
used handles to objects which the OS could relocate as needed so as to avoid
fragmentation.
See above.
Using OS-managed handles made it possible to grow and shrink large strings
without fragmentation killing everything, at least if there weren't too many
immovable objects fragmenting the free store. While code could use malloc,
realloc, and free, application performance would often be better if programs
used the system's relocatable memory handles instead when practical.
Post by Jerry Stuckle
Post by s***@casperkitty.com
They're pretty terrible for most purposes. If one wants to concatenate
two strings and doesn't knows the lengths, memcpy() will be faster and in
pretty much every way better than strcat(). If one doesn't know the
lengths, but somehow knows that the destination is big enough, strcat()
might be usable I suppose, but using strlen on strings whose length isn't
known, ensuring that adequate space exists, and then using memcpy, seems
like a better approach than giving the strings to strcat and hoping nothing
blows up.
C is not a great language for handling strings. But adding a length to
the string wouldn't make it any better.
Allowing the byte identified by a "string pointer" to indicate whether the
pointer identifies:

A string of a given length that precisely fills its buffer

An empty buffer of a given size

A buffer of a given size which is not completely full, and has the number
of slack bytes stored at the end.

A string descriptor which starts with a couple bytes describing what it
is, along with a pointer to the buffer, its size, the length of string
therein, and optional information allowing the buffer to be resized.

would make it possible to have a function like "strcat" whose first argument
can be a fixed-size buffer, a descriptor of a fixed-size block of storage,
or a descriptor for a resizable block of storage, and whose second argument
could be any kind of string or string descriptor, without having to pass it
anything except two string pointers. A string buffer would have to be
initialized prior to use, but that would only require storing 1-5 bytes to
it, depending upon length.

The biggest obstacle to using such strings is the lack of any decent way
to include string literals in-line within C code. If the language supported
static compound literals and a construct like:

(constExpr ? (void*)&staticCompoundLiteral1 : (void*)&staticCompoundLiteral2)

would only generate one of them, code could be written more cleanly using
prefixed strings than C strings.
Post by Jerry Stuckle
And memcpy does not add the trailing null character.
It will copy any trailing null character which is present in the original if
the null byte is included in the size.
Post by Jerry Stuckle
We all know you don't like C. So why don't you find a language you do
like and stop wasting bandwidth bitching about C? No one here cares.
Low-level C is the best language for embedded systems. Today's compiler
writers, however, prefer to process a different language which is less
suitable for such purposes.
Jerry Stuckle
2017-05-19 02:17:33 UTC
Reply
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Jerry Stuckle
Post by s***@casperkitty.com
On 1980s Macintosh C compilers, a string literal starting with "\p"
would be preceded by a length byte. An absolutely essential extension
when writing Macintosh applications, since the OS functions all expected
pointers to length-prefixed strings.
So, who cares what non-compliant compilers did? A properly designed C
library would handle the specific OS requirement without breaking
conformance.
The Standard allows compilers to add additional backslash escapes as an
extension. The implementation came with bundled libraries for file I/O,
but and I think its OS interface libraries included some functions that
would convert C strings to Pascal strings and then perform an OS request
(e.g. to render a string onto a GrafPort using its current selected font)
but calling a function which would copy a C string to a separate buffer
and then pass that to the OS was slower than simply using Pascal strings
when communicating with OS code that needed them.
An extension is not standard C.
Post by s***@casperkitty.com
Post by Jerry Stuckle
Post by s***@casperkitty.com
Functions which needed to operate on strings longer than 256 bytes generally
used handles to objects which the OS could relocate as needed so as to avoid
fragmentation.
See above.
Using OS-managed handles made it possible to grow and shrink large strings
without fragmentation killing everything, at least if there weren't too many
immovable objects fragmenting the free store. While code could use malloc,
realloc, and free, application performance would often be better if programs
used the system's relocatable memory handles instead when practical.
Sure. But it is not standard C, and is not compatible with any other C
compilers.
Post by s***@casperkitty.com
Post by Jerry Stuckle
Post by s***@casperkitty.com
They're pretty terrible for most purposes. If one wants to concatenate
two strings and doesn't knows the lengths, memcpy() will be faster and in
pretty much every way better than strcat(). If one doesn't know the
lengths, but somehow knows that the destination is big enough, strcat()
might be usable I suppose, but using strlen on strings whose length isn't
known, ensuring that adequate space exists, and then using memcpy, seems
like a better approach than giving the strings to strcat and hoping nothing
blows up.
C is not a great language for handling strings. But adding a length to
the string wouldn't make it any better.
Allowing the byte identified by a "string pointer" to indicate whether the
A string of a given length that precisely fills its buffer
An empty buffer of a given size
A buffer of a given size which is not completely full, and has the number
of slack bytes stored at the end.
A string descriptor which starts with a couple bytes describing what it
is, along with a pointer to the buffer, its size, the length of string
therein, and optional information allowing the buffer to be resized.
A string is not the same as a buffer - in *ANY* language. And when the
string has a length as the first two bytes (one more byte than a null
terminator), that length is the length of the string, not the buffer.

And if you have a string descriptor, you are talking a lot more than a
single terminating null byte.
Post by s***@casperkitty.com
would make it possible to have a function like "strcat" whose first argument
can be a fixed-size buffer, a descriptor of a fixed-size block of storage,
or a descriptor for a resizable block of storage, and whose second argument
could be any kind of string or string descriptor, without having to pass it
anything except two string pointers. A string buffer would have to be
initialized prior to use, but that would only require storing 1-5 bytes to
it, depending upon length.
A fixed-sized buffer would limit any operation to the length of that
buffer, as well as requiring all operations to use that size buffer.
Both are severely limiting factors.

And having to initialize a string buffer before using string function is
another problem.
Post by s***@casperkitty.com
The biggest obstacle to using such strings is the lack of any decent way
to include string literals in-line within C code. If the language supported
(constExpr ? (void*)&staticCompoundLiteral1 : (void*)&staticCompoundLiteral2)
would only generate one of them, code could be written more cleanly using
prefixed strings than C strings.
There are a number of ways to include string literals in C code. *Good*
C programmers know how to use the language.
Post by s***@casperkitty.com
Post by Jerry Stuckle
And memcpy does not add the trailing null character.
It will copy any trailing null character which is present in the original if
the null byte is included in the size.
IFF you include the null character in the size. If you don't, you are SOL.
Post by s***@casperkitty.com
Post by Jerry Stuckle
We all know you don't like C. So why don't you find a language you do
like and stop wasting bandwidth bitching about C? No one here cares.
Low-level C is the best language for embedded systems. Today's compiler
writers, however, prefer to process a different language which is less
suitable for such purposes.
No, we all know you don't like C. So why don't you find a language you
do like and stop wasting bandwidth bitching about C? No one here cares.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
John Bode
2017-05-18 15:06:28 UTC
Reply
Permalink
Raw Message
Post by GOTHIER Nathan
On Thu, 18 May 2017 03:53:29 -0700 (PDT)
Post by Malcolm McLean
Templates are efficient.
The problem is that when a type is templated, you don't know what
symbols ans operations the type needs to support. This isn't such a
problem with STL - once you know you need a default constructor and a
copy constructor and a move constructor for heavyweight objects, you
know. But when non-standard library programmers create their own
generics, it becomes a big problem.
Templates are as efficient as a generic logic can be but a specifically
designed interface is way more efficient. It's like pretending a general
purpose circuit such as a microprocessor is the only way to process all
kind of data but why do so many people buy graphic cards?
You *can* provide specialized handling for specific types in a template
definition, so if you need to do something special for floating point
types vs. integral types, that's not a problem.
Post by GOTHIER Nathan
The only reason for the STL to be is to lower the bar for unskilled
programmers.
Or, maybe, it's to allow skilled programmers to focus on the actual problem
and not worry about the small stuff.

With the std::copy function in <algorithm>, I can:

- Copy the contents of one container to another;
- Write the contents of a container to an output stream;
- Read the contents of an input stream into a container;
- Write the contents of an input stream to an output stream;

without having to implement any kind of helper function (as with qsort)
or other specialized logic. That's a *huge* productivity win IMO.

Container types do their own memory management, meaning *I don't have to*.
That frees me up to worry about the actual *problem I'm trying to solve*.

C++ gives you options to do things the easy way or the hard way, depending
on your particular needs. C requires you to do everything the hard way.
That's not necessarily a win.
Post by GOTHIER Nathan
Post by Malcolm McLean
The malloc family of functions are special. A pure function may need to
call malloc and free. Any other subroutines can be supplied or folded
into the main function.
But really you want standard math functions and a few standard string
handling functions, the first because they are a pain to write, the
second because otherwise everyone has their own version of strcpy()
which accepts parameters in a different order or copies to and from
dynamic memory or takes a length parameter. Any of those things you can
build a case for, but it's best to stick to a standard.
I doubt that all C programmers need float, complex type or even string utilities.
You'd be hard-pressed to find a C programmer who *doesn't* need to do string
processing of some sort.
Post by GOTHIER Nathan
Once more, if it's difficult to write it doesn't mean it needs to be
standard but only you need a library to avoid the pain.
Do we need GTK+ to be included in the C standard? I don't think so.
Criteria for inclusion in the standard library:

- Abstract away system-specific behavior: I/O, memory management, file
management, date and time processing, signal handling, locale;
- Maximize portability by providing a standard interface for very common
operations: string and character processing, math operations;

Far, far, *far* more people do strcmp() on a daily basis than mess with
GUIs of any sort, much less a specific toolkit like GTK+.
John Bode
2017-05-18 16:17:00 UTC
Reply
Permalink
Raw Message
On Thursday, May 18, 2017 at 10:06:38 AM UTC-5, John Bode wrote:

[snip]
Post by John Bode
- Copy the contents of one container to another;
- Write the contents of a container to an output stream;
- Read the contents of an input stream into a container;
- Write the contents of an input stream to an output stream;
without having to implement any kind of helper function (as with qsort)
or other specialized logic. That's a *huge* productivity win IMO.
Actually, now that I think about it, that's not true - for anything
that isn't a primitive type, you *do* need to implement some additional
code. But my point still stands, I think. It's a major productivity win
over having to write multiple implementations of what is basically the same
operation.
fir
2017-05-17 21:34:08 UTC
Reply
Permalink
Raw Message
Post by Vassilis Spiliopoulos
Well I am a newbie yet I have not decided yet if I should start c or c++
Please tell me your ideas
learn slightly c++ to know what it is and never touch it again (like me)
Vassilis Spiliopoulos
2017-05-18 13:16:13 UTC
Reply
Permalink
Raw Message
Post by fir
Post by Vassilis Spiliopoulos
Well I am a newbie yet I have not decided yet if I should start c or c++
Please tell me your ideas
learn slightly c++ to know what it is and never touch it again (like me)
---
This email has been checked for viruses by AVG.
http://www.avg.com
I forgot to tell you what I want to do with C.I want to edit source
codes and contribute to dogecoin, bitcoin and linux as well as reverse
engineer some operating system kernels like windows ce and others.
So I have general purposes, I just want to be able to put an idea into
action.
Stefan Ram
2017-05-18 18:11:42 UTC
Reply
Permalink
Raw Message
Post by Vassilis Spiliopoulos
I forgot to tell you what I want to do with C.I want to edit source
codes and contribute to dogecoin, bitcoin and linux as well as reverse
Then learn the language that was used to program these systems.
For the Linux kernel, it's C and assembler.
Post by Vassilis Spiliopoulos
engineer some operating system kernels like windows ce and others.
To reverse engineer, just learn the language of the machine,
disassemble the kernel and then add comments to it,
explaining each part of the code. You do not actually need
to translate it back into a higher-level language. If you
want to do this, it might help to learn the language that
the kernel was written in (probably C, C++, and assembler).

To do this it helps to write programs in the higher-level
language and then disassemble them to learn how higher-level
constructs are compiled. Do this with several compilers and
levels of optimization.
Cholo Lennon
2017-05-18 13:26:27 UTC
Reply
Permalink
Raw Message
Post by Vassilis Spiliopoulos
Well I am a newbie yet I have not decided yet if I should start c or c++
Please tell me your ideas
Ask this question in comp.lang.c++ and you will get a totally different
set of answers (I prefer C++, but this not the place to say it)
--
Cholo Lennon
Bs.As.
ARG
John Bode
2017-05-18 14:36:19 UTC
Reply
Permalink
Raw Message
Post by Vassilis Spiliopoulos
Well I am a newbie yet I have not decided yet if I should start c or c++
Please tell me your ideas
---
This email has been checked for viruses by AVG.
http://www.avg.com
C is definitely the simpler language of the two, and by that metric easier
to learn. It doesn't give you much in the way of a toolkit, and the
abstractions it provides are fairly low-level (streams and pointers are
basically it).

C++ has more tools that will make you more productive early on, but some
concepts may not be immediately intuitive, and to use it effectively you
kind of have to learn a lot of different concepts up front (classes,
templates, and now lambdas).

I would not recommend either one for *learning how to program*. Neither
language was designed with teaching in mind, and some concepts in each
are *deeply* non-intuitive. Both language specifications are fairly loose
in places, allowing you to write code that will build and run, but its
behavior will not be predictable or repeatable.

I've started comparing learning how to program in C with learning how to
drive in a Lamborghini Countach. Fast, difficult to drive, and if you
let your attention wander for more than a few seconds you're spinning
into the ditch. It's not an appropriate car for student drivers, and C
is not an appropriate language to teach basic programming.
Stefan Ram
2017-05-18 17:46:26 UTC
Reply
Permalink
Raw Message
Post by John Bode
C is definitely the simpler language of the two, and by that metric easier
It might be easier to /learn/. But is it also easier to apply?

One example: Write a program, that reads in a line from the
console and then echoes the same line to the console again.

C++:

#include <iostream>
#include <ostream>
#include <string>

int main()
{ ::std::string line;
getline( ::std::cin, line );
::std::cout << line << '\n'; }

How can a beginner write something like this in C without
the risk of a buffer overflow or arbitrary limitations on
the length and without having to think about distracting
low-level details?

Another example: Read in lines until "-1" is entered and
then print them again, in shuffled order.

#include <algorithm>
#include <chrono>
#include <initializer_list>
#include <iostream>
#include <iterator>
#include <ostream>
#include <random>
#include <string>
#include <vector>

using namespace ::std::literals;

int main()
{ ::std::vector< ::std::string >lines;

auto readline =[ & ]()
{ ::std::string line;
getline( ::std::cin, line );
if( line == "-1"s )return false; else
{ lines.push_back( line ); return true; }};

while( readline( ));

{ auto const seed{ ::std::chrono::system_clock::now().
time_since_epoch().count() };
auto engine{ ::std::default_random_engine( seed )};
shuffle( begin( lines ), end( lines ), engine ); }

for( auto & line: lines )::std::cout << line << '\n'; }

All memory allocated in the above (outermost) block will be
properly freed at the end of the block, even in the case of
exceptions. In C++, that is. In C one can only pray that the
programmer gets the many mallocs (with checks) and frees
right.
Scott Lurndal
2017-05-18 18:23:53 UTC
Reply
Permalink
Raw Message
Post by Stefan Ram
Post by John Bode
C is definitely the simpler language of the two, and by that metric easier
It might be easier to /learn/. But is it also easier to apply?
One example: Write a program, that reads in a line from the
console and then echoes the same line to the console again.
#include <iostream>
#include <ostream>
#include <string>
int main()
{ ::std::string line;
getline( ::std::cin, line );
::std::cout << line << '\n'; }
How can a beginner write something like this in C without
the risk of a buffer overflow or arbitrary limitations on
the length and without having to think about distracting
low-level details?
I'd argue that a beginner _should_ be learning about
low-level details before ever learning C++.

#include <stdio.h>

int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer), stdin), stdout); }

For that matter, this code also compiles just fine as C++ code.
Gareth Owen
2017-05-18 20:51:12 UTC
Reply
Permalink
Raw Message
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer), stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Post by Scott Lurndal
For that matter, this code also compiles just fine as C++ code.
But doesn't run fine as either. I assume, you knew that.

So you've demonstrated how its marginally simpler to write incorrect
code in C than correct code in C++.

Erm ... well done?
Scott Lurndal
2017-05-19 12:38:04 UTC
Reply
Permalink
Raw Message
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer), stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
Post by Gareth Owen
Post by Scott Lurndal
For that matter, this code also compiles just fine as C++ code.
But doesn't run fine as either. I assume, you knew that.
Actually, it does compile and run using the C++ compiler.
s***@casperkitty.com
2017-05-19 14:44:49 UTC
Reply
Permalink
Raw Message
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer), stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
It doesn't truncate lines; it wraps them. Sometimes that's desirable, and
sometimes not. A function which behaved like fgets() but provided a choice
of behaviors (truncate, wrap, or trap/signal) would have been helpful, but
fgets is what it is.
Ben Bacarisse
2017-05-19 15:45:37 UTC
Reply
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer),
stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
It doesn't truncate lines; it wraps them. Sometimes that's desirable, and
sometimes not. A function which behaved like fgets() but provided a choice
of behaviors (truncate, wrap, or trap/signal) would have been helpful, but
fgets is what it is.
Yes, strange is what it is[1]. But it's possible to write a truncating
version that doesn't scan for the newline:

char *fgets_truncate(char *buf, int size, FILE *fp)
{
buf[size - 1] = !0; /* anything but 0 will do */
if (!fgets(buf, size, fp))
return NULL;
else if (buf[size - 1] == 0 && buf[size - 2] != '\n')
for (int c; (c = fgetc(fp)) != '\n' && c != EOF;);
return buf;
}

It's handy to know this trick, since I've see a lot of code that uses,
say, strchr(buf, '\n') after the call. (I've added some for-abuse for
good measure!)

--------
[1] It does not take a size_t size, and it usually returns something you
know (the buffer) rather than something you'd like to know (for example,
how many bytes were read).
--
Ben.
Tim Rentsch
2017-05-20 04:59:04 UTC
Reply
Permalink
Raw Message
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer),
stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
It doesn't truncate lines; it wraps them. Sometimes that's desirable, and
sometimes not. A function which behaved like fgets() but provided a choice
of behaviors (truncate, wrap, or trap/signal) would have been helpful, but
fgets is what it is.
Yes, strange is what it is[1]. But its possible to write a truncating
char *fgets_truncate(char *buf, int size, FILE *fp)
{
buf[size - 1] = !0; /* anything but 0 will do */
if (!fgets(buf, size, fp))
return NULL;
else if (buf[size - 1] == 0 && buf[size - 2] != '\n')
for (int c; (c = fgetc(fp)) != '\n' && c != EOF;);
return buf;
}
It's handy to know this trick, since I've see a lot of code that uses,
say, strchr(buf, '\n') after the call. (I've added some for-abuse for
good measure!)
Oh but you have a wonderful function to do the scanning for
you (no pun intended). Take out the for() and put in

fgets_truncate( (char[16]){0}, 16, fp );

leaving no need for 'int c;' or comparing c to EOF.

(All tongue firmly in cheek, in case that needs saying.)

Keith Thompson
2017-05-19 17:06:58 UTC
Reply
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer),
stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
It doesn't truncate lines; it wraps them. Sometimes that's desirable, and
sometimes not. A function which behaved like fgets() but provided a choice
of behaviors (truncate, wrap, or trap/signal) would have been helpful, but
fgets is what it is.
No, it doesn't wrap.

The program reads and prints a single line, discarding any remaining
input. If the line is longer than 512 characters, including the
trailing newline, it prints only the first 512 characters and discards
the rest. (Which means that the output might not contain a terminating
newline even if the input does.)

If the fputs(fgets(...)) call were in a loop, rather than being called
just once, it would copy the entire content of stdin to stdout.
Remember that fputs() doesn't add a newline.

The original problem statement was:

Write a program, that reads in a line from the console and then
echoes the same line to the console again.

The program assumes, perhaps incorrectly, that stdin and stdout
are associated with "the console".

A correct implementation of that requirement could read a character
at a time, stopping after printing a '\n' or reaching end-of-file.

If course if you need to do some additional processing on each line,
it gets a bit more complicated.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Ben Bacarisse
2017-05-19 17:18:55 UTC
Reply
Permalink
Raw Message
Post by Keith Thompson
Post by s***@casperkitty.com
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer),
stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
It doesn't truncate lines; it wraps them. Sometimes that's desirable, and
sometimes not. A function which behaved like fgets() but provided a choice
of behaviors (truncate, wrap, or trap/signal) would have been helpful, but
fgets is what it is.
No, it doesn't wrap.
The program reads and prints a single line, discarding any remaining
input. If the line is longer than 512 characters, including the
trailing newline, it prints only the first 512 characters and discards
the rest. (Which means that the output might not contain a terminating
newline even if the input does.)
I found this description a bit confusing so I'll offer a clarification.
Instead of "and discards the rest" I'd say "and leaves the rest to be
read by later input calls".

Discarded input sounds to me like input lost forever.

<snip>
--
Ben.
Keith Thompson
2017-05-19 18:59:24 UTC
Reply
Permalink
Raw Message
Post by Ben Bacarisse
Post by Keith Thompson
Post by s***@casperkitty.com
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer),
stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
It doesn't truncate lines; it wraps them. Sometimes that's desirable, and
sometimes not. A function which behaved like fgets() but provided a choice
of behaviors (truncate, wrap, or trap/signal) would have been helpful, but
fgets is what it is.
No, it doesn't wrap.
The program reads and prints a single line, discarding any remaining
input. If the line is longer than 512 characters, including the
trailing newline, it prints only the first 512 characters and discards
the rest. (Which means that the output might not contain a terminating
newline even if the input does.)
I found this description a bit confusing so I'll offer a clarification.
Instead of "and discards the rest" I'd say "and leaves the rest to be
read by later input calls".
Discarded input sounds to me like input lost forever.
Yes, the input is lost forever when the program (shown above in its
entirety but missing `#include <stdio.h>` terminates.

I suppose another program executed after this one could read the input,
but that's outside the scope of C.

I think people are assuming that the fputs(fgets(...)) line is meant to
be part of some larger program. I'm not making that assumption, and the
original problem description doesn't imply it.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Ben Bacarisse
2017-05-19 20:05:11 UTC
Reply
Permalink
Raw Message
Post by Keith Thompson
Post by Ben Bacarisse
Post by Keith Thompson
Post by s***@casperkitty.com
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer),
stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
It doesn't truncate lines; it wraps them. Sometimes that's desirable, and
sometimes not. A function which behaved like fgets() but provided a choice
of behaviors (truncate, wrap, or trap/signal) would have been helpful, but
fgets is what it is.
No, it doesn't wrap.
The program reads and prints a single line, discarding any remaining
input. If the line is longer than 512 characters, including the
trailing newline, it prints only the first 512 characters and discards
the rest. (Which means that the output might not contain a terminating
newline even if the input does.)
I found this description a bit confusing so I'll offer a clarification.
Instead of "and discards the rest" I'd say "and leaves the rest to be
read by later input calls".
Discarded input sounds to me like input lost forever.
Yes, the input is lost forever when the program (shown above in its
entirety but missing `#include <stdio.h>` terminates.
OK. But it still sounds too active for me. Something other than the
program probably discards the input. I prefer to think of it as ignored
by the program.

<snip>
--
Ben.
James R. Kuyper
2017-05-19 16:42:15 UTC
Reply
Permalink
Raw Message
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer), stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
The C++ code that it supposedly replaced had no such behavior.
Therefore, it fails to be a proper replacement for that code.
Richard Heathfield
2017-05-19 16:54:52 UTC
Reply
Permalink
Raw Message
Post by James R. Kuyper
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer), stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
The C++ code that it supposedly replaced had no such behavior.
Therefore, it fails to be a proper replacement for that code.
Agreed. In fact, I would be disappointed if a language that came /after/
C had no better way of gathering stdin data than C itself had. Thus, a
replacement in C is going to be a little more involved than a one-liner.

A few years ago, several clc subscribers posted their attempts at
reading an *entire* line from stdin (right up to the newline, regardless
of how long the line was). There was never any consensus about what
constituted the best interface, of course, but that's C programmers for you.

(Mine was the best. So there.)
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
Gareth Owen
2017-05-19 17:52:41 UTC
Reply
Permalink
Raw Message
Post by James R. Kuyper
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer), stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
The C++ code that it supposedly replaced had no such
behavior. Therefore, it fails to be a proper replacement for that
code.
Thank you James. I kept going back to see if I'd missed something.
Gareth Owen
2017-05-19 17:51:02 UTC
Reply
Permalink
Raw Message
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer), stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
If I want a program to duplicate the line, and sometimes it truncates it
then that program does not work correctly. For every programming
problem there is a solution that is short, elegant and wrong.
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
For that matter, this code also compiles just fine as C++ code.
But doesn't run fine as either. I assume, you knew that.
Actually, it does compile and run using the C++ compiler.
Except that sometimes it does not duplicate the output correctly.

The program has a bug in it - to whit whenever an input line is longer
than 512 bytes, the output is incorrect.
Scott Lurndal
2017-05-19 18:55:28 UTC
Reply
Permalink
Raw Message
Post by Gareth Owen
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer), stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
If I want a program to duplicate the line, and sometimes it truncates it
then that program does not work correctly. For every programming
problem there is a solution that is short, elegant and wrong.
The program solves the original assignment:

Write a program, that reads in a line from the console and then
echoes the same line to the console again.

There is nothing there about 'infinite line length' explictly, and
even the C++ version using getline() can't handle every possible input,
eventually the std::string will hit a memory limitation.

I would never write such code for production, but that wasn't the purpose here.
Gareth Owen
2017-05-19 18:58:08 UTC
Reply
Permalink
Raw Message
Post by Keith Thompson
Write a program, that reads in a line from the console and then
echoes the same line to the console again.
There is nothing there about 'infinite line length' explictly, and
even the C++ version using getline() can't handle every possible input,
eventually the std::string will hit a memory limitation.
Weak
Keith Thompson
2017-05-19 19:12:11 UTC
Reply
Permalink
Raw Message
Post by Keith Thompson
Post by Gareth Owen
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer),
stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
If I want a program to duplicate the line, and sometimes it truncates it
then that program does not work correctly. For every programming
problem there is a solution that is short, elegant and wrong.
Write a program, that reads in a line from the console and then
echoes the same line to the console again.
There is nothing there about 'infinite line length' explictly, and
even the C++ version using getline() can't handle every possible input,
eventually the std::string will hit a memory limitation.
It fails the original requirements if the line is longer than 512 bytes.
There could be perfectly valid reasons to have input lines longer than
that; perhaps the input was automatically generated, or perhaps your cat
sat on the keyboard. The C++ version is unlikely to fail for lines that
short.
Post by Keith Thompson
I would never write such code for production, but that wasn't the purpose here.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Keith Thompson
2017-05-19 19:01:28 UTC
Reply
Permalink
Raw Message
Post by Gareth Owen
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
int main() { char buffer[512]; fputs(fgets(buffer, sizeof(buffer), stdin), stdout); }
Great. Except it doesn't work if the input line is too big.
Sure it does. It just truncates it. And the programmer is, of
course, aware of that.
If I want a program to duplicate the line, and sometimes it truncates it
then that program does not work correctly. For every programming
problem there is a solution that is short, elegant and wrong.
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
For that matter, this code also compiles just fine as C++ code.
But doesn't run fine as either. I assume, you knew that.
Actually, it does compile and run using the C++ compiler.
Except that sometimes it does not duplicate the output correctly.
The program has a bug in it - to whit whenever an input line is longer
than 512 bytes, the output is incorrect.
One way to address that issue would be to modify the problem statement
so that the program's behavior is undefined if the input line (including
the trailing newline) is longer than 512 characters.

That might seem silly but there are times when it's not unreasonable to
document that a program is intended to work only with some restricted
input.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Ian Collins
2017-05-18 20:22:47 UTC
Reply
Permalink
Raw Message
Post by Stefan Ram
Post by John Bode
C is definitely the simpler language of the two, and by that metric easier
It might be easier to /learn/. But is it also easier to apply?
One example: Write a program, that reads in a line from the
console and then echoes the same line to the console again.
#include <iostream>
#include <ostream>
#include <string>
int main()
{ ::std::string line;
getline( ::std::cin, line );
::std::cout << line << '\n'; }
Beginners shouldn't be instructed to use all those superfluous colons,
they'll piss of their future colleagues.
--
Ian
Gareth Owen
2017-05-18 20:53:14 UTC
Reply
Permalink
Raw Message
Post by Ian Collins
Post by Stefan Ram
int main()
{ ::std::string line;
getline( ::std::cin, line );
::std::cout << line << '\n'; }
Beginners shouldn't be instructed to use all those superfluous colons,
they'll piss of their future colleagues.
Or the hideous brace style...

Its fine to *be* e.e.cummings, but don't teach "no capitals"
Scott Lurndal
2017-05-19 12:36:43 UTC
Reply
Permalink
Raw Message
Thunderbird/38.5.1
X-Received-Body-CRC: 3760745476
X-Received-Bytes: 1629
Post by Stefan Ram
Post by John Bode
C is definitely the simpler language of the two, and by that metric easier
It might be easier to /learn/. But is it also easier to apply?
One example: Write a program, that reads in a line from the
console and then echoes the same line to the console again.
#include <iostream>
#include <ostream>
#include <string>
int main()
{ ::std::string line;
getline( ::std::cin, line );
::std::cout << line << '\n'; }
Beginners shouldn't be instructed to use all those superfluous colons,
they'll piss of their future colleagues.
Only if they pass the interview screening, and the superfluous colons
would be a huge red negative checkmark around here.
Gareth Owen
2017-05-19 17:54:21 UTC
Reply
Permalink
Raw Message
Post by Scott Lurndal
Only if they pass the interview screening, and the superfluous colons
would be a huge red negative checkmark around here.
I think you'd get through the screening (all other things being
excellent) but you'd certainly get a "what's with all the ::'s?" as an
interview question.
Scott Lurndal
2017-05-19 18:58:05 UTC
Reply
Permalink
Raw Message
Post by Gareth Owen
Post by Scott Lurndal
Only if they pass the interview screening, and the superfluous colons
would be a huge red negative checkmark around here.
I think you'd get through the screening (all other things being
excellent) but you'd certainly get a "what's with all the ::'s?" as an
interview question.
I'm not so sure. We hire programmers here, and that would certainly
be a tickmark in the negative column. We don't look for people who
can leverage every feature of the language, but those who can solve
problems and maintain existing, sometimes decades old, code in
multiple languages (C, C++, Python, Perl, Verilog, SystemC are the
main languages).
Keith Thompson
2017-05-19 19:18:07 UTC
Reply
Permalink
Raw Message
Post by Scott Lurndal
Post by Gareth Owen
Post by Scott Lurndal
Only if they pass the interview screening, and the superfluous colons
would be a huge red negative checkmark around here.
I think you'd get through the screening (all other things being
excellent) but you'd certainly get a "what's with all the ::'s?" as an
interview question.
I'm not so sure. We hire programmers here, and that would certainly
be a tickmark in the negative column. We don't look for people who
can leverage every feature of the language, but those who can solve
problems and maintain existing, sometimes decades old, code in
multiple languages (C, C++, Python, Perl, Verilog, SystemC are the
main languages).
This is off-topic, since it's about C++, but I'll jump in anyway.

There is a valid reason for writing, for example, `::std::string`
rather than `std::string`. The identifier `std` is not reserved,
so it would be possible to define a local class or namespace named
`std` with a member named `string`. Then `std::string` would refer
to that member, not to the standard type declared in the <string>
header. `::std::string` is unambiguous and doesn't break anything.

It's a trick for avoiding a problem that's unlikely to occur in
practice, and that can be easily avoided by not redefining `std`.
It might partially guard against accidental inclusion of malicious
headers, but if that's a possibility you're probably screwed anyway.
It clutters the code and it's non-idiomatic. But it is defensible.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Loading...