- A string pointer to a static or dynamic string : how to free the dynamic one ? - 22 Updates
- Compute Unique Numbers in a Set - 2 Updates
- Vector Fractal Bloom... - 1 Update
Juha Nieminen <nospam@thanks.invalid>: Jan 23 06:34AM > This is C++, so just return a std::string from your function, and forget > everything about C-style strings, malloc, free and strdup. Good riddance! When it comes to "C-style strings", not really. After all, they are essentially just syntactic sugar over arrays of char, and thus have all the advantages of such arrays. C++ doesn't really add a "better" equivalent to C-style strings which would have all the efficiency benefits of them. std::string_view gets close, and in some cases it's actually the better choice, but it's not exactly the same thing (for starters, it's larger than the size of a pointer which, while in many cases that's inconsequential, sometimes it can be a deal breaker). And rather obviously std::string cannot completely replace C-style strings. While safetywise and featurewise it's mostly superior (save for a few exceptional cases), its problem is that it's always dynamically allocated and doesn't support statically allocated strings (which is the very reason why std::string_view was created, to support that very thing). In most cases avoiding the dynamic allocation may be completely unnecessary and without any benefit. However, in the situations where avoiding it does introduce a significant benefit it's good to have the alternative. Especially if all you need to handle the data is a pointer (and thus std::string_view would be overkill). |
Juha Nieminen <nospam@thanks.invalid>: Jan 23 06:40AM > pointers. Basically, if there were a /simple/ answer to your original question, there would be no > interesting debate, but there's not - so you need to carefully balance costs/benefits. Simple is > good, unless simple doesn't work! :) Instead of putting the meta information about the string in the pointer type, it could be put in the string itself. Make the first char of the string contain any information you need about the string (up to 8 bits of it available), and have the actual string contents start after that, and make the "pointer" point to that second byte. When destroying the string, make it check the actual first byte to see if it has to free it or not. This way the pointer itself can be the size of a pointer, and the metadata only takes 1 byte. |
"R.Wieser" <address@not.available>: Jan 23 08:04AM +0100 "James Kuyper" <jameskuyper@alumni.caltech.edu> wrote in message news:tqk7dn$386s5$1@dont-email.me... >> stored in ? > C doesn't have a string type, just a data storage format for strings > that is recognized by many standard library functions. The famous "C string", non terminated but instead with its length stored before the first character. > Since there is no string type, there's no specific pointer type that is > used for storing such pointers. Thats not what I'm trying to get at. You have an address and a variable you store that address in. Which names do you use for both ? I most allways see them referred to with the same phrase : "a string pointer". Which is ofcourse ambigue. That doesn't matter much in most circumstances (which one of the two it actually is can be gleaned from the context), but does some others. Regards, Rudy Wieser |
"R.Wieser" <address@not.available>: Jan 23 08:33AM +0100 "Keith Thompson" <Keith.S.Thompson+u@gmail.com> wrote in message news:87wn5egtw8.fsf@nosuchdomain.example.com... > If I understand you correctly, the two things you're referring to are > the pointer *value* and an *object* of pointer type that holds that > value. I do not call it an object, to me its just a variable. Anything beyond that (an object wich might contain other properties as well as methods) is (way) outside of my scope. > There's nothing special about pointers to strings here. > The same confusion occurs with, for example, a pointer to an int Indeed. But if there is one thing I've learned from Usenet it is that you need to keep the context to a question simple. Referring to all the other adresses and what they point to would just be "muddying the water". > between a value of some type and an object/variable that holds a > value of some type either *isn't important or is sufficiently clear > from the context*. Agreed. But thats the crux : somethimes I get the distinct feeling that someone is talking about the address (pointing to a string or otherwise), but than suddenly seems to talk about the variable holding it. :-\ > etc.) as an adjective rather than a noun. Thus we can refer to a > *pointer value*, or a *pointer object", or a *pointer type*, or a > *pointer expression*, all of which are clearly distinct concepts. I think I can translate "pointer value" as to be meaning an address. For the others ? I do not have the foggiest I'm afraid. > <OT> Whoooo.... Is that *on*, of *off* topic ? Not that it matters much which one though. :-) > For C's definition of a "pointer to a string", I'd say it refers > to a *value* of pointer type. AFAIK most people do not use that phrase but use the (shorthand) "string pointer" (with or without the space) instead. But yes, I would also. Though thats the whole problem to me : most people seem to use that "string pointer" phrase for the addres (the "value of pointer type") *as well as* the variable (or worse : an object) its stored in. But I think I am going to stop asking. It looks like the destinction between the address and what its stored in isn't of much, if any, importance to the people here. Oh well, you can't get /everything/ answered. :-) Regards, Rudy Wieser |
David Brown <david.brown@hesbynett.no>: Jan 23 09:46AM +0100 On 22/01/2023 19:16, jak wrote: >>> to a string" from the next C standard, then C will not have such >>> thing any more. But until then it does. >> The comments are feedback. Feedback helps. Faith sometimes kills. <snip> (This is a technical language group - please don't bring any kind of political or religious issues into it, even if you think they are analogous or illustrative. People get too worked up.) You can comment all you like on the C and C++ standards, but those are what /define/ the languages. Implementations follow those standards - often with extensions, variations and small non-conformities, but still basically following the standards. Books, courses, and tutorials (at least those of any quality) primarily follow the terminology and definitions from the standards. The standards are what give us our common language. They let someone call themselves a "C programmer", and let him or her write code that will compile on a "C compiler". They let people write a new C compiler for a new processor, and know people can use existing C code on it. They let people have technical language discussions in a group like this and know what each other is talking about. So when someone talks about "C strings" or "strings in C", we all know what is meant - the standards tell us. When someone says "this C function takes a string pointer", we know what it means. It doesn't matter that a "C string" is different from a "C++ std::string" or a "BASIC string" or a "piece of string", as long as the context is clear. (C++ standards are a bit more complicated than C standards, since there are bigger differences between the versions, but the same principles apply.) |
James Kuyper <jameskuyper@alumni.caltech.edu>: Jan 23 04:00AM -0500 On 1/23/23 02:33, R.Wieser wrote: > I do not call it an object, to me its just a variable. Anything beyond > that (an object wich might contain other properties as well as > methods) is (way) outside of my scope. The term "object" has a well-defined meaning in C, but since it is not an object-oriented language, that definition carries a lot less baggage than you're thinking of: "region of data storage in the execution environment, the contents of which can represent values" (3.15p2). The C standard does not define the noun "variable", a fact that is difficult to confirm because it makes extensive use of the adjective "variable". Also, it makes extensive use of the ISO convention of defining some terms by italicizing those terms inside of a sentence whose contents constitute the official definition of those terms, so in principle you have to search every use of the word "variable" in the entire standard. In practice, however, the index usually notes the location where a term is defined, if it is defined. C++ does have a definition of the noun "variable". If you strip that definition of everything specific to C++, it boils down to "named object". As far as I've been able to tell, that definition fits every use of the noun "variable" in the C standard. Therefore, I assume that's what the term means in the C standard, and I recommend that you do the same. For example, if you declare "struct tm *start_times;" and assign it to point at a dynamically allocated array of at least six elements, then start_times, the array that it points at, start_times[5], and start_times[5].tm_year are all considered to be objects, but only start_times and tm_year are variables, because they are the only objects in that list that have names. The array that start_times points at is an unnamed object, and the last two are sub-objects of that object. Therefore, every variable is also an object. >> *pointer expression*, all of which are clearly distinct concepts. > I think I can translate "pointer value" as to be meaning an address. > For the others ? I do not have the foggiest I'm afraid. A pointer object is a a region of memory used to store a pointer value. A pointer type is the type of a pointer value, including in particular the pointer value that might be stored in a pointer object. "An expression is a sequence of operators and operands that specifies computation of a value, 92) or that designates an object or a function, or that generates side effects, or that performs a combination thereof." (C standard, 6.5p1). Since operators and operands are parts of the text of a C program, expressions are things that exist only in the source code, not in the compiled program. Translation of source code into an executable results in the generation of code that does what the expression specifies should be done. A pointer expression is an expression that specifies computation of a pointer value, or designates a pointer object. This whole issue is especially difficult for a newbie because it's often perfectly clear, to an experienced user of C, whether "a pointer" refers to a pointer value, a pointer object, a pointer type, or a pointer expression. As a result, all of those terms are frequently shortened to "pointer", unless the context is ambiguous. This is true even within the standard itself. I'm sorry, but that's the way it is. I can't do anything about it even if I didn't find it convenient to do the same. All I can do is assure you that it will become clearer as you get more familiar with the language. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Jan 23 04:13AM -0500 On 1/23/23 02:04, R.Wieser wrote: > "James Kuyper" <jameskuyper@alumni.caltech.edu> wrote in message > news:tqk7dn$386s5$1@dont-email.me... ... >> that is recognized by many standard library functions. > The famous "C string", non terminated but instead with its length stored > before the first character. That sentence no verb. I point that out because that fact that is has no verb is part of the reason why I'm not sure what you meant by it. The term "string", as defined by the C standard, is by definition null-terminated, and does not have a stored length. > pointer". Which is ofcourse ambigue. That doesn't matter much in most > circumstances (which one of the two it actually is can be gleaned from the > context), but does some others. Any given use might seem ambiguous to a newbie like yourself, but the reason why it is commonplace to use "string pointer" without following it with "value", "object", "type", or "expression" is precisely because it's usually clear from context (at least to those with more experience with the language) which of those is being referred to. When it would otherwise be ambiguous, people usually (but unfortunately, not always) do add the additional word that's needed to make it clear. |
David Brown <david.brown@hesbynett.no>: Jan 23 10:24AM +0100 On 22/01/2023 20:46, Malcolm McLean wrote: >> variable (or object) > The snag is that C has no way of resolving the problem that a string has > an unknown number of bytes. That is a very clumsy way of expressing yourself. A string in C is a /value/ - it is formed by a particular set of characters of a particular length. What you are trying to say, I think, is that a /pointer/ to a string does not encode the length of the string. And that is true - but it is not a "snag" or a "problem". It is an unavoidable artefact of the simple way C strings are implemented. And it is easily solved by calling "strlen". > char *stringpointer; > *stringpointer = "foo"; > Won't work. Unlike a pointer to a numerical type. Pointers to numerical types don't let you make type mistakes either. "foo" is not a C string - it is a string literal. Neither a string literal not a C string is a specific type in C. > In C++, the std::string manages memory internally, so you can have this convenience. C++ has a real standard string type, rather than just a defined concept as in C. And it has a lot of useful features - it is a higher level concept that C strings. > The cost is that you lose control of the run time operations used to manage the > memory. In C++, std::string is a convenience shortcut for a specific instantiation of the std::basic_string template. If you want to have a string type with specific control of memory management, you can instantiate the template with your own choice of allocator function. |
Muttley@dastardlyhq.com: Jan 23 09:25AM On Sat, 21 Jan 2023 20:15:39 +0200 >> inefficient substr() etc. >If you want to speed up substring processing, then there is >std::string_view for you. As fast as plain pointers and much cleaner. Not really. This is fast, simple and clear: for(p=str;*p;) { switch(*p) { case '[': p = parseList(p+1); break; case '{': p = parseBlock(p+1); break; case '(': p = parseArray(p+1); break; default: <do something else> ++p; } } Not sure how using indexes and substrings would improve it. |
Muttley@dastardlyhq.com: Jan 23 09:30AM On Sat, 21 Jan 2023 19:30:48 +0100 > hw.resize( 5 ); > return hw; >} char *hw = "hello world!"; : return hw + 5; |
David Brown <david.brown@hesbynett.no>: Jan 23 10:33AM +0100 On 23/01/2023 08:04, R.Wieser wrote: >> that is recognized by many standard library functions. > The famous "C string", non terminated but instead with its length stored > before the first character. C strings are, by definition, always terminated - if they are not terminated, they are not strings. And any length indicator is not part of the string. What you are describing here sounds more like what is known as a "Pascal-style string", because it is the common format for variable length short strings in Pascal. (Typical Pascal implementations can support other string formats too, including fixed length formats, "long" strings with 32-bit length indicators at the start, C-style strings, and maybe others.) |
Paavo Helde <eesnimi@osa.pri.ee>: Jan 23 12:11PM +0200 > } > } > Not sure how using indexes and substrings would improve it. This looks like it either assumes the string is syntactically correct (all parens are balanced correctly) or the parsed string is terminated by a null byte. So when parsing a substring of some larger text or binary file I would need to copy it out and append a null byte, just to be sure my error detection works properly. When using string_view, you always know how long your to-be-processed piece is, so you don't need to make pointless copies just to know where to stop processing. With raw pointers, you would need to pass a separate end pointer, which would make the interfaces more complex. |
Muttley@dastardlyhq.com: Jan 23 10:14AM On Mon, 23 Jan 2023 12:11:40 +0200 >This looks like it either assumes the string is syntactically correct >(all parens are balanced correctly) or the parsed string is terminated >by a null byte. So when parsing a substring of some larger text or Or the given function works up to the matching close bracket and returns the pointer to that + 1. In a real parser this would be in a recursive function because of nested blocks/lists etc. >be sure my error detection works properly. >When using string_view, you always know how long your to-be-processed >piece is, so you don't need to make pointless copies just to know where Your to-be-processed piece will be the entire program/text to be parsed at the start. >to stop processing. With raw pointers, you would need to pass a separate >end pointer, which would make the interfaces more complex. I think we can assume you've never written a parser and leave it at that. |
Paavo Helde <eesnimi@osa.pri.ee>: Jan 23 12:49PM +0200 23.01.2023 08:34 Juha Nieminen kirjutas: > dynamically allocated and doesn't support statically allocated > strings (which is the very reason why std::string_view was created, > to support that very thing). Maybe you meant "dynamically initialized", not "dynamically allocated"? AFAIK there is no guarantee a std::string would always involve dynamic allocation, and with short strings it often does not. Dynamic initialization might indeed be a problem because in C++ the order of global statics initialization is not very well determined, and there is a danger to access the object before its creation or after its destruction. But strictly speaking, this is a problem with dynamic initialization, not dynamic allocation (although it might be the allocation step which is failing). > where avoiding it does introduce a significant benefit it's good > to have the alternative. Especially if all you need to handle the > data is a pointer (and thus std::string_view would be overkill). It's true that when striving for max performance, using C-style strings might sometimes have benefits. I myself have coded large global C-style arrays containing C-style string constants, sorted by hand for faster lookup at run time. However, the OP claims he is novice in C++, aiming for a simple solution, so he should not deal with such nuances before he has got some years of experience under his belt. |
Juha Nieminen <nospam@thanks.invalid>: Jan 23 11:51AM > Maybe you meant "dynamically initialized", not "dynamically allocated"? > AFAIK there is no guarantee a std::string would always involve dynamic > allocation, and with short strings it often does not. Short string optimization is not guaranteed by the standard and, thus, you cannot rely on it. Additionally, even when it is implemented, you have no way of controlling how large the "short" string is (which would actually be a nice feature; I believe Boost has "short" data optimizing containers where you can actually determine the size of that "short data". But alas, that's not standard.) Even more additionally, if short string optimization is implemented, you pay the price of having an additional conditional on each single access and operation you do to the string, whether you want it or not (there's no way to turn it off if you wanted to). Sure, in most situations this additional conditional is inconsequential, but in those situations where you need to squeeze the last clock cycle out of your code you will be paying the price. I would even go as far as saying that it would be better if implementations *don't* use short string optimization, because then you get a consistent guaranteed behavior without surprising side effects (in terms of performance). A "short (whatever) optimizing" data container should be its own thing (like in Boost). > destruction. But strictly speaking, this is a problem with dynamic > initialization, not dynamic allocation (although it might be the > allocation step which is failing). Dynamic memory allocation is slow (relatively speaking) and causes other optimization problems such as memory fragmentation. In most situations this is inconsequential but, as mentioned, when you need to squeeze the last clock cycles out of the code... > lookup at run time. However, the OP claims he is novice in C++, aiming > for a simple solution, so he should not deal with such nuances before he > has got some years of experience under his belt. Novice or not, I think it's not good advise to just say "forget about C style strings, they are completely obsolete and not to be used". Perhaps something more along the lines of: "It's better to just use std::string in this case. It's much easier and much safer, and offers a lot more features." |
Malcolm McLean <malcolm.arthur.mclean@gmail.com>: Jan 23 04:05AM -0800 On Monday, 23 January 2023 at 11:52:01 UTC, Juha Nieminen wrote: > Perhaps something more along the lines of: "It's better to just use > std::string in this case. It's much easier and much safer, and offers > a lot more features." It's often easier to construct a string in a C style buffer, and easier to parse. But std::strings can be copied and assigned. So it's much easier to pass the strings around. Most strings in most programs are quite short, and execution time and memory use isn't very relevant. |
Paavo Helde <eesnimi@osa.pri.ee>: Jan 23 02:14PM +0200 >> by a null byte. So when parsing a substring of some larger text or > Or the given function works up to the matching close bracket and returns > the pointer to that + 1. This is relying on the often-not-so-guaranteed assumption the string is syntactically correct and actually contains this matching close bracket - that's what I wrote. [...] > I think we can assume you've never written a parser and leave it at that. You can assume what you like. Meanwhile, I have written my part of pointer-based parsers and now switching over to string_view. |
jak <nospam@please.ty>: Jan 23 01:22PM +0100 Il 23/01/2023 09:46, David Brown ha scritto: > (C++ standards are a bit more complicated than C standards, since there > are bigger differences between the versions, but the same principles > apply.) hi David, I have read your comments on these groups for a few years and I have an excellent opinion about you but this time I have the impression that you have read this branch of the thread with poor attention. Please read more carefully the statement I replied. Always with respect, Jak. |
Muttley@dastardlyhq.com: Jan 23 12:27PM On Mon, 23 Jan 2023 14:14:26 +0200 >This is relying on the often-not-so-guaranteed assumption the string is >syntactically correct and actually contains this matching close bracket >- that's what I wrote. If its not correct the parser throws an error. Thats what parsers do. >> I think we can assume you've never written a parser and leave it at that. >You can assume what you like. Meanwhile, I have written my part of >pointer-based parsers and now switching over to string_view. If you say so. Another reason to use char* is that a lot of parsers will memory map a file R/W and MAP_PRIVATE which gives you a char* pointing to the beginning of the file and which you can manipulate as you see fit. |
wij <wyniijj5@gmail.com>: Jan 23 04:45AM -0800 On Monday, January 23, 2023 at 7:52:01 PM UTC+8, Juha Nieminen wrote: > Perhaps something more along the lines of: "It's better to just use > std::string in this case. It's much easier and much safer, and offers > a lot more features." c-string or std::string are library (implementing) stuff, not really The language. C/C++ just says any character sequence ending with 0 is a string. struct AA { char aa[33]; AA() { aa[32]=0; }; } aa; AA* ptr=&aa; // (char*)ptr points to a string? 'string' is human question, not the CPU's problem. For commercial programs, I would select QString (and QCString). I also have my String, no string class is generally better. So, in the end, it is still c-string. OS demands c-string. |
Bonita Montero <Bonita.Montero@gmail.com>: Jan 23 01:53PM +0100 > char *hw = "hello world!"; > : > return hw + 5; You're returning a newly created string object, thereby inducing the issue a second allocation Muttley@dastardlyhq.com mentioned. In this case this might not make a difference due to the short string optimizations, in others this might be a peformance pro- blem. And you're returning the exclamation mark I also stripped. |
David Brown <david.brown@hesbynett.no>: Jan 23 02:42PM +0100 On 23/01/2023 13:22, jak wrote: >>> Il 22/01/2023 19:04, jak ha scritto: >>>> Il 22/01/2023 13:53, Paavo Helde ha scritto: >>>>> 22.01.2023 14:23 jak kirjutas: <snip> >>>>>> strings but only an agreement that allows the functions to use >>>>>> array as >>>>>> strings. <snip> > have read this branch of the thread with poor attention. Please read > more carefully the statement I replied. > Always with respect, Jak. Then let me be sure we are discussing the same thing, and there are no misunderstandings. I've cut out all except the most relevant quotation from your posts in this branch. You claimed that C does not have strings, and when given a direct reference to the definition of strings in the C standard, you claimed that the standards do not determine what the C language is, and the standards should be changed to remove the definition of strings, since in your opinion they do not exist in the language. Is that correct? I tried to explain that the C language standards /do/ define the language. Do you still deny that? If so, how do /you/ think the language is defined? Have you now looked at the standards and read for yourself how "strings" are define in the standards? Have you looked at the other uses of the word "string" in the standard, including "string literal", "pointer to a string", and the "<string.h>" header and functions? C's concept of a string is different from (and more low-level and primitive than) that found in many other programming languages. But that does not mean C does not have strings, defined in the standards and as part of the language and standard library. |
Muttley@dastardlyhq.com: Jan 23 09:34AM On Sun, 22 Jan 2023 13:33:37 +0100 >> unrelated group which somehow ends up quoting me and being coincidentally >> crossposted to comp.lang.c++. >I will say it again - it appears to be the result of a server glitch. I will say it again - it is the CLIENT that does the quoting of the "From:" field NOT the server. The original post I saw DID NOT have my name in that field. >It may only have been visible in one server, it may have been passed on >to some other servers but not all servers. Some people (such as myself, >and Bonita) saw the original broken and header-jumbled cross post. And my id was in this jumbled header was it? >Others did not. Bonita replied to this mistaken cross-post, thinking it >was real. It is not actually that hard to understand, and does not need >paranoia or conspiracy theories as an explanation. She didn't reply, she effectivlty reposted it with no comments. Why would she do that? >> someone hacked her account. The fact that she's vanished from this group for >> a few days when she normally never stays away is rather telling. >Please stop. Not until she explains herself. Little sign of that so far. >But trust me on this, you are not that important. No one - not Bonita, >not anyone else - is going to hack a Usenet server to make a fake Why would she need to hack it? Do even you understand how usenet works? |
David Brown <david.brown@hesbynett.no>: Jan 23 02:29PM +0100 > I will say it again - it is the CLIENT that does the quoting of the "From:" > field NOT the server. The original post I saw DID NOT have my name in that > field. You can say it as many times as you want - you are merely describing how things are /supposed/ to work. This was the result of a server fault that scrambled a post. We /know/ you did not write the post. We /know/ that many people saw a post in this newsgroup with /your/ name in the "From" field. Somewhere, a Usenet server screwed up - the "From" field, along with the newsgroup(s), threading, and perhaps other fields, from one real post in a real c.l.c++ thread was mixed with the message content from a completely unrelated post in an unrelated group. The fact that the post /you/ saw did not appear to come from you, merely re-enforces the server glitch theory - different people saw different things on different Usenet servers. >> to some other servers but not all servers. Some people (such as myself, >> and Bonita) saw the original broken and header-jumbled cross post. > And my id was in this jumbled header was it? Yes. >> paranoia or conspiracy theories as an explanation. > She didn't reply, she effectivlty reposted it with no comments. Why would she > do that? In Usenet terms, she replied to the post. In stereotypical google poster fashion, she did so by top-posting a single comment and quoting the entire original message (as she saw it on her newsserver). Why do some people repost entire messages just to tell others that it is spam or make other single-line comments? I don't know. I can try to explain what she saw on her server, but I won't attempt to explain her thought processes! >>> a few days when she normally never stays away is rather telling. >> Please stop. > Not until she explains herself. Little sign of that so far. I can't answer for her. For all I know, she's off on holiday somewhere. But I can certainly understand why she might not want to respond to someone who is making wild paranoid accusations without justification, and contrary to the evidence and explanations received. I can appreciate that you were confused initially - we all were, since the post was not a normal Usenet post and was not visible on all servers, giving different people a very different view. But you should know better now. >> But trust me on this, you are not that important. No one - not Bonita, >> not anyone else - is going to hack a Usenet server to make a fake > Why would she need to hack it? Do even you understand how usenet works? Yes, I do. I know how to make fake posts, and how they work - and I know this was /not/ a fake post. Making a post whose headers contain only one group, but which appear in another group, is not a simple fake. Basically, the header download from one or more newsservers (at least news.eternal-september.org) differed completely from the headers in the content of the message. You can't fake that, since it is (obviously) not supported by the NNTP protocols. Either it is a sophisticated hack - and that is not realistic - or it was the result of a server glitch. |
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jan 22 09:04PM -0800 On 5/12/2022 12:16 PM, Chris M. Thomasson wrote: > Using my experimental vector field to generate a fractal formation. Here > is generation two: > https://fractalforums.org/gallery/1612-120522191048.png A special way to iterate escape time fractals. One of my friends named it the Mulia, short for Mutated Julia. https://fractalforums.org/gallery/1612-220123205518.jpeg |
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