N
Nick Keighley
Ever heared of printf?
yes, why? Does it use VLAs?
Ever heared of printf?
C isn't subset of C++.
C++ isn't superset of C.
They are different.
C++ is a new language.
Now I somewhat agree with a similar opinion thrown long time ago:
C++ has no relationship with C except its name stolen from C
lovecreatesbeauty said:C isn't subset of C++.
C++ isn't superset of C.
They are different.
C++ is a new language.
Now I somewhat agree with a similar opinion thrown long time ago:
C++ has no relationship with C except its name stolen from C
Now I somewhat agree with a similar opinion thrown long time ago:
C++ has no relationship with C except its name stolen from C
I understand this (and in fact knew it was the case). But that doesn't
stop it being silly!
The C committee should learn - as the C++ committee apparently knows -
that backwards compatibility is only "important", not "critical". It is
/okay/ to introduce a new "static_assert" keyword in the new version of
a language, as long as people can continue to use their compilers with
older standards. This is not a new idea - consider K&R style function
declarations, for example.
Failing that, what is to stop the C++ people following the C people here?
Anyway, this is just one example that is easy to see, where the two
committees added the same feature to the two languages but with
differing details.
The more annoying issue, as I see it, is the increasing gap of C
features that are missing in C++. There are steadily more features
being added to C for embedded use, such as fixed point formats. But C++
doesn't get that sort of thing, because it could all be implemented in a
class. I understand the principle that you should not add something to
the core library if it can be done just as well in a class - but the C++
committee doesn't seem to realise that compatibility with C is important
here.
If someone is making a wish list here, I'd add support for defining
endianness (allowing code to explicitly define and use variables and
types as big endian or little endian independently of the architecture)
and bit field ordering.
That would be great for portable code.
Support for types bigger than "char" which are "can always alias" would
be a big help whenever you need to move data around, and an 8-bit type
that does not alias would be nice for small systems.
Proper, standardised memory barriers of different types and granularity
would be a help for some low-level programming.
Generally speaking, it would be nice to be able to do more C++ in
low-level and embedded code, and cut out some more of the last remnants
of assembly that is still needed.
Le 26/08/12 11:57, Ansel a écrit :[...]Isn't it a lame use of human time and effort to maintain completely
separate
C and C++ standards? As in the words of Betty White about Facebook: "It
sizeof('b') is sizeof(int) int C, 1 in C++
Which one would you compromise on?
You do not know what you are talking about dude...
Simple. Require sizeof(int)==1. Problem solved.
Jens Gustedt said:on my wish list would be
- variably modified types (not necessarily VLA but pointers to VLA are
nice)
What good are pointers to VLAs without VLAs? What would they point
to???
What good are pointers to VLAs without VLAs? What would they point
to???
IMHO:
C++ could adopt C99 or C11 as its C subset (and make "void *" support
implicit conversion to other pointer types, formally allow "#include
<stdio.h>" and friends, adopt the "((void *)0)" definition of NULL, ...);
C++ _does_ formally allow "include <stdio.h>". <XXX.h> defines the same
set of entities as <cXXX>, except that <cXXX> provides them in namespace
std (and optionally the global namespace), whereas <XXX.h> provides them
in the global namespace (and optionally in namespace std). See 17.6.1.2
and Appendix D.5 in C++11.
Definition of NULL as ((void*)0) is contingent on the implicit
conversion of void* to other pointer types.
That implicit conversion from void* to any pointer type is a dangerous
hole in the type system. I admit I'm not much of a C programmer anymore:
the only valid reason I can think of to have this conversion is so that
malloc calls don't require you to specify the type _three_ times (e.g.,
int* p = (int*)malloc(sizeof(*p)); ).
If I really wanted to pitch the committees for stronger ties between C
and C++, I'd probably suggest that (a) C pick up nullptr (and nullptr_t)
to serve as generic null pointer constant,
(b) C drop the implicit
conversion from void*,
and (c) both languages use a new distinct type
that can implicitly convert to any pointer type.
Holes in the type
system are very useful at the fringes of C/C++ programs, I think that
having distinct "source" (X -> any*) and "sink" (any* -> X) pointer
types preserves the utility of C-style void* while minimizing the danger.
I suppose you could permit VLAs with allocated storage duration
but not with automatic storage duration. (They're already not
permitted to have static storage duration.) That would remove the
case where you can define a VLA, but there's no way to handle an
allocation failure. It would also remove the case where they're
most convenient.
we call this 'void *', where this is nearly the only thing that can
really be done with this type anyways ("void" variables are otherwise
pretty much useless, ...).
Basically, I just want to be able to mix and match C and C++ code
freely. I want to be able to write in the same style in each language.
If I am not using C++ features, I want the code to be compilable as C
or C++, with the same functionality each time. And I want to be able to
do so without artificially restricting the features I can use in C. It's
okay if I have to #include a few standard headers, and put in a few
extern "C" wrappers.
Am I really asking too much?
(Here's another thing C should support - it should accept extern "C".)
void * just documents that "this is an unsigned char * holding arbitraryAm 28.08.2012 05:34, schrieb BGB:
That said, I don't really see the point of "void*" as it is in C++
nowadays. Since you'd have to do an explicit conversion any time you
use it, in C++ it has nothing that couldn't be done with a "unsigned
char*". In the contrary, "unsigned char*" allows byte based pointer
arithmetic and to inspect the contents on a byte base.
No, it is not defined nearly well enough.
There are ambiguities regarding padding, alignment, etc., especially as
the size of the fields change. Different underlying types of the fields
can make a difference (especially if you want something like an enum
type),
No, these types are fine (I use them all the time). The issue is with
aliasing.
Sometimes in programming, you need to move data around in a format other
than the data's "natural" format. Maybe you've got data held in a
struct, and you want to make a copy of the whole struct. Or maybe you
want to pass data around using the Modbus protocol, which likes to treat
everything using 16-bit words. The trouble comes when you want to work
with a pointer to the struct data using a *uint16_t pointer (or any
other "incompatible" pointer). The compiler knows that the struct is
incompatible with a uint16_t, so the pointer cannot point to the struct,
and therefore nothing read or written to the struct can affect anything
read or written through the pointer.
Chars, or pointers to char, have the opposite problem - because they can
alias anything, the compiler has to assume that any access through a
char pointer can hit any other data (well, not /any/ other data - local
data in registers is safe). This can lead to lost optimisation
opportunities.
So I would like to see types other than inefficient 8-bit types that
have the "alias everything" property, and 8-bit types that don't alias
anything.
An alternative is to be able to specify aliasing more conveniently,
without having to use type-punning unions.
Well, atomics helps a bit - but they are overkill. Mostly all you need
is to be able to say "make sure the store to variable X is completed
here", or "don't move the read before this point". You can get a fair
amount of this using volatile accesses, but sometimes it is much more
convenient with general barriers. Depending on the target cpu, you may
also want the barriers to issue additional instructions to flush buffers.
Basically, I just want to be able to mix and match C and C++ code
freely. I want to be able to write in the same style in each language.
If I am not using C++ features, I want the code to be compilable as C
or C++, with the same functionality each time. And I want to be able to
do so without artificially restricting the features I can use in C.
It's okay if I have to #include a few standard headers, and put in a few
extern "C" wrappers.
Am I really asking too much?
That's true - but I want to be able to unambiguously place fields across
boundaries, and I want to be able to use fields of different types in a
well-defined, portable and cross-platform way. For example, I want to
be able to write:
struct {
uint8_t a;
uint8_t b;
uint8_t c : 4;
uint8_t d : 4;
uint8_t e;
}
I want to be guaranteed that this struct takes 32 bits, and is aligned
to 8-bit boundaries.
The atomic_thread_fence may be an answer here. I'll need to wait a bit
for support to make it into the tools I use, and then see what the code
is actually generated for it (and for the atomic types). But it is
always possible that I'll be able to strike this one from my wishlist.
mvh.,
Ultimately, I'd like some way to tell the compiler what data, pointers
and/or types can alias what.
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.