| olcott <NoOne@nospicedham.NoWhere.com>: Apr 17 09:15AM -0500 If a function X() is called by function Y() twice in sequence from the same machine address of Y() with the same parameters to X() and the execution trace shows no conditional branch instructions in Y() or function call returns in X() then the function call from Y() to X() is infinitely recursive unless X() stops it. The referenced excution trace is on x86 machine language, disassembled for human consumption. -- Copyright 2021 Pete Olcott "Great spirits have always encountered violent opposition from mediocre minds." Einstein |
| MrSpook__k@rw5_r42g0rzmn7wwf3izpl4.biz: Apr 17 03:16PM On Sat, 17 Apr 2021 09:15:14 -0500 >Copyright 2021 Pete Olcott Pretentious twat. |
| olcott <NoOne@NoWhere.com>: Apr 17 10:22AM -0500 > olcott <NoOne@nospicedham.NoWhere.com> wrote: >> Copyright 2021 Pete Olcott > Pretentious twat. ad hominem the favorite reply of ignoramuses. -- Copyright 2021 Pete Olcott "Great spirits have always encountered violent opposition from mediocre minds." Einstein |
| MrSpook_ejo78o@4t98owsqx2nlg6yp.com: Apr 17 03:32PM On Sat, 17 Apr 2021 10:22:47 -0500 >Copyright 2021 Pete Olcott >"Great spirits have always encountered violent opposition from mediocre >minds." Einstein Self aggrandisement, the favourite approach of Dunning-Kruger types. |
| Kaz Kylheku <563-365-8930@kylheku.com>: Apr 17 03:41PM >>> Copyright 2021 Pete Olcott >> Pretentious twat. > ad hominem the favorite reply of ignoramuses. I see you have not yet read the exellent article: https://laurencetennant.com/bonds/adhominem.html |
| olcott <NoOne@nospicedham.NoWhere.com>: Apr 17 11:01AM -0500 On 4/17/2021 9:15 AM, olcott wrote: > infinitely recursive unless X() stops it. > The referenced execution trace is on x86 machine language, disassembled > for human consumption. When Halts() uses an x86 emulator to simulate its input and maintains an execution trace of this emulation then it can examine this execution trace according to the above criteria and correctly decide that Y() is invoking X() in infinite recursion. On this basis it can stop simulating Y() and report that Y() would not halt unless its execution was aborted by Halts(). void Y(u32 P) Halts(P, P); } int main() { Halts((u32)Y, (u32)Y); } _Y() [000009ac](01) 55 push ebp [000009ad](02) 8bec mov ebp,esp [000009af](03) 8b4508 mov eax,[ebp+08] [000009b2](01) 50 push eax [000009b3](03) 8b4d08 mov ecx,[ebp+08] [000009b6](01) 51 push ecx [000009b7](05) e840feffff call 000007fc [000009bc](03) 83c408 add esp,+08 [000009bf](01) 5d pop ebp [000009c0](01) c3 ret Size in bytes:(0021) [000009c0] _main() [000009cc](01) 55 push ebp [000009cd](02) 8bec mov ebp,esp [000009cf](05) 68ac090000 push 000009ac [000009d4](05) 68ac090000 push 000009ac [000009d9](05) e81efeffff call 000007fc [000009de](03) 83c408 add esp,+08 [000009e1](02) 33c0 xor eax,eax [000009e3](01) 5d pop ebp [000009e4](01) c3 ret Size in bytes:(0025) [000009e4] =============================== ....[000009cc][00011278][00000000](01) 55 push ebp ....[000009cd][00011278][00000000](02) 8bec mov ebp,esp ....[000009cf][00011274][000009ac](05) 68ac090000 push 000009ac ....[000009d4][00011270][000009ac](05) 68ac090000 push 000009ac ....[000009d9][0001126c][000009de](05) e81efeffff call 000007fc Begin Local Halt Decider Simulation at Machine Address:9ac ....[000009ac][00031318][0003131c](01) 55 push ebp ....[000009ad][00031318][0003131c](02) 8bec mov ebp,esp ....[000009af][00031318][0003131c](03) 8b4508 mov eax,[ebp+08] ....[000009b2][00031314][000009ac](01) 50 push eax ....[000009b3][00031314][000009ac](03) 8b4d08 mov ecx,[ebp+08] ....[000009b6][00031310][000009ac](01) 51 push ecx ....[000009b7][0003130c][000009bc](05) e840feffff call 000007fc ....[000009ac][0007bd40][0007bd44](01) 55 push ebp ....[000009ad][0007bd40][0007bd44](02) 8bec mov ebp,esp ....[000009af][0007bd40][0007bd44](03) 8b4508 mov eax,[ebp+08] ....[000009b2][0007bd3c][000009ac](01) 50 push eax ....[000009b3][0007bd3c][000009ac](03) 8b4d08 mov ecx,[ebp+08] ....[000009b6][0007bd38][000009ac](01) 51 push ecx ....[000009b7][0007bd34][000009bc](05) e840feffff call 000007fc Local Halt Decider: Infinite Recursion Detected Simulation Stopped ....[000009de][00011278][00000000](03) 83c408 add esp,+08 ....[000009e1][00011278][00000000](02) 33c0 xor eax,eax ....[000009e3][0001127c][00010000](01) 5d pop ebp ....[000009e4][00011280][00000058](01) c3 ret Number_of_User_Instructions(23) Number of Instructions Executed(16920) sizeof(Decoded_Line_Of_Code)(24) -- Copyright 2021 Pete Olcott "Great spirits have always encountered violent opposition from mediocre minds." Einstein |
| olcott <NoOne@NoWhere.com>: Apr 17 02:02PM -0500 On 4/17/2021 10:41 AM, Kaz Kylheku wrote: >> ad hominem the favorite reply of ignoramuses. > I see you have not yet read the exellent article: > https://laurencetennant.com/bonds/adhominem.html In any case back to the actual point the following <is> confirmed to be correct halt deciding criteria in the case of infinite recursion. If a function X() is called by function Y() twice in sequence from the same machine address of Y() with the same parameters to X() and the execution trace shows no conditional branch instructions in Y() or a function call returns from X() then the function call from Y() to X() is infinitely recursive unless X() stops it. The referenced execution trace is on x86 machine language, disassembled for human consumption. When Halts() uses an x86 emulator to simulate its input and maintains an execution trace of this emulation then it can examine this execution trace according to the above criteria and correctly decide that Y() is invoking X() in infinite recursion. On this basis Halts() can stop simulating Y() and report that Y() would not halt unless its execution was aborted by Halts(). void Y(u32 P) { Halts(P, P); } int main() { Halts((u32)Y, (u32)Y); } -- Copyright 2021 Pete Olcott "Great spirits have always encountered violent opposition from mediocre minds." Einstein |
| olcott <NoOne@NoWhere.com>: Apr 17 02:23PM -0500 On 4/17/2021 2:14 PM, Kaz Kylheku wrote: > as any other. > Name calling isn't an argument; therefore we might say that it's "not > even fallacious". Can we get back to the actual point or are you afraid to do this because when a point is correct there is no basis for rebuttal? The halt deciding principle If a function X() is called by function Y() twice in sequence from the same machine address of Y() with the same parameters to X() and the execution trace shows no conditional branch instructions in Y() or function call returns from X() then the function call from Y() to X() is infinitely recursive unless X() stops it. -- Copyright 2021 Pete Olcott "Great spirits have always encountered violent opposition from mediocre minds." Einstein |
| Real Troll <rel.troll@trolls.com>: Apr 17 08:38PM +0100 On 17/04/2021 20:23, olcott wrote: > execution trace shows no conditional branch instructions in Y() or > function call returns from X() then the function call from Y() to X() > is infinitely recursive unless X() stops it. Does this not depend on what the functions are doing? If the function gets a value and uses it for something else then as far as I can see that's it. If you call the same function second time then it will do the same [again]. Either use the value or simply ignores it and stops. I am not sure what has this got to do with recursion? Have you got a concrete example to try it? Cross posting to comp.theory removed as it has nothing to do on my machine!! |
| olcott <NoOne@NoWhere.com>: Apr 17 03:01PM -0500 On 4/17/2021 2:38 PM, Real Troll wrote: > I am not sure what has this got to do with recursion? Have you got a > concrete example to try it? > Cross posting to comp.theory removed as it has nothing to do on my machine!! I am trying to make a halt decider that can correctly detect infinite recursion. Here are some more key details: When Halts() uses an x86 emulator to simulate its input and maintains an execution trace of this emulation then it can examine this execution trace according to the above criteria and correctly decide that Y() is invoking X() in infinite recursion. On this basis it can stop simulating Y() and report that Y() would not halt unless its execution was aborted by Halts(). void Y(u32 P) { Halts(P, P); } int main() { Halts((u32)Y, (u32)Y); } http://www.liarparadox.org/Halting_problem_undecidability_and_infinite_recursion.pdf -- Copyright 2021 Pete Olcott "Great spirits have always encountered violent opposition from mediocre minds." Einstein |
| olcott <NoOne@NoWhere.com>: Apr 17 03:56PM -0500 On 4/17/2021 3:47 PM, Malcolm McLean wrote: > modest claim from someone with a reputation in the field, but maybe whom > you don't like. It's the same underlying fallacy, but the second is a higher dose > and far more likely to lead to a false conclusion. It seems to me that everyone dodges this point because I am correct The halt deciding principle for infinite recursion If a function X() is called by function Y() twice in sequence from the same machine address of Y() with the same parameters to X() and the execution trace shows no conditional branch instructions in Y() or a function call returns from X() then the function call from Y() to X() is infinitely recursive unless X() stops it. http://www.liarparadox.org/Halting_problem_undecidability_and_infinite_recursion.pdf -- Copyright 2021 Pete Olcott "Great spirits have always encountered violent opposition from mediocre minds." Einstein |
| Kaz Kylheku <563-365-8930@nospicedham.kylheku.com>: Apr 17 03:01PM > If a function X() is called by function Y() twice in sequence from the > same machine address of Y() with the same parameters to X() and the > execution trace shows no conditional branch instructions in Y() or The problem is, the execution trace only shows no such instructions because you have concealed them. You have declared that X is part of the "operating system" and not part of the test case. So in your trace there is an illegal discontinuity. There is a JSR Halts instruction executed, but then the next instruction which is traced is not inside Halts, but inside H_Hat. The address does not match. > function call returns in X() then the function call from Y() to X() is > infinitely recursive unless X() stops it. Problem is, the above decision about the traces is being made by X itself. It is accessing these global tracers, which make X not a function, but an imperative procedure. Below is a quote from the following idiotic document: http://www.liarparadox.org/Eliminating_pathological_self_reference_error_from_the_halting_problem.pdf Note how after every "call 00000833", the next instruction being traced is not 00000833, but 00000A63. A63 is _H_Hat. The document does not reveal the disassembly of code at 833, so we have no idea what instructions are there. However, those instructions have to do with the decision that leads to "Infinite Recursion Detected", which is not possible without conditionals. (01)[00000a93][000114f7][00000000] (01) 55 push ebp (02)[00000a94][000114f7][00000000] (02) 8bec mov ebp,esp (03)[00000a96][000114f3][00000000] (01) 51 push ecx (04)[00000a97][000114ef][00000a63] (05) 68630a0000 push 00000a63 (05)[00000a9c][000114eb][00000a63] (05) 68630a0000 push 00000a63 (06)[00000aa1][000114e7][00000aa6] (05) e8ddfdffff call 00000883 (07)[00000a63][00031577][0003157b] (01) 55 push ebp (08)[00000a64][00031577][0003157b] (02) 8bec mov ebp,esp (09)[00000a66][00031573][00021547] (01) 51 push ecx (10)[00000a67][00031573][00021547] (03) 8b4508 mov eax,[ebp+08] (11)[00000a6a][0003156f][00000a63] (01) 50 push eax (12)[00000a6b][0003156f][00000a63] (03) 8b4d08 mov ecx,[ebp+08] (13)[00000a6e][0003156b][00000a63] (01) 51 push ecx (14)[00000a6f][00031567][00000a74] (05) e80ffeffff call 00000883 (15)[00000a63][0004271f][00042723] (01) 55 push ebp (16)[00000a64][0004271f][00042723] (02) 8bec mov ebp,esp (17)[00000a66][0004271b][000326ef] (01) 51 push ecx (18)[00000a67][0004271b][000326ef] (03) 8b4508 mov eax,[ebp+08] (19)[00000a6a][00042717][00000a63] (01) 50 push eax (20)[00000a6b][00042717][00000a63] (03) 8b4d08 mov ecx,[ebp+08] (21)[00000a6e][00042713][00000a63] (01) 51 push ecx (22)[00000a6f][0004270f][00000a74] (05) e80ffeffff call 00000883 Infinite Recursion Detected Simulation Stopped -- TXR Programming Language: http://nongnu.org/txr Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal |
| Bonita Montero <Bonita.Montero@gmail.com>: Apr 18 12:03AM +0200 STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! STOP POSTING IN comp.lang.c/c++ !!! |
| olcott <NoOne@NoWhere.com>: Apr 17 05:12PM -0500 On 4/17/2021 5:03 PM, Bonita Montero wrote: > STOP POSTING IN comp.lang.c/c++ !!! KNOW !!! -- Copyright 2021 Pete Olcott "Great spirits have always encountered violent opposition from mediocre minds." Einstein |
| olcott <NoOne@NoWhere.com>: Apr 17 05:30PM -0500 On 4/17/2021 10:01 AM, Kaz Kylheku wrote: >> execution trace shows no conditional branch instructions in Y() or > The problem is, the execution trace only shows no such instructions > because you have concealed them. You are responding with boiler-plate that does not account for my reconfiguration. A halt deciding principle that detects infinite recursion If a function X() is called by function Y() twice in sequence from the same machine address of Y() with the same parameters to X() and the execution trace shows no conditional branch instructions in Y() or a function call returns from X() then the function call from Y() to X() is infinitely recursive unless X() stops it. The above specification need not look inside X() at all as long is we have the assurance that the execution trace of X() does not include any "ret" instructions. I modified my halt decider to makes sure that this part works correctly. -- Copyright 2021 Pete Olcott "Great spirits have always encountered violent opposition from mediocre minds." Einstein |
| Juha Nieminen <nospam@thanks.invalid>: Apr 17 05:56AM I know that this is probably going to piss off avid C programmers, but I don't really care all that much. Many C fans keep insisting how C is so much better than C++ because C++ is so utterly complicated, with a standard that reads like a phonebook and a standard library so vast that nobody in their sane mind could ever even hope to remember all of it, and how C++ is becoming more and more complicated with every standard, and how C is such a simple, straightforward and beautiful language, so immensely better than C++. I myself happen to know both languages quite well, and in fact I program in both languages as my profession, and I would say that I am very knowledgeable and proficient in both languages and have no trouble in developing in either one. I am of the strong opinion that no, C is not a "simple" language, and that C++ makes so many things so much simpler, easier and safer. I was reminded of this in a quite concrete manner recently when I was trying to help a beginner programmer who had decided to try his hands on C, and wanted to create a simple text editor, which would read a text file, allow the user to edit the text in several ways, and to save the file. It quite quickly turned very frustrating for *both* of us that dynamic string manipulation in C is so damn complicated, especially for a complete beginner who has never programmed in C, and has only very little experience even with other programming languages (he had some very small experience with Python.) I tried approaching the problem by explaining that for a project of this nature and size, it would be much more better to create a separate (and reusable) "string" module, ie. a struct that represents a string (which has a char* and a length member variable), and a bunch of functions that operate on objects of that struct type, clearly and logically named. (In other words, I was trying to make him essentially replicate a subset of std::string in C.) This would make it much easier to do things like appending strings to other strings, inserting characters and strings in the middle of other strings (having them automatically grow dynamically), and so on. Even then, it was just frustration after frustration, trying to explain and make him understand why in C you need to always explicitly call an initializer function (ie. "constructor") for every single new string object (and any struct that may have such a string object as a member variable, and any struct that may have those types of structs as members, all the way down), and especially how you have to make sure to call the destruction function for every such object, or else there would be a leak. It's surprisingly complicated and frustrating to try to explain to a complete beginner how and why he should follow very strict coding practices when it comes to initializing and destructing every object and, especially, why he should be very careful about assigning string objects to each other directly. In the middle of this mountain of new complicated information, try to explain to a complete beginner the subtleties of doing this: String str1 = String_with_cstr("hello"); String str2 = str1; While not wrong per se, and it actually does have its uses, it's very prone to errors because now str1 and str2 are pointing to the same string data, so only one of them must be destroyed and the other must not be used after that (unless it's initialized again). Also, trying to inculcate how wrong this is, and how important it is to avoid it: String str1 = String_with_cstr("hello"); String str2 = String_with_cstr("there"); str1 = str2; // No! He also asked why he couldn't do something like this: String str = "hello"; Now try to explain why that doesn't directly work (obviously causes a compiler error), and try to think whether you should explain that he *can* assign the string literal to the member char* of the struct (remember to also update the length parameter) but once again how fraught with peril that is, because now he will have to remember to *not* destruct *this* particular object, or else bad things will happen. Then try to explain the concept of string capacity vs its length, which is useful in this kind of module because of efficiency reasons (and also because the string may become shorter, while retaining its capacity). The worst thing, however, was trying to inculcate the importance of always properly initializing and destructing the objects at the proper places, and to avoid the pitfalls and mistakes that are so easy to make when handling such objects. And those are just a couple of examples from many. I couldn't help but to constantly comment how much easier all this would be in C++, using std::string, where you don't have to worry about any of that. The project he was trying to make was almost *trivial* to do in C++, because of the readymade tools available in the standard library, and the ease and safety mechanisms provided by the language. Instead of writing thousands of lines of code to create his own string class, and then having to follow strict coding practices to avoid mistakes when creating dynamic arrays of such string objects, in C++ he could just create a std::vector<std::string> and be done with it. All the tools he needed for that project available easily and safely. |
| Christian Gollwitzer <auriocus@gmx.de>: Apr 17 08:42AM +0200 Am 17.04.21 um 07:56 schrieb Juha Nieminen: > mind could ever even hope to remember all of it, and how C++ is > becoming more and more complicated with every standard, and how > C is such a simple, straightforward and beautiful language I fully agree and I think there is a confusion about the word "simple". C is definitively a simple language in the sense that the definition of it is small, therefore the code maps very directly to the underlying assembly and it is easy to write a compiler for. That, however, doesn't make it simple to *use*, rather the opposite - otherwise we would be coding in Brainfuck or lambda calculus, these are inherently simple languages. C++'s quirks actually come from the forced compatibility with C, for example why is this "abc" not a string, but a pointer? Why are unsigned integers used not only for bit-twiddling? std::string test = "abc" + "def"; // Very strange error for (size_t c=5; c>=0; c--); // endless loop For a language to be simple to use, it needs a way to express the intent of the programmer in the language he thinks in. This varies for different domains of computing: Numerical algorithms -> infix math, linear algebra Data structures -> List comprehensions, functional programming Controlling hardware, IO -> Serial/Iterative programming GUIs -> Classes and Inheritance Otherwise, the programmer is forced to shoehorn the problem into the language. This is easily shown by the abominations of Java's forced-OO APIs and "Design patterns" or when you try to do numerical math in Lisp. To be simple to *use*, a language must be complex - because then you can choose the right paradigm for your work. Another example: A pocket calculator is so much simpler and more beautiful than a current computer! But we wouldn't use it to calculate the stability of a bicycle frame using it. Christian |
| wij <wyniijj@gmail.com>: Apr 16 11:49PM -0700 On Saturday, 17 April 2021 at 13:57:04 UTC+8, Juha Nieminen wrote: > dynamic arrays of such string objects, in C++ he could just create a > std::vector<std::string> and be done with it. All the tools he needed > for that project available easily and safely. One reason C programmer do not like C++ is C++ does things in the background Good or bad? not easy to say shortly. But something is sure, pretty much in all cases, programmers sooner or latter will need to know those underlying things, C or better, Assembly. C++ is no exception. |
| MrSpook_wb@g9b2a_ex9aicgvs04.net: Apr 17 10:27AM On Sat, 17 Apr 2021 05:56:42 +0000 (UTC) >complete beginner who has never programmed in C, and has only very >little experience even with other programming languages (he had some >very small experience with Python.) Umm, asprintf() >which is useful in this kind of module because of efficiency reasons >(and also because the string may become shorter, while retaining its >capacity). Any powerful language is hard to learn at the start. Try telling a beginner about C++ virtual function overloading or templates and watch the blank expression appear. However once someone DOES know C or C++ it all becomes 2nd nature. |
| jacobnavia <jacob@jacob.remcomp.fr>: Apr 17 05:43PM +0200 Le 17/04/2021 à 07:56, Juha Nieminen a écrit : > I know that this is probably going to piss off avid C programmers, > but I don't really care all that much. It is funny how comic you look trying to convince people that C is complicated, even more complicated than c++, imagine that. Obviously I am one of those "avid" C programmers that never quite got into the c++ bandwagon. > becoming more and more complicated with every standard, and how > C is such a simple, straightforward and beautiful language, so > immensely better than C++. The whole C language fits in your brain without overflowing it with computer trivia. Try that with c++. [snip] > String str1 = String_with_cstr("hello"); > String str2 = String_with_cstr("there"); > str1 = str2; // No! Did you try to explain him about why c++ has similar problems? For instance: #include <iostream> #include <string> #include <string_view> int main() { std::string s = "Hellooooooooooooooo "; std::string_view sv = s + "World\n"; std::cout << sv; } Here, the expression s + "World" yields a std::string that is converted to a string view and immediately freed. Each time you use the string view you risk a segmentation fault. Now, try to explain that to a beginner! And of course you did NOT tell that beginner that he could avoid all accounting problems with strings if ne NEVER frees any string and just uses Boehm's GC that is available for C since more than a decade. You are ignoring how to use C efficiently and using the right tools. > He also asked why he couldn't do something like this: > String str = "hello"; He could do: const String str = { 5, "hello"}; But that is beyond the poor beginner's brain capacity or what? Obviously assuming that writing a text editor for a guy that doesn't know much about programming is an "easy" task is not an error from YOUR side! Nonsense really |
| Manfred <noname@add.invalid>: Apr 17 07:12PM +0200 (cross-posting to comp.lang.c to let the heat fire up) On 4/17/2021 7:56 AM, Juha Nieminen wrote: > I know that this is probably going to piss off avid C programmers, > but I don't really care all that much. Excellent start [...] > text file, allow the user to edit the text in several ways, and to > save the file. > It quite quickly turned very frustrating for *both* of us ... The first comment that comes to mind is that probably part of the frustration stems from your approach (no offense) to try and use in C a design that would be suitable for C++ instead. Despite their name, the two are quite different languages. The similarities are about their runtime footprint, not about how they are used. For example, at a first glance the design of string object is not that great for C. A common pattern that pops to the mind is to use opaque structs (see e.g. FILE*), and have something like: typedef struct string_t STRING; STRING* alloc_string(); // creates the empty string STRING* set_string(STRING* s, const char* value); void free_string(STRING* s); STRING* concat_string(STRING* s1, STRING* s2); ... This way there would be no ambiguity about how the STRING object has to be used. And yes, in C you have to do all yourself - C is a low level language, and it is meant for low level stuff. It is hardly the right tool for anything meant to interface with a human user - it is (still) great for system programming and back-end processing, IMO. As second, I agree with Jacob that a text editor is a simple tool, but it is not easy to make expecially for a beginner. [snip] |
| Bonita Montero <Bonita.Montero@gmail.com>: Apr 17 09:36PM +0200 > I am of the strong opinion that no, C is not a "simple" language, > and that C++ makes so many things so much simpler, easier and safer. Of course C is a very simple language, i.e. the language itself is very easy to understand. But it hard to develop in C because C lacks almost every modern language facility. C++ as the language itself is hard to understand, but if you've managed to understand it, it is by magnitudes easier to develop with C++. |
| Paavo Helde <myfirstname@osa.pri.ee>: Apr 18 12:48AM +0300 17.04.2021 08:56 Juha Nieminen kirjutas: > Many C fans keep insisting how C is so much better than C++ because > C is such a simple, straightforward and beautiful language, so This claim might be true, but this has no relevance to whether C should be used for a given task. For any given task one should choose the best fitting tool, not the simplest one. For example, the simplest reliable tool for ensuring a horizontal level is a water-filled hose. OTOH, the easiest one to use is generally a cross line laser, built on technologies whose very existence is still not believed by some people. Nothing simple there. However, in some circumstances, like with limited access and no clear line of sight, a water-filled hose might still yield a better result than any high-tech alternative (e.g. GPS). So, for each usage there is a best tool. Sometimes the tool is itself simple, sometimes it's not. Sometimes there is no good tool and one needs to invent a new one (inventing TeX for typesetting comes to mind). |
| olcott <NoOne@NoWhere.com>: Apr 17 09:17AM -0500 If a function X() is called by function Y() twice in sequence from the same machine address of Y() with the same parameters to X() and the execution trace shows no conditional branch instructions in Y() or function call returns in X() then the function call from Y() to X() is infinitely recursive unless X() stops it. The referenced execution trace is on x86 machine language, disassembled for human consumption. -- Copyright 2021 Pete Olcott "Great spirits have always encountered violent opposition from mediocre minds." Einstein |
| 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