Sunday, October 12, 2014

Digest for comp.lang.c++@googlegroups.com - 25 updates in 5 topics

comp.lang.c++@googlegroups.com Google Groups
Unsure why you received this message? You previously subscribed to digests from this group, but we haven't been sending them for a while. We fixed that, but if you don't want to get these messages, send an email to comp.lang.c+++unsubscribe@googlegroups.com.
Robert Hutchings <rm.hutchings@gmail.com>: Oct 12 01:13PM -0500

Some people strongly prefer Slackware....
arnuld <sunrise@invalid.address>: Oct 12 05:26PM

AIM: To understand why "arrays of int/float" and "arrays of char" behave
differently in C++
 
 
#include <iostream>
 
int main()
{
int arr1[] = {10,11,12};
char arr2[] = {'a','b','c'};
double arr3[] = {0,10, 0.11, 0.12};
const char* str = "comp.lang.c++";
const wchar_t* alpha = L"first line"
"Second Line";
 
std::cout << "arr1 = " << arr1 << std::endl;
std::cout << "arr2 = " << arr2 << std::endl;
std::cout << "arr3 = " << arr3 << std::endl;
std::cout << "str = " << str << std::endl;
std::wcout << "alpha = " << alpha << std::endl;
 
return 0;
}
========================= OUTPUT ================================
[arnuld@arch64 c++]$ g++ -ansi -pedantic -Wall -Wextra arrays.cpp
[arnuld@arch64 c++]$ ./a.out
arr1 = 0x7fffffffe960
arr2 = abc
arr3 = 0x7fffffffe930
str = comp.lang.c++
alpha = first lineSecond Line
[arnuld@arch64 c++]$
 
 
An array name is converted to pointer to its first element. arr1 and arr3
(1st and 3rd wariable) are arrays of int and float respectively and they
behave accordingly to this rule but arr2 and str (2nd and 4th variables)
do not. Why ?
 
alpha (5th variable) has its initialization spread across 2 lines. I
need to give L only on first line and not on 2nd line. Is this assumption
correct ?
 
 
 
 
--
arnuld
http://lispmachine.wordpress.com/
Victor Bazarov <v.bazarov@comcast.invalid>: Oct 12 01:37PM -0400

On 10/12/2014 1:26 PM, arnuld wrote:
> (1st and 3rd wariable) are arrays of int and float respectively and they
> behave accordingly to this rule but arr2 and str (2nd and 4th variables)
> do not. Why ?
 
When you ask "why", you presume that your conclusion is correct. It
isn't. All arrays behave according to the rule.
 
> alpha (5th variable) has its initialization spread across 2 lines. I
> need to give L only on first line and not on 2nd line. Is this assumption
> correct ?
 
Yes. Concatenation of the adjacent string literals is done prior to the
syntactic analysis of the code.
 
V
--
I do not respond to top-posted replies, please don't ask
Barry Schwarz <schwarzb@dqel.com>: Oct 12 10:45AM -0700

>(1st and 3rd wariable) are arrays of int and float respectively and they
>behave accordingly to this rule but arr2 and str (2nd and 4th variables)
>do not. Why ?
 
Actually they do. The difference is how the compiler generates code
for the overloaded operator <<. When the right operand has type
pointer to char, the generated code treats the address as the start of
a C style string (similar to using %s in printf). When the operand
has type pointer to "object that cannot be a string," the generated
code treats it the same as using %p in printf.
 
 
>alpha (5th variable) has its initialization spread across 2 lines. I
>need to give L only on first line and not on 2nd line. Is this assumption
>correct ?
 
Yes. It only looks like the initialization is spread across two
lines. Two string literals separated only by white space are merged
into a single string literal in one of the early compilation phases.
Since '\n' and ' ' are both white space characters, your
initialization of alpha is processed as
L"first lineSecond Line"
 
--
Remove del for email
Wouter van Ooijen <wouter@voti.nl>: Oct 12 08:11PM +0200

arnuld schreef op 12-Oct-14 7:26 PM:
> "Second Line";
 
> std::cout << "arr1 = " << arr1 << std::endl;
> std::cout << "arr2 = " << arr2 << std::endl;
 
Note that you are doing something dangerous here: you ask a string
(const char pointer) to be printed that is not 0-terminated.
 
Wouter
Bo Persson <bop@gmb.dk>: Oct 12 11:34AM +0200

On 2014-10-12 00:48, JiiPee wrote:
 
