- rational numbers - 5 Updates
- Memory allocator - 2 Updates
| David Brown <david.brown@hesbynett.no>: Sep 23 09:52PM +0200 On 23/09/2021 18:42, Manfred wrote: > My point is about having it in the language as in the "language > specification", which includes the standard library, a broader sense > than yours. Yes, I can see that. That is why I made the distinction of the /core/ language. That includes statements, expressions, operators, types, etc. It can also language support libraries that come with compilers - for more limited processors, things like floating point might be in a software library. (These are for function calls generated by the compiler, rather than written in the source code.) And some headers would be included as they are required for the language - for example, the language "sizeof" operator evaluates to an expression of type "size_t" defined in <stddef.h>. (One could reasonably argue that it would be better to talk about "freestanding C and C++ environments, rather than "core language" - at least these terms are well defined in the standards.) > wrote afterwards) is not strictly needed from the language as long as it > offers the means, if you need it, to build or integrate alternatives > according to your needs. Yes, indeed. When you have such flexible and general purpose languages as C and C++, then any given solution to printing will be far too big and complicated for some use-cases, and far too small and limited for others. The language has to provide the tools you need to make the solutions you need. And then the standard library can provide one or more printing and formatting systems that suit a wide range of programs, so that you only need to re-invent the wheel when you really need a new one. |
| Ian Collins <ian-news@hotmail.com>: Sep 24 08:48AM +1200 On 24/09/2021 02:02, Bart wrote: > next i > It works better than the C++! And better than C's scanf which everyone > tries to avoid using. How is that fundamentally different from for( int i = 0; i < 3; ++i ) { std::cout << "Prompt> "; std::cin >> a >> b >> c; std::cout << a << ' ' << b << ' ' << c << '\n'; } ? -- Ian. |
| Paavo Helde <myfirstname@osa.pri.ee>: Sep 24 12:51AM +0300 23.09.2021 11:28 Juha Nieminen kirjutas: >> parameters to tostring() functions, with streams it becomes complicated >> and hidden. > So, what's *your* suggested alternative? Suggested alternative for what? Formatting or streaming? The solutions like printf() and iostreams mix these two up and attempt to solve them both in one go, and do not really succeed in either, IMO. Or do you mean an alternative easy syntax for debug printouts? That's a totally another topic (which I'm not very interested in). > (One could suggest std::format(), but AFAIK that's not going to be enormously > more efficient either. It's more of a convenience thing than an efficiency > thing.) The best performance is delivered by formatting the data into raw memory. That's what std::to_chars() and Boost's double-conversion are doing. To avoid memory and latency overheads, this raw memory should be periodically flushed out to the final destination. For example, if the output is sent out over network, ideally each TCP frame should be sent out as soon as it is ready. If it is written in a disk file, the content should be flushed before the computer free memory is exhausted, etc. The idea with iostreams is that the data is flushed by each primitive value written. This can become a bottleneck because iostreams are keen on doing formatting in addition to streaming and are thus choked full of virtual functions and multithread-hostile locale dependencies. My solution would be to cleanly separate the formatting and the streaming parts. The class would format its content to a raw memory buffer as needed, and the streaming part would flush the buffer to the destination as often as needed. One thing with today's many-gigabyte machines is that in most cases this need to flush never appears, the whole data structure can be easily formatted into raw memory fully before sending it to anywhere. BTW, one does not need to use a fixed-size buffer, for example std::string::append() is perfectly capable of growing the buffer with amortized constant complexity. Some motivations for formatting the whole file in memory first: when sending data over network one often wants to send Content-Length first which might not be known before formatting the whole packet. When storing the data in a local file it often does not really matter if the file sits in RAM in a userland buffer or in the kernel disk cache. Thus we arrive to the dreaded "tostring" solution (advocated by Bart for example). The whole data structure is first formatted into a std::string or equiv, then streamed out to std::cout or wherever. Understandably, this solution does not fit 8-bit controllers and like, but neither do iostreams! At least the "tostring" solution cleanly separates the formatting and streaming parts, and allows for easy way to pass formatting parameters to the formatting part. Tell me again how do I instruct my class operator<< to place "</td><td>" between each output number when formatting HTML output? > to dynamically construct a string to be printed, and instead the > type should get an std::ostream (or FILE*, or whatever) that it > can use to directly write whatever it wants there. Why? Is this just because of memory overhead concerns? |
| Bart <bc@freeuk.com>: Sep 23 11:05PM +0100 On 23/09/2021 21:48, Ian Collins wrote: > std::cout << a << ' ' << b << ' ' << c << '\n'; > } > ? Haven't you followed the thread? A lot of things have been pointed out. But here's a summary of issues with the C++ loop: * It's not line-oriented; the new lines get out of sync with the data being read * If fewer than 3 items are present on a line, then it apparently hangs, with no explanation, waiting for them on the next line * If more than 3 items are present on a line, then those aren't discarded, but are confusingly used as input for a, b, c for the next line. So if 400 and 500 are extra items, and the user enters 10 20 30 on the next line, if will read '400 500 10', with 20 and 30 rolled over to the subsequent line * If more than 3 extra items are present, then on the next iteration, it doesn't wait for user input at all. If will not do so until everything on that initial line is consumed * Numeric separators within numbers such as "_" and "'" are not recognised, and cause an error * Numbers which are quoted are not recognised, and cause an error * Separators between numbers other than white space are not recognised, such as commas, and cause an error * Floating point numbers (using "." and/or "e") are not recognised; those characters cause an error * When an out-of-range number is entered, it reads i32.max (etc) for that number, but also generates an error * I mentioned error a few times, when that happens, it goes crazy. I think the internal pointer is not stepped past it, and it just reads zeros, so it never consumes the rest of the line. So in a loop, it just prints zeros over and over again without the user entering anything. Apart from that it's fine! The behaviour of mine (bearing in mind I only use the feature casually, and it's never been implemented comprehensively), is as follows: * It is strictly line oriented. Each READLN discards the rest of the last read, and asks for a fresh line of input. It can never get out of sync * If fewer than 3 items are entered, the missing ones are zero. (In dynamic version, they are read as "".) It will not hang. * If more than 3 items are entered, those are ignored. (A program would have to speculatively read a fourth item, as a string, to test for trailing characters) * Numeric separators within numbers like "_" and "'" are recognised and skipped. * Numbers can be separated by white space or commas, or a mix (remember this can be used for ad hoc user input, not tidy machine-generated files) * Floating point numbers are properly consumed, then converted to ints (when reading int values) * Out-of-range numbers are truncated to 64 bits (for int types). (In dynamic version, it results in a bignum value.) * For certain errors, internal flags are set, which can be interrogated with a special Read (eg. read err:"e"), but I rarely do so. It doesn't now screw any line synchronisation * Print items can be enclosed in quotes. (Mainly for the benefit of strings, names etc which then allow embedded spaces, commas and quotes, but all print items share the same tokenisation step.) Hope that answers your question! I can't speak specifically for that Basic code, as I only tested one version, and only to confirm that it appeared to be line-oriented too. |
| Ian Collins <ian-news@hotmail.com>: Sep 24 10:06AM +1200 On 24/09/2021 05:30, Manfred wrote: > whatever. > I find it really hard to try and reason with such an insulting attitude. > Have it your way. Incorrect might be a kinder way of putting it. Many command line tools provide a variety of output formatting options, such as human and machine readable formats. Even basic kernel and driver logging requires some degree of formatting (timestamps, fixed widths etc.). Much "systems" programming is tool writing. -- Ian |
| scott@slp53.sl.home (Scott Lurndal): Sep 23 05:15PM >For a Windows DLL you can override `malloc` internally in the DLL, but a >Unix shared library is more like a static library, not separate from the >client code, so you can't do that with a shared library. By why criteria do you consider a unix shared object to be anything like a static library? "malloc" is a "weak" symbol in all modern unix systems, which means that the symbol can be overridden by the application if desired. |
| "Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Sep 23 09:59PM +0200 On 23 Sep 2021 19:15, Scott Lurndal wrote: > a static library? > "malloc" is a "weak" symbol in all modern unix systems, which means that > the symbol can be overridden by the application if desired. The OP is interested in overriding it locally in his library (to be precise the OP calls it a "package", I presume that's a library). A Windows DLL supports that local override where the library uses one variant of `malloc` while the client code, the app, uses another. I believe, but please correct me if I'm wrong, that you can't do that with a Unix shared library? - Alf |
| 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:
Post a Comment