|
Yeah, I've seen that. Wasn't that the same posting which tried to express a pair using the syntax (a,b) ?
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)
|
|
|
|
|
Yes, you contributed an answer to that one[^], where (a, b) was the syntax for a function definition's unnamed arguments!
|
|
|
|
|
C++ tried it's best to be compatible with C at the beginning, including it's idiosyncrasies. What's the point in the compiler guessing what the programmer's intention might be?
|
|
|
|
|
I do not think a compiler should be guessing at what a programmer's intention should be. It should give them a warning (or error) that what they are asking makes no since. The compilers job is to turn your text into a program that runs on the given platform.
There are two major issues with the compiler making dissensions for you:
1) You are not learning how to tell it what to do.
2) Your are learning that even if you do not understand how it works, that someone (way smarter than you) has figured out how to make it work - even if you don't.
The main problem is that their solution to the problem (#2) may result in a solution that breaks what you intended. You'll never become an expert in the language of your choice if the compiler is deciding what you intended to do, as apposed to what you actually told it to do.
INTP
"Program testing can be used to show the presence of bugs, but never to show their absence." - Edsger Dijkstra
"I have never been lost, but I will admit to being confused for several weeks. " - Daniel Boone
|
|
|
|
|
John R. Shaw wrote: It should give them a warning (or error) that what they are asking makes no since. I suppose you wanted to say "makes no sense"?
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
One major difference between the TCP/IP protocol suite and the OSI protocol suite is that the former asks you to try to make sense of whatever you receive, one way or the other.
OSI follows the principle that a protocol error is fatal, you cancel the connection. Disconnect is mandatory; if you continue operation trying to keep it going, then you are not conformant to the standard. Those sloppy, haphazard implementations are kicked out. If you want to exchange data, you better do it in the proper way!
Of course it makes it more difficult to be an eager student who has not yet learnt proper behavior; before he goes out in the wide open world he must know what to do. The Internet lenient philosophy is fair enough while you are still playing in the sand pit, but not when you grow up.
Programming languages are similar. They should define clearly what you can and cannot do. They should specify clearly all the issues that the compiler is required to detect, those that the generated code / runtime system is required to detect, and those that cannot reasonably be detected neither at compile time nor run time but is nevertheless an error. I know of one language specifications that includes all three, the Z.200 CHILL language. Unfortunately, CHILL never made it as a mainstream language (nobody really tried to make it!) - it was a language design of excellent quality. But I guess most programmers moving from C to CHILL would feel the strict discipline as a straightjacket.
|
|
|
|
|
That's one of the problems that don't fit modern coding standards: When your (valid) syntax doesn't properly express what it does, then your choice of syntax is bad. In your example, it would be better to use some function like
template <class T> T* makeCArrayOfLength(size_t length) { return new T[length]; }
whereas the functionality you invoked should be represented by
template <class T> T* makeObjectFromValue(T const& value) { return new T(value); }
That syntax not only will give you much better insight on what you are doing, it might also cause compiler warnings or errors when used incorrectly.
Of course, it's a little more effort to write
_TCHAR *buffer = makeCArrayOfLength<_TCHAR>(buffersize);
But that effort pays off in the long run.
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)
|
|
|
|
|
To my mind, the code I wrote should have triggered a compiler diagnostic. The expression on the left side of the assignment operator is a pointer to _TCHAR while the right side is a single _TCHAR constructed from the value buffer_size . Barring perversions of the assignment operator, those two aren't the same thing.
Of course, I am using a very old version of Visual Studio for this project, so...
Software Zen: delete this;
|
|
|
|
|
Unfortunately, new creates an object on the heap, and it does return a pointer. That corresponds to the left hand side. Also, it's not obvious to the compiler to understand what you intended. If you had constructed a class instance instead, it would be quite reasonable. While creating an integral type on the heap is quite unusual, it might still make sense if that code is part of a template implementation:
template <class T>
T* copy(T& const source) {
return new T(source);
}
This code works for any kind of class, but also for integral types. So why should the compiler complain?
However, the crux of the problem is that C/C++ treat {addreess to first element of array} the same as {address of object}. It doesn't differentiate the two, and that is why your assignment doesn't even raise a warning.
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)
|
|
|
|
|
Aha! Thanks for the explanation. I sometimes forget subtleties because I'm constantly switching back and forth between C++ and C#.
Software Zen: delete this;
|
|
|
|
|
Stefan_Lang wrote: However, the crux of the problem is that C/C++ treat {addreess to first element of array} the same as {address of object}. It doesn't differentiate the two, and that is why your assignment doesn't even raise a warning.
const char *c = "Hello world!";
std::cout << "*c = " << *c << "\n";
std::cout << "size of *c = " << sizeof *c << "\n";
std::cout << "c[0] = " << c[0] << "\n";
std::cout << "size of c[0] = " << sizeof c[0] << "\n";
std::cout << "c = " << c << "\n";
std::cout << "size of c = " << sizeof c << "\n";
std::cout << "&c[0] = " << &c[0] << "\n";
std::cout << "size of &c[0] = " << sizeof &c[0] << "\n";
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
|
So for the C++ illiterate, what's wrong with that line of code? Or did you mean new _TCHAR[buffer_size]; ?
|
|
|
|
|
Precisely. As written, it casts buffer_size as a _TCHAR and allocates only one of them.
|
|
|
|
|
This man, Mr. Arnab Chakraborty has taught me so much about parsing. His videos are incredible. They're basically class lectures on advanced CS topics, like this one on viable prefix computation in shift reduce parsing.
Viable Prefixes and Valid Items - YouTube[^]
It appears he's not a doctor - not that it matters, but it's just startling to me given the variety of advanced subjects I've found him lecture on. I'd think he'd make a great CS professor anywhere.
I'm not really here to plug his site, but he's such a valuable resource at the same time i don't want anyone to miss out. I usually google with "tutorialspoint [topic]" if i want to find him in particular.
I don't even usually like videos to teach things, but in some cases seeing him whiteboard it is very helpful.
Real programmers use butterflies
|
|
|
|
|
|
NPTEL seems to be great resource for online learning.
If you are not criticized, you may not be doing much.
|
|
|
|
|
Forget digresses! Either he knows what he it talking about or he does not. I've been telling computers what to do for over 30 years and do not have a degree. But then again, there was no degree's on the subject when I stated.
INTP
"Program testing can be used to show the presence of bugs, but never to show their absence." - Edsger Dijkstra
"I have never been lost, but I will admit to being confused for several weeks. " - Daniel Boone
|
|
|
|
|
I don't have a degree either, and it's one of the reasons I find the work above so valuable.
Real programmers use butterflies
|
|
|
|
|
When I saw a cmovne instruction in a disassembly through which I am tracing, I asked Bing what it was, and got the details at Purpose of cmove instruction in x86 assembly? - Stack Overflow, which are borne out by the demonstrated behavior of my code. It appears that the Visual C++ compiler that ships with Visual Studio 2019 counts the cost of two mov instructions followed by a cmovne instruction as less than that of a branch that causes both to execute anyway, even though the outcome of one of the two mov instructions would eventually be discarded.
Moreover, this is happening in a debug build!
This is by no means the first such unexpected optimization that I've seen the MSVC compiler generate in a debug build.
David A. Gray
Delivering Solutions for the Ages, One Problem at a Time
Interpreting the Fundamental Principle of Tabular Reporting
|
|
|
|
|
David A. Gray wrote: It appears that the Visual C++ compiler that ships with Visual Studio 2019 counts the cost of two mov instructions followed by a cmovne instruction as less than that of a branch that causes both
Keep in mind that due to the speculative execution leaks... the emitted instructions may be avoiding data-dependent branching. Optimization is not as simple as it was ten years ago...
Do me a favor and right click on your project settings and navigate to the 'Code Generation' tab and check if /Qspectre is enabled.
|
|
|
|
|
My take on the whole point of the conditional move instruction is to eliminate speculative execution from the mix by keeping the program flow in a straight line. FWIW, I double-checked, and Spectre mitigation is disabled. I suspected it was, because I've never enabled it for any of my projects.
What made it stand out was that this was happening in a debug build. Had it been a release build, I would have expected this level of optimization. However, this is the most recent of many such unanticipated, and welcome, optimizations, that I've seen in recent debug builds.
David A. Gray
Delivering Solutions for the Ages, One Problem at a Time
Interpreting the Fundamental Principle of Tabular Reporting
|
|
|
|
|
David A. Gray wrote: What made it stand out was that this was happening in a debug build. Had it been a release build, I would have expected this level of optimization. However, this is the most recent of many such unanticipated, and welcome, optimizations, that I've seen in recent debug builds. Yeah, it's not a coincidence that the first compiler implementing the /Qspectre mitigations[^] is generating slighty different conditional moves. It's an active area of development.
Best Wishes,
-David Delaune
|
|
|
|
|
I just pasted a block of #define directives from the application header of a C++ program that I am writing in preparation for writing a short article for the Actian developer blog. When I applied the Trim worksheet function to a substring that contains a hexadecimal value that I wanted in its own column, I noticed that the cell had a leading space. Since it obviously wasn't a SPACE or a TAB, I turned on the hexadecimal view mode in my editor (UltraEdit), and discovered that the hexadecimal code of the character at that location was 0xA0, 160 decimal, the nonbreaking space character.
David A. Gray
Delivering Solutions for the Ages, One Problem at a Time
Interpreting the Fundamental Principle of Tabular Reporting
|
|
|
|
|
I always use invisible whitespace in my comment and human strings, don't you?!
Everyone loves them!
|
|
|
|