> str.size();
 
> so they have to understand that str is an object and it can call its
> member functions, but yes its not too much OO there.
 
There is no OO going on here, just some "C with classes". No new or
delete, no inheritance, no virtual functions. It just works.
 
Telling a new student that std::string holds a string, and that you can
get its size by calling str.size(), will surprise nobody.
 
Compare that to the "easy to understand" C string functions, and try to
explain the incantation
 
char* b = malloc(strlen(a) + 1);
 
 
Bo Persson
Emanuel Berg <embe8573@student.uu.se>: Oct 12 04:41PM +0200


> Why? You can easily learn italian without knowing
> latin first. It's the same way with programming
> languages.
 
In general: yes, but in the case of C++ and C it is
impossible from a practical perspective to learn C++
without learning C as well as C is a huge subset of
C++. (At least formally so, in reality it is probably
more correct to say that C++ is an extention of C.)
 
--
underground experts united
Robert Hutchings <rm.hutchings@gmail.com>: Oct 12 09:46AM -0500

On 10/12/2014 9:41 AM, Emanuel Berg wrote:
> without learning C as well as C is a huge subset of
> C++. (At least formally so, in reality it is probably
> more correct to say that C++ is an extention of C.)
 
I am following this discussion with keen interest. So, if one reads
"Accelerated C++" by Koenig and Moo, they are learning C++ right from
the start. Are we saying that this is the *wrong* way to learn C++?
Emanuel Berg <embe8573@student.uu.se>: Oct 12 04:47PM +0200

> classes, and different I/O.
 
> That's totally different from the way you write C
> code.
 
Yes, I mean: if the C program was good you don't need
the C++ stuff to begin with. But if you want to you
can compile it with g++ instead of gcc and you got a
C++ program that does the same thing, probably just as
good. (But again, why do that?)
 
You often C the combination C/C++ in literature, ads,
and so on. Well, there *is* a "C/C++" and that is C++.
Other than that C and C++ are two different languages
with different syntax, tools, and (as you mention)
libraries. Tho the biggest difference by far is the
C++ focus on OO.
 
--
underground experts united
Emanuel Berg <embe8573@student.uu.se>: Oct 12 04:56PM +0200


> yes. On videos the top C++ people they always say
> the code should be as short as possible and simple.
> Using C++ and classes does that.
 
OO and programming with classes does not make the code
"shorter".
 
OO makes programs "simpler" only when the purpose of
the program lend itself naturally to modelling: like
simulation, games, certain abstract situations with
clear building blocks (e.g., a hierarchical
scheduler), and so on. OO is not "always better".
 
Also: Short code is not always an advantage. Most
often it is because it is fast to read and write. But
sometimes short code gets really cryptical and
difficult to maintain. Short code doesn't imply
execution speed. It can actually be the other way
around as there isn't any optimization of obscure
hacks.
 
> For example for-loop becomes very short some
> times... with C you cannot do such things.
 
Yes you can: for-loop is the same in C and C++ and
several other languages as well.
 
--
underground experts united
Bo Persson <bop@gmb.dk>: Oct 12 05:31PM +0200

On 2014-10-12 16:56, Emanuel Berg wrote:
> execution speed. It can actually be the other way
> around as there isn't any optimization of obscure
> hacks.
 
So lets's compare. :-)
 
std::string a = "Sample string";
std::string b = a;
 
or
 
char a[] = "Sample string";
char* b = malloc(strlen(a) + 1);
strcpy(b, a);
/* and sometimes later: */
free(b);
 
 
>> times... with C you cannot do such things.
 
> Yes you can: for-loop is the same in C and C++ and
> several other languages as well.
 
Newer C++ has better for loops as well, like:
 
for (auto x : v)
std::cout << x;
 
will output all elements in the sequence v, like a vector, or a string
or an array, or ...
 
 
Bo Persson
Jorgen Grahn <grahn+nntp@snipabacken.se>: Oct 12 04:06PM

On Sun, 2014-10-12, Emanuel Berg wrote:
> impossible from a practical perspective to learn C++
> without learning C as well as C is a huge subset of
> C++.
 
It is, but a lot of that subset is of no use in normal C++
programming. (Perhaps more the idioms than the concrete language
constructs: you will use most C language constructs in your C++
programs over the years, but not in the way a C programmer would.)
 
So, a lot like latin and italian.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
JiiPee <no@notvalid.com>: Oct 12 05:22PM +0100

