- What is the data structure of a NULL? - 8 Updates
- Don't be fooled by cpp.sh - 12 Updates
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Dec 31 05:26PM On Tue, 31 Dec 2019 10:46:30 -0600 > Öö Tiib wrote: [snip] > > It does not say that bit-wise checks are made, > If NULL == 0, bitwise checks aren't required, just a check of the > Z flag of the register that received the return. 'NULL == 0' will always evaluate to true, by virtue of the definition of NULL. The bit pattern of the integer literal 0 as null pointer constant may be different from its bit pattern as an integer, so your check is meaningless. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Dec 31 10:27AM -0800 Ned Latham wrote: > I don't know why you haven't already got it. If NULL == 0 the same > logic can be used with pointers as with integers and all their bitwidth > lookalikes and all the functions that require or return those types. NULL is absolutely guaranteed to compare equal to 0 when using any conforming implementation of C++, regardless of how null pointers are represented. That's because NULL is required to expand into a null pointer constant (21.2.3p2). 7.11p1 allows for only two possibilities for a null pointer constant. The first is that it can be an "integer literal with a value of zero", which obviously compares equal to 0. The second is that it can be "a prvalue of type std::nullptr_t". Since the 0 it's being compared with also qualifies as a null pointer constant, they necessarily compare equal (8.10p4). Therefore, checking whether NULL==0 doesn't give you any information about whether an implementation has null pointers with all bits set to zero. This matters if you've made the mistake of relying on things like calloc() or memset(0) to fill pointer objects with representations of null pointers. On the flip side, it's not a problem if you're relying on zero-initialization, since zero-initialization of a pointer is guaranteed to give it a valid representation of a null pointer(11.6p6, 7.11p1), even if that representation doesn't have all bits 0. > Tests like > if (!(array=calloc(hemeny,sizeof(arrayrcrd)))) // then deal with OOM. > wouldn't work correctly otherwise. Yes they will. Clause 8.3.1p9 says "The operand of the logical negation operator ! is contextually converted to bool (Clause 7); its value is true if the converted operand is false and false otherwise. The type of the result is bool." 7.14p1 describes the results of converting values to bool. It says that "A ... null pointer value ... is converted to false ...". That's true, regardless of how null pointers are represented. Therefore, this code does precisely what it's supposed to do, regardless of that representation. Note that this also applies to if(array). In all statements that contain a condition (other than switch), the condition is "... contextually converted to bool ..." (9p4). All null pointers, regardless of how they are represented, convert to a bool value of false, so using a pointer as a condition always handles null pointer values the way you'd expect, even if the representation of null values is not what you'd expect |
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Dec 31 11:11AM -0800 Chris Vine <chris@cvine--nospam--.freeserve.co.uk> writes: [...] > You have a point so far as concerns, say, memset'ing structs of > trivial type to all-bits-zero where those structs contain pointers > which you want to be NULL (should your code actually do that). But you null, not NULL. > pointer constant if calloc fails, and the test for falsity will work > correctly irrespective of whether the null pointer constant is > signalled by all-bits-zero. 'array' will be a null pointer, not a null pointer constant. A *null pointer constant* is a source code construct (and NULL is a macro that expands to a null pointer constant). A *null pointer* is a value that can exist at run time. It's probably OK in most cases to use the term "NULL" to refer to a null pointer value, but in this case the distinction is a large part of what we're talking about, so I suggest being a bit more pedantic than usual. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com [Note updated email address] Working, but not speaking, for Philips Healthcare void Void(void) { Void(); } /* The recursive call of the void */ |
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Dec 31 11:20AM -0800 David Brown <david.brown@hesbynett.no> writes: [...] > than, say, "((void*) 0)". > It is not in any way dependent on the representation of null pointers, > as you probably know. In C, NULL can be defined as 0 or as ((void*)0). In C++, ((void*)0) is not a valid definition of NULL, because C++'s definition of "null pointer constant" is more strict than C's. A *null pointer constant* is an integer literal with value zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type; the result is the *null pointer value* of that type and is distinguishable from every other value of object pointer or function pointer type. (In C++11 and earlier, a integral constant expression with value 0 could be a null pointer constant, but C++14 restricted this to integer literals. ((void*)0) hasn't been a valid C++ null pointer constant going back at least to C++98.) But yes, NULL might be usable in a context that requires an integer value depending on how the implementation defines it. Of course it would be silly to depend on that. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com [Note updated email address] Working, but not speaking, for Philips Healthcare void Void(void) { Void(); } /* The recursive call of the void */ |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Dec 31 07:47PM On Tue, 31 Dec 2019 11:11:17 -0800 > > trivial type to all-bits-zero where those structs contain pointers > > which you want to be NULL (should your code actually do that). But you > null, not NULL. I think you mean that "hold a null pointer value" should replace "be NULL". If so, I don't object although I think the meaning is clear enough and you are being somewhat on the pedantic side. > A *null pointer constant* is a source code construct (and NULL is a > macro that expands to a null pointer constant). A *null pointer* is a > value that can exist at run time. I agree, clumsy language - for one thing, 'array' is neither a constant nor a literal. As you say, I meant that 'array' will hold a null pointer value. I doubt anyone misunderstood me however. |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Dec 31 09:37PM On Tue, 2019-12-31, Ned Latham wrote: >> except that this does not compiles. Imlicit conversion of int to pointer >> is not done... > Ok. if ((void*)(i - j) == NULL) // then do whatever. Then rewrite it as if (i==j) and that reason to know extra things about null pointers disappears. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Dec 31 09:54PM On Mon, 2019-12-30, Öö Tiib wrote: > actual defects (in non-trivial code on about 50% of cases IME). So > in review I typically request unit tests and static asserts about > platform-specific assumptions instead of rewrite. Thanks -- a sane and useful posting in this thread, at last. (Other postings have been sane, but not useful. Including mine.) I'm going to stop reading now, so my last Usenet read of 2019 is a good one. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
James Kuyper <jameskuyper@alumni.caltech.edu>: Dec 31 03:21PM -0800 Ned Latham wrote: > Ok. if ((void*)(i - j) == NULL) > // then do whatever. Were you under the impression that the left hand side of that comparison was required to be a null pointer value when i==j? There is no such requirement. The requirement you're probably thinking is 7.11p1, but that only applies to integer literals with a value of zero. (i - j) is not an integer literal. Note that even if it does result in a null pointer value, the behavior would still not depend upon representation of null pointer values. NULL is required to expand to a null pointer constant, and the comparison causes it to be converted to void*, resulting in a null pointer value. All null pointer values are required to compare equal, regardless of how they are represented. In any event, what did you expect this line of code to do that couldn't be done more simply and portable by writing if(i == j)? |
David Brown <david.brown@hesbynett.no>: Dec 31 06:22PM +0100 On 31/12/2019 18:00, Bonita Montero wrote: >> Are you kidding? -Wall is one of the most basic options one always >> uses with gcc (together with -Wextra and a bunch of other warning flags). > -Wall includes useful als well as rather useless child-proof locks. Would you like to give some examples? (I realise this will require you to actually look something up, instead of making up your arguments as you go along.) |
Bonita Montero <Bonita.Montero@gmail.com>: Dec 31 06:35PM +0100 >> That's your personal taste and not C++. > What part of "the compiler and flags that I use" made you think it was > something other than my personal choice? Those which make every warning an error; that's very uncommon and nerdish. >> kind of aliasing. > Yes, it matters - it matters to people that want to write correct code, > and not "I know this is crap, but it worked when I tried it" code. The code I have shown works with any compiler. > What you wrote is not particularly common, I think. You think that yout habits are the center of the world. > Right... > That's because compilers implement C++ based on "Bonita says so" > rules rather than the standards. I'll bear that in mind. No, what I wrot is simply common because it is very convenient over having a union. |
Bonita Montero <Bonita.Montero@gmail.com>: Dec 31 06:46PM +0100 > Would you like to give some examples? (I realise this will require you > to actually look something up, instead of making up your arguments as > you go along.) There are not much, but these are useless: -Wcomment It's not rare that you first comment out a part with // and then the outer block with /* */. This isn't really a problem. -Wenum-compare Unscoped enums are in the same namespace so they should be all comparable. -Wmissing-braces That's really a useless aesthetic warning. -Wreorder It's very rare that the order of initialization-calls counts. -Wunused-function This would be disturbing if you would have the function in the code for a later purpose. But I agree that the vast majority of -Wall-warnings makes sense. |
David Brown <david.brown@hesbynett.no>: Dec 31 06:51PM +0100 On 31/12/2019 18:35, Bonita Montero wrote: >> something other than my personal choice? > Those which make every warning an error; that's very uncommon > and nerdish. I simply don't think you have experience with quality programming. Some people write code where bugs are not acceptable. There are many things required in a development process to achieve a zero bugs (or at least, as low a chance of bugs as achievable in the time and resource budget). Heavy use of compiler warnings, and a zero-warning build policy, is a simple, cheap and commonly used part of that. (Not all code is developed to such standards, of course - otherwise software would be ridiculously expensive in many cases.) >> Yes, it matters - it matters to people that want to write correct >> code, and not "I know this is crap, but it worked when I tried it" code. > The code I have shown works with any compiler. A "C++ implementation" covers the compiler, library and choice of flags and options. Sure, the compiler I use could be made to accept the code you wrote - but not with the flags I require. >> What you wrote is not particularly common, I think. > You think that yout habits are the center of the world. No, I think they are /my/ habits. Some of them are common, some are uncommon. Some are common in the branch I work in but uncommon in more general programming. (I find comparisons between different types of programming arenas to be an interesting topic in these newsgroups.) I don't think casts like yours are common in any area of programming. I could be wrong here, of course, but that is what I think. If people whose opinion I respect tell me otherwise, I may change that opinion - but it is usually extremely difficult to get an idea of what techniques are common or rare in C++ programming "in general". >> rules rather than the standards. I'll bear that in mind. > No, what I wrot is simply common because it is very convenient > over having a union. Look, the common way of writing the code in question is not to faff around with casts /or/ unions - you write "if (x < 0)". And people who are concerned with accurate IEEE floating point, and careful handling of NaNs and the rest of it, will write "if (signbit(x))". Almost the only people who care about the representation details of the floating point types are the ones /implementing/ such functions or macros - and they can rely on whatever compiler-specific features they want. |
Bonita Montero <Bonita.Montero@gmail.com>: Dec 31 06:59PM +0100 > I simply don't think you have experience with quality programming. Your quality-programming is not a matter of maintainability or if the code is de-facto guaranteed to work but partitially an aesthetic baublery. > Some people write code where bugs are not acceptable. What I showed works with any compiler. |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Dec 31 06:14PM On Tue, 31 Dec 2019 16:13:57 +0000 (UTC) > If you don't know what type you'll have at a given point in code then > that is what templates were invented for. They're also more flexible than > variants. First, the purpose of variants is not to provide an alternative to templates for polymorphic code. Their main purpose is to allow values of a limited set of alternative types to be passed in a type safe way. Secondly, variants are constructed from templates. Templates are not "more flexible than variants": they are different things. Variants test the contained type within the permitted set of types at run time by reference to an index or tag; templates discriminate their types at compile time (which includes trying to instantiate a variant with a type not within its permitted variant set, which will give a compile time error). > >avoid the responsibility of creating, tracking and destroying them. > No true. Unless you use the visit() horror then you need to know the index > position or type of what you want to access. If you need to interrogate the variant at run time to find out what it holds you can use std::variant::index (std::holds_alternative and std::get_if are also available). But in almost all real-life cases, you want to use std::visit. You have an astonishing lack of knowledge about C++. Almost everything you post is wrong. |
Bonita Montero <Bonita.Montero@gmail.com>: Dec 31 07:16PM +0100 > compile time (which includes trying to instantiate a variant with a > type not within its permitted variant set, which will give a compile > time error). Is this a nonsense-pettifogging-contest here? |
Paavo Helde <myfirstname@osa.pri.ee>: Dec 31 08:30PM +0200 On 31.12.2019 19:46, Bonita Montero wrote: > -Wcomment > It's not rare that you first comment out a part with // and > then the outer block with /* */. This isn't really a problem. Your description does not match what this warning is doing. It warns about /* inside /*. Usually it is easy to fix, replace inner /* with //. > -Wenum-compare > Unscoped enums are in the same namespace so they should be > all comparable. I think this is a really useful comment. If I have mixed up my enums I would want to know that. > -Wmissing-braces > That's really a useless aesthetic warning. Never seen that warning. Probably because I take care to write my initializers. > -Wreorder > It's very rare that the order of initialization-calls counts. This is the only one which I agree with. It should not warn if the initializer is a constant expression, at least. > -Wunused-function > This would be disturbing if you would have the function in the > code for a later purpose. So you are checking in untested code. > But I agree that the vast majority of -Wall-warnings makes sense. ok |
Bonita Montero <Bonita.Montero@gmail.com>: Dec 31 07:44PM +0100 >> all comparable. > I think this is a really useful comment. If I have mixed up my enums I > would want to know that. That's a child-proof lock. >> That's really a useless aesthetic warning. > Never seen that warning. Probably because I take care to write my > initializers. It's rare but useless. >> This would be disturbing if you would have the function in the >> code for a later purpose. > So you are checking in untested code. I'll check it later and that's quite ok. |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Dec 31 06:48PM On Tue, 31 Dec 2019 19:16:50 +0100 > > type not within its permitted variant set, which will give a compile > > time error). > Is this a nonsense-pettifogging-contest here? So you really think that "If you don't know what type you'll have at a given point in code then that is what templates were invented for. They're also more flexible than variants" is an accurate discription of the purpose of variants and templates. If so, you are as clueless as Boltar. Have you ever used discriminated unions in your programming life? (Clearly Boltar hasn't) |
"Öö Tiib" <ootiib@hot.ee>: Dec 31 12:23PM -0800 On Tuesday, 31 December 2019 19:36:08 UTC+2, Bonita Montero wrote: > > something other than my personal choice? > Those which make every warning an error; that's very uncommon > and nerdish. People with infantile reactions how rules of project they join are so very "uncommon" and "nerdish" are soon back on streets searching for project with more "common" and "dumboish" rules. |
Daniel <danielaparker@gmail.com>: Dec 31 12:29PM -0800 On Tuesday, December 31, 2019 at 1:48:50 PM UTC-5, Chris Vine wrote: > > > run time by reference to an index or tag > > Is this a nonsense-pettifogging-contest here? > So you really think that <quote from bol...> I think Bonita is permitted to question your wording in the quote above, without a suggestion that that implies bol...'s position :-) Daniel |
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. |