On 12/10/2014 15:56, Emanuel Berg wrote:
> execution speed. It can actually be the other way
> around as there isn't any optimization of obscure
> hacks.
 
many times there is no difference in assembly code though. For example
c-loop:
 
int i;
for(i=0; i<size; ++i)
 
can be done in C++:
for(auto i : vec)
 
clearly c++ version is shorter and more elegant here. Its also easier to
see what happens in the looop. So its better readable. plus the assembly
code is the same in both, so they are equally fast
 
Or would you say the C code here is better? In what way?
 
>> times... with C you cannot do such things.
> Yes you can: for-loop is the same in C and C++ and
> several other languages as well.
 
you can do:
 
for(auto i : vec)
 
in C (and lets imagine that the vector item type is very long, thus auto
makes the type short)?
 
Jorgen Grahn <grahn+nntp@snipabacken.se>: Oct 12 04:27PM

On Sat, 2014-10-11, Emanuel Berg wrote:
>> learn C before learning C++". Stroustrup said
>> definite "no".
 
> Maybe he said that as a way of promoting C++ and OO?
 
The context is that someone wants to learn C++ -- surely no promotion
is needed?
 
I think the real background to that response is too many people have
come to C++ over the years with a C background and written terrible
code, making C++ (not C) look bad.
 
> No harm can come from knowing C, on the contrary.
 
> Only if you want to specifically do C++ and OO, of
> course you shouldn't do C.
 
That's the second time in three paragraphs you mention object
orientation -- why? It was popular in the 1990s, but today noone
forces you to do it, not in C++ at least. Personally I live happily
without it[1].
 
[snip practical tips which I agree with]
 
> have to be that "careful". A good C program is often a
> good C++ program with minimal or zero modifications
> (tho why do that if it is already good?).
 
Strongly disagree. Good C++ programs use RAII, type safety,
exceptions and the standard library: good C programs have to make do
with arrays or home-grown linked lists, and manual memory management.
 
/Jorgen
 
[1] I find abstract datatypes useful in every program, but rarely see
a need for run-time polymorphism, abstract interfaces, design
patterns and so on. YMMV.
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
JiiPee <no@notvalid.com>: Oct 12 05:30PM +0100

On 12/10/2014 16:31, Bo Persson wrote:
> strcpy(b, a);
> /* and sometimes later: */
> free(b);
 
yes, this would be pain for me... "lazy" programmer as I am. I really
don't like to remember doing free() at the end. I want it to be
automatic. Although maybe C-people can show how to aumatizice this?? I
guess C programmers use some helper function to do these? Doing like
that would be pain for me at least... I do not like to write code if not
necessary.
 
> std::cout << x;
 
> will output all elements in the sequence v, like a vector, or a string
> or an array, or ...
 
Yeps. This is a really good feature imo after learning to use it. It
takes some time to get used to this new syntax, but after familiar with
it, its very good and natural and no going back.
Paavo Helde <myfirstname@osa.pri.ee>: Oct 12 11:41AM -0500

Emanuel Berg <embe8573@student.uu.se> wrote in
> impossible from a practical perspective to learn C++
> without learning C as well as C is a huge subset of
> C++.
 
But it is not a proper subset, and neither is it "huge". There are lots
of things in C which cannot be used or are not needed in C++ (from the
top of my head: calling undeclared functions (default types!), _Bool,
restrict, C-style casts, longjmp(), strcat() et al, malloc() et al, qsort
(), printf() et al, tables of function pointers, naming conventions (like
encoding library name or parameter types in the function name), static
free functions, most of preprocessor, most of pointer arithmetics and
sizeof, array syntax (esp tricky when passing to/from functions), error
reporting by error codes, etc., tedious cleanup in error paths, etc.).
The 'const' behavior is slightly different so some relearning is needed
if the C const is learned too well. The idiomatic use of for() loops in
C++ has variable declarations inside for(), which is not valid C syntax,
and if()/while() also support similar syntax in C++, so one would need to
learn the usage of basic looping constructs twice, first with unneeded
restrictions. Placement of variable declarations inside function also has
unnessecary and harmful restrictions in C, so learning the C way first is
actually harmful when learning C++.
 
To be honest, what's left in common is quite a small subset, basically
built-in datatypes and conversions plus general syntax of declaring and
defining functions. Yes, you will need these basics to learn C++, but
they do not constitute a large part of either C or C++.
 
Cheers
Paavo
Richard Damon <Richard@Damon-Family.org>: Oct 12 12:46PM -0400

On 10/12/14, 10:41 AM, Emanuel Berg wrote:
> without learning C as well as C is a huge subset of
> C++. (At least formally so, in reality it is probably
> more correct to say that C++ is an extention of C.)
 
In learning C++, you will learn much of the syntax of C (at least C90),
but you might not know which parts of the syntax you learned are C and
which parts are C++ only.
 
What you are less apt to learn is the library. While basically all of
the C library is available in C++, these well might not be covered in a
basic course.
Emanuel Berg <embe8573@student.uu.se>: Oct 12 07:48PM +0200

> functions, pure virtual functions, overriding
> functions, stuff I forgot, and stuff I don't even
> know about,
 
A lot of the stuff you mention (e.g, inheritance,
overloading) I include when I say OO.
 
C also has a library: the standard C library :)
 
> You need another 800 page book to tell you how to
> use the STL library. GUI and the web is extra.
 
> K&R's book on C has only has 272 pages *total*.
 
I don't think counting the pages of books as a method
has any value to examine complexity but there is no
doubt in my mind that C++ is more difficult to master
- it has many more concepts than C and those are not
always implemented the way you would first think.
 
> marginal value. C++ is "right up there" in terms of
> difficult programming languages. Think of learning
> Spanish vs. Mandarin.
 
Natural languages and not a good metaphor for
programming languages. If you sucked at Spanish at
school you might still be a great programmer. C++ is
not as straightforward as C but it is very possible to
do with time and effort, besides you don't need to use
all that fancy OO stuff if you don't want to.
Inheritance is a good example that is a big part of OO
(at least if you read books about it) but i real
programs usually it just makes things complicated and
difficult to overview. C++ isn't as simple and clean
as C but that doesn't matter you can't use C++, can't
use OO in a clean and simple way.
 
--
underground experts united
Wouter van Ooijen <wouter@voti.nl>: Oct 12 09:42AM +0200

Richard Damon schreef op 11-Oct-14 11:40 PM:
> specific things to specific signals under specific signals, and don't
> have many cases of writing a program to toggle an arbitrary signal under
> some condition.
 
Indeed. If you never need to do something with 'abstract' pins the C
approach is sufficient.
 
I want for instance be able to write a bit-banged I2C master, that uses
an abstract pin. In actual use that pin can be a regular input-output
pin, or an open-collector pin. The regular input-output pin needs to be
handled a bit different (low => output and low, high => input). The I2C
code does not concern itself with such details, but the resulting
machine code is as efficient as if it fully knew.
 
Or maybe I was in a funny mood, and the I2C pins were pins on an
MCP23017 I/0 extender chip.
 
But I do agree, if you can write your code directly for the I/O pins
that you use there is no advantage in the abstraction I describe.
 
Wouter
Richard Damon <Richard@Damon-Family.org>: Oct 12 08:40AM -0400

On 10/12/14, 3:42 AM, Wouter van Ooijen wrote:
 
> But I do agree, if you can write your code directly for the I/O pins
> that you use there is no advantage in the abstraction I describe.
 
> Wouter
 
Actually, I find the insufficient as the piece of code to manipulate the
pin then needs to change based on the pin type. With my method, there is
a single line of code, in a header that is visible to the code that
automatically reconfigures the code that is providing the "higher level"
driver.
 
In my method, the I2C Master interface that you describe would get its
pin definitions from an configuration include file, as opposed to having
some setup call build a pointer for them. This does say I need to
duplicate the code if I want to build two bit banged I2C ports in a
given application, or accept the added inefficiency of the virtual calls
(but for bit banged I2C, is it really significant?)
Wouter van Ooijen <wouter@voti.nl>: Oct 12 04:52PM +0200

Richard Damon schreef op 12-Oct-14 2:40 PM:
 
>> Wouter
 
> Actually, I find the insufficient as the piece of code to manipulate the
> pin then needs to change based on the pin type.
 
Yes and no: The i2c lib must of course state that it wants an
open-collector pin. But the actual 'conversions' of input-output and
open-collector to open-collector are written once, and are also used by
other protocols that need an open-collector pin, for instance the dallas
1-wire interface. All in the name of 'write it once' or 'don't repeat
yourself.
 
The relevant part of the i2c interface:
 
template<
class arg_scl,
class arg_sda
 
class i2c_bus_master_bb_scl_sda {
 
// use the pins in an appropriate way
// (and assert that they can be used as such)
typedef pin_oc_from< arg_scl > scl;
typedef pin_oc_from< arg_sda > sda;
 
...
};
 
All code in the class template uses the scl and sda, not the arg_scl and
arg_sda.
 
The pin_oc_from class template is specialized for the 3 cases:
input-output pin, open-collector pin, and the default that generates an
appropriate compiler error message. The actual code:
 
// fallback: compile-time error
template<
class unsupported,
class dummy = void
> struct pin_oc_from {
static_assert(
sizeof( unsupported ) == 0,
"pin_oc_from<> requires "
"a pin_oc, or pin_in_out"
);
};
 
// from itself: delegate
template< class pin >
struct pin_oc_from <
pin,
typename pin::has_pin_oc
> :
public pin_oc_archetype
{
static void init(){ pin::init(); }
static bool get(){ return pin::get(); }
static void set( bool x ){ pin::set( x ); }
};
 
// from a pin_in_out
template< class pin >
struct pin_oc_from <
pin,
typename pin::has_pin_in_out
> :
public pin_oc_archetype
{
 
static void init(){
pin::init();
}
 
static void set( bool x ){
 
// to make a pin_in_out behave like a pin_oc
if( x ){

// make it float when it is set high
pin::direction_set_input();

} else {

// make it output and low when it is set low
pin::direction_set_output();
pin::set( 0 );
}
}
 
static bool get(){
return pin::get();
}
 
};
 
> duplicate the code if I want to build two bit banged I2C ports in a
> given application, or accept the added inefficiency of the virtual calls
> (but for bit banged I2C, is it really significant?)
 
Maybe not for I2C, but you give up that possibility for IMO no gain. And
for (for instance) dallas 1-wire or SPI I can very well imagine more
than one bus of a certain type per system.
 
What you essentially do is compile-time polymorphism by modifying the
source file to include the right 'input' source file. One thing that I
certainly don't like about that is that it requires you to copy the
library file (bb i2c interface) to your project and modify it. (Or some
other scheme, where #include something that is essentially a source
file, not a header). There are other points, for instance that the
interface between the points and the i2c part is essentially by global
functions.
 
Note that my scheme is not limited to GPIO's. There are many other
abstractions that can be encapsulated similarly in static class templates.
 
Wouter
Paavo Helde <myfirstname@osa.pri.ee>: Oct 12 01:44AM -0500


> Was thinking if there are any reasons. There is one reason: Was it
> Sutter who said that class should have as less funtions as possible. So
> doing this globally would reduce the number of functions in classes.
 
I agree that class public interface should be as minimal as possible - but
not smaller! This example of unscalable mess with typeid checking is
exactly the reason why virtual functions were invented in the first place.
 
Cheers
Paavo
Paavo Helde <myfirstname@osa.pri.ee>: Oct 12 02:57AM -0500

Urs Thuermann <urs@isnogud.escape.de> wrote in
> B *b1 = new auto(*b);
> }
 
> Is this the correct and preferred way in C++11?
 
To work as expected, one needs to have dynamic type lookup at runtime
here, but 'auto' is a compile-time concept, so I don't think it helps
here.
 
Moreover, it should know all possible run-time types of B-derived classes
at compile time, but this is in principle impossible (as one can add new
dynamic libraries with new classes at runtime).
 
 
 
> and then call b->clone() instead of the new operator.
 
> Is there a way to do this in C++98 without the need to add a new
> function like clone() in each derived class?
 
Yes, that's the way to do it. 1 extra line per class is not so much.
 
Cheers
Paavo
JiiPee <no@notvalid.com>: Oct 12 10:04AM +0100

On 12/10/2014 07:44, Paavo Helde wrote:
> exactly the reason why virtual functions were invented in the first place.
 
> Cheers
> Paavo
 
but if for example std::string public interface had a function called:
B* clone();
which nobody really uses other than some code internally, then isn't it
bad from the users point of view seeing this kind of clone function
which they never need?
 
But surely there is a way to hide the clone, like being protected, then
this would not be a problem.
JiiPee <no@notvalid.com>: Oct 12 10:06AM +0100

On 12/10/2014 07:44, Paavo Helde wrote:
> exactly the reason why virtual functions were invented in the first place.
 
> Cheers
> Paavo
 
I would not like to see B* clone() being a public member of a
std::string class. But if its a private member then it would be ok. The
functions calling it can be friends so they can get access to private
clone().
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: