Worrying C/C++ skills



  • Whenever I wonder if I'm a decent C/C++ programmer, I just need to look around some programming websites.

    This is one which really had me wondering if this was a new trick I should have known - then I realised - no, it wasn't...

    As an example.

    To allocate a block of memory to store a copy of a string in, we should all use:

    char *ptr = new char[strlen(sourcestring) * sizeof(char *)];

    This is OK 'because sizeof(char *) is always 1'. Also, you should use 'new' rather than 'malloc' because 'new' will manage the memory allocation & freeing for you, so you won't get memory leaks.

    I certainly wish I'd known that trick.

    I've been living with the misconception for years that:

    • sizeof(char *) is probably either 4 or 8, but pretty certainly not '1' (except on computers with 256 or fewer bytes of memory)
    • strlen(string) is the length of the string. For storing a string in a C character array, you need 1 extra byte (in this case, probably not an problem, except for empty strings, because of the massive overallocation caused by the previous issue)
    • I always thought a 'new' should have a matching 'delete'. I could have saved so much typing and thinking if I'd known that 'new' managed the memory for you.

    So, I feel humbled by the superior knowledge of the people on these forums.

    (It's just slightly worrying that this is from a forum for people using IBM's DataStage, which is a thing for high performance handling of large databases. So, these people could well be working for your bank, or health service or government)



  • How about this "tutorial":

    @dipshitx said:

    Because a pointer by defining is a reference to the address where a variable resides, when a function is defined as returning a pointer, you can also return a reference to the appropriate type. Here is an example:

    double * GetSalary()
    {
        double salary = 26.48; 
    
        return &salary;
    }

    But am I supposed to free this memory or not? He didn't call new, so I'm not sure it's managed for me!



  • @pscs said:

    strlen(string) is the length of the string. For storing a string in a C character array, you need 1 extra byte (in this case, probably not an problem, except for empty strings, because of the massive overallocation caused by the previous issue)
     

    You just allocate 4 or 8 times the needed memory. No harm done. It is also good, because the coder forgot to include space for the trailing '/0', the fact that he allocaes at least 3 more bytes that he'll use fixes that.

    @pscs said:

    I always thought a 'new' should have a matching 'delete'. I could have saved so much typing and thinking if I'd known that 'new' managed the memory for you.

    There are garbage collectors that will act on memory allocated by 'new', but not by 'malloc'. Somehow, I doubt the poster of that explanation knew enough to think about that... But those things exist. 

     

     



  • @Enterprise Architect said:

    How about this "tutorial":

    @dipshitx said:

    Because a pointer by defining is a reference to the address where a variable resides, when a function is defined as returning a pointer, you can also return a reference to the appropriate type. Here is an example:

    double * GetSalary()
    {
        double salary = 26.48; 
    
    return &salary;
    

    }

    But am I supposed to free this memory or not? He didn't call new, so I'm not sure it's managed for me!

     

    Wow that is an impressive number of errors in such a small text. It really looks like the author is confused about the difference between a pointer and a referance.

     



  • Oh my god. That tutorial is scary. Who are the guys writing tutorials about c++ without even understanding the concept of pointers and referances?

     



  • @mt@ilovefactory.com said:

    Oh my god. That tutorial is scary. Who are the guys writing tutorials about c++ without even understanding the concept of pointers and referances?

     

    It's very easy to do when your only programming knowledge is JScript and tiny bits of VB6 you learned from reading a book from 1987.


    Even easier if your only programming knowledge is HTML 3



  • Don't worry about having to free the local variable when returning a pointer to it, the language will free the variable for you. Just remember to never dereference the pointer since it is guaranteed to always point to deallocated stack memory.



  • @mt@ilovefactory.com said:

    @Enterprise Architect said:
    How about this "tutorial":

    @dipshitx said:

    Because a pointer by defining is a reference to the address where a variable resides, when a function is defined as returning a pointer, you can also return a reference to the appropriate type. Here is an example:

    double * GetSalary()
    {
        double salary = 26.48; 
    
    return &salary;
    

    }

    But am I supposed to free this memory or not? He didn't call new, so I'm not sure it's managed for me!

    Wow that is an impressive number of errors in such a small text. It really looks like the author is confused about the difference between a pointer and a referance.
     

    IMHO the worst flaw is that he is returning a pointer to memory that is part of the stack. Next time any function is called that will be overwritten with garbage. Yes, I know this because years ago I did it.

     

     



  • @henke37 said:

    Don't worry about having to free the local variable when returning a pointer to it, the language will free the variable for you. Just remember to never dereference the pointer since it is guaranteed to always point to deallocated stack memory.

    Someone really should finally implement summoning daemons out of programmer's nose in the compiler.



  • @pscs said:

    http://www.dsxchange.com/viewtopic.php?t=126804&postdays=0&postorder=asc&start=15

    The biggest problem is their rating system. It goes from "offtopic/superfluous" over various levels of "helpful" to "solved my problem", but for threads like this it would really need "totally wrong, please ban this user from ever responding again".



  • Could be another of Bjarne's little pranks.



  • @Mcoder said:

    You just allocate 4 or 8 times the needed memory. No harm done. It is also good, because the coder forgot to include space for the trailing '/0', the fact that he allocaes at least 3 more bytes that he'll use fixes that.

    Unless you pass in an empty string...

    @Mcoder said:

    There are garbage collectors that will act on memory allocated by 'new', but not by 'malloc'. Somehow, I doubt the poster of that explanation knew enough to think about that... But those things exist. 

    But not in this environment AFAICT - you write DLLs (actually '.so's) which IBM's "super" (but very badly documented and/or designed) system calls when it feels like it. Your DLL uses whichever memory allocator it feels like. The DLL can be written in either C or C++, so requiring 'new' would be impossible.

    (the DataStage system seems to be fundamentally flawed as far as we can tell - you have to return "char *"s, but there's no way of freeing "malloc"ed memory, and it's multi-threaded so you shouldn't use statics. (The only 'simple' solution would be return stack variables and 'hope' that they get copied before they're overwritten. A more complex "solution" would be to write your own memory manager with a time based de-allocator, and assume that the returned variables can be deleted after a certain amount of time). All the suggestions on the forums either have memory leaks or potential overwrite situations. And 90% of the people on the forums don't even seem to realise!)



  • @pscs said:

    I've been living with the misconception for years that:

     

    • sizeof(char *) is probably either 4 or 8, but pretty certainly not '1' (except on computers with 256 or fewer bytes of memory)

    It's also 1 on a typical DSP. Most of the more recent ones can't address anything less than 32 bits of memory, so CHAR_BIT == 1, sizeof(char) == sizeof(char*) == sizeof(int) == sizeof(float) == 32. (And doubles and long longs would have a sizeof 2.) This complies with the C standard, but not the POSIX standard.

    DSPs tend to be very bad at pointer handling (apart from indexing into an array) and string manipulation anyway. It's not really what they're designed for.

     


  • Discourse touched me in a no-no place

    @ais523 said:

    @pscs said:

    I've been living with the misconception for years that:

     

    • sizeof(char *) is probably either 4 or 8, but pretty certainly not '1' (except on computers with 256 or fewer bytes of memory)

    It's also 1 on a typical DSP. Most of the more recent ones can't address anything less than 32 bits of memory, so CHAR_BIT == 1, sizeof(char) == sizeof(char*) == sizeof(int) == sizeof(float) == 32. (And doubles and long longs would have a sizeof 2.) This complies with the C standard, but not the POSIX standard.

    DSPs tend to be very bad at pointer handling (apart from indexing into an array) and string manipulation anyway. It's not really what they're designed for.

     

    No.

    In The Standard sizeof(char) is defined as 1 -always-, not 32. and CHAR_BIT must be at least 8, not one.


  • The code is wrong and your points are valid but not for all the right reasons. In C you use malloc and pointers and call free on it later. In C++ you use std::string, std::vector, shared_ptr, shared_array or whatever.

    There is no such language as C/C++. There is C and there is C++.

     



  • @Enterprise Architect said:

    How about this "tutorial": @dipshitx said:
    Because a pointer by defining is a reference to the address where a variable resides, when a function is defined as returning a pointer, you can also return a reference to the appropriate type. Here is an example:
    double * GetSalary()
    {
    double salary = 26.48;

    return &salary;
    

    }

    But am I supposed to free this memory or not? He didn't call new, so I'm not sure it's managed for me!

    This code will compile in both C and C++ and in both cases will return the address of a local (stack) variable and therefore is undefined behaviour if you use the return value. If you don't use the return value there is no actual error (but it's still bad code).

     

     

     



  • @Cbuttius said:

    @Enterprise Architect said:

    How about this "tutorial": @dipshitx said:
    Because a pointer by defining is a reference to the address where a variable resides, when a function is defined as returning a pointer, you can also return a reference to the appropriate type. Here is an example:

    double * GetSalary()
    {
    double salary = 26.48;

    return &salary;
    

    }

    But am I supposed to free this memory or not? He didn't call new, so I'm not sure it's managed for me!

    This code will compile in both C and C++ and in both cases will return the address of a local (stack) variable and therefore is undefined behaviour if you use the return value. If you don't use the return value there is no actual error (but it's still bad code).

    The great part is he manages to get away with it in his final example by immediately dereferencing the pointer, so he lucks out and his variable hasn't been trashed yet.

    The other great part is any decent compiler can generate a warning when you try this. GCC even spits a warning by default: stupid.cc:4: warning: address of local variable ‘salary’ returned



  • @Mcoder said:

    @pscs said:

    strlen(string) is the length of the string. For storing a string in a C character array, you need 1 extra byte (in this case, probably not an problem, except for empty strings, because of the massive overallocation caused by the previous issue)
     

    You just allocate 4 or 8 times the needed memory. No harm done. It is also good, because the coder forgot to include space for the trailing '/0', the fact that he allocaes at least 3 more bytes that he'll use fixes that.


    That's what he said in his initial post. And as he also wrote, and you missed, is that it doesn't work like that on an empty string. Also, it's \0, not /0.

    @Mcoder said:

    @pscs said:

    I always thought a 'new' should have a matching 'delete'. I could have saved so much typing and thinking if I'd known that 'new' managed the memory for you.

    There are garbage collectors that will act on memory allocated by 'new', but not by 'malloc'. Somehow, I doubt the poster of that explanation knew enough to think about that... But those things exist. 

     

     


    Are you talking about special types of garbage collection, such as C++'s unique_ptr (auto_ptr) or shared_ptr? Those work equally well on malloc as they do on new[] (as in, all you need is a custom deallocator). I wonder what kind of extension would provide garbage collection on raw pointers, must be some Visual C++ extension?

    @PJH said:

    @ais523 said:

    @pscs said:

    I've been living with the misconception for years that:

     

    • sizeof(char *) is probably either 4 or 8, but pretty certainly not '1' (except on computers with 256 or fewer bytes of memory)

    It's also 1 on a typical DSP. Most of the more recent ones can't address anything less than 32 bits of memory, so CHAR_BIT == 1, sizeof(char) == sizeof(char*) == sizeof(int) == sizeof(float) == 32. (And doubles and long longs would have a sizeof 2.) This complies with the C standard, but not the POSIX standard.

    DSPs tend to be very bad at pointer handling (apart from indexing into an array) and string manipulation anyway. It's not really what they're designed for.

     

    No.

    In The Standard sizeof(char) is defined as 1 -always-, not 32. and CHAR_BIT must be at least 8, not one.
    True, but maybe he meant sizeof(char) == sizeof(char*) == 1 && CHAR_BIT == 32? That's legal, and would have a 32-bit pointer type.


  • @Mcoder said:

    @pscs said:

    strlen(string) is the length of the string. For storing a string in a C character array, you need 1 extra byte (in this case, probably not an problem, except for empty strings, because of the massive overallocation caused by the previous issue)
     

    You just allocate 4 or 8 times the needed memory. No harm done. It is also good, because the coder forgot to include space for the trailing '/0', the fact that he allocaes at least 3 more bytes that he'll use fixes that.


    That's what he said in his initial post. And as he also wrote, and you missed, is that it doesn't work like that on an empty string. Also, it's \0, not /0.

    @Mcoder said:

    @pscs said:

    I always thought a 'new' should have a matching 'delete'. I could have saved so much typing and thinking if I'd known that 'new' managed the memory for you.

    There are garbage collectors that will act on memory allocated by 'new', but not by 'malloc'. Somehow, I doubt the poster of that explanation knew enough to think about that... But those things exist. 

     

     


    Are you talking about special types of garbage collection, such as C++'s unique_ptr (auto_ptr) or shared_ptr? Those work equally well on malloc as they do on new[] (as in, all you need is a custom deallocator). I wonder what kind of extension would provide garbage collection on raw pointers, must be some Visual C++ extension?

    @PJH said:

    @ais523 said:

    @pscs said:

    I've been living with the misconception for years that:

     

    • sizeof(char *) is probably either 4 or 8, but pretty certainly not '1' (except on computers with 256 or fewer bytes of memory)

    It's also 1 on a typical DSP. Most of the more recent ones can't address anything less than 32 bits of memory, so CHAR_BIT == 1, sizeof(char) == sizeof(char*) == sizeof(int) == sizeof(float) == 32. (And doubles and long longs would have a sizeof 2.) This complies with the C standard, but not the POSIX standard.

    DSPs tend to be very bad at pointer handling (apart from indexing into an array) and string manipulation anyway. It's not really what they're designed for.

     

    No.

    In The Standard sizeof(char) is defined as 1 -always-, not 32. and CHAR_BIT must be at least 8, not one.
    True, but maybe he meant sizeof(char) == sizeof(char*) == 1 && CHAR_BIT == 32? That's legal, and would have a 32-bit pointer type.


  • I was browsing that functionx site a bit more, and here's another classic one:

    Count the number of WTF's. For one, switching from C++ to C# halfway the tutorial. Other than that, too many to name. I do see why his version is better than std::vector, at least this one doesn't need allocations! Except for the object itself, which never gets deallocated.

    That's the second tutorial I've seen from that site... It's impressive.



  • @Cbuttius said:

    There is no such language as C/C++. There is C and there is C++.
    In theory. But in practice, there's plenty of frankencode.



  • @PJH said:

    No.



    In The Standard sizeof(char) is defined as 1 -always-, not 32. and CHAR_BIT must be at least 8, not one.

    You missed the comma.

    sizeof(char) == 1

    sizeof(char *) == 1

    CHAR_BIT == 32



  • @Evo said:

    That's what he said in his initial post. And as he also wrote, and you missed, is that it doesn't work like that on an empty string. Also, it's \0, not /0.
     

    Yep, I know. That'll teach me to not post on TDWTF while drunken.

    @Evo said:

    Are you talking about special types of garbage collection, such as C++'s unique_ptr (auto_ptr) or shared_ptr? Those work equally well on malloc as they do on new[ (as in, all you need is a custom deallocator). I wonder what kind of extension would provide garbage collection on raw pointers, must be some Visual C++ extension?

    No, I was talking exactly about garbage collection on raw pointers. There are extensions that do that floating on the net, I've never actualy used them (if I waned garbage collected memory, I'd be using a more modern language), but they exist. Some overwrite both malloc and new, some just overwrite one of those. They are mostly a mess, but very interesting in an "ivory tower" kind of way.

     



  • @Cbuttius said:

    There is no such language as C/C++. There is C and there is C++.
    Scott Meyers said (in "Effective C++") that C++ was really an amalgam of 4 different languages: C, C++, template C++ and STL. Although you could argue that the STL is really an extension of template C++. However to be conversant in modern C++ you have to know all 4 of these areas.



  • It is because of things like this that the makers of Java and C# did not give programmers pointers.



  • @Anketam said:

    It is because of things like this that the makers of Java and C# did not give programmers pointers.

    They do, they just don't call them pointers, they call them references. But in Java and C#, all your objects have the semantics of a pointer in that you point them to an object, rather than them actually being the object.

    What these language do is throw runtime exceptions if you either try to use a null pointer (and in Java I think the exception is called NullPointerException, although C# called it NullReferenceException), and similarly they protect you with an exception if you do other silly things like go off the bounds of an array.

    Java and C# don't protect you from writing WTF'y code, as the many instances of CodeSOD's in those languages on this site have shown.

     



  • @Cbuttius said:

    @Anketam said:
    It is because of things like this that the makers of Java and C# did not give programmers pointers.
    They do, they just don't call them pointers, they call them references. But in Java and C#, all your objects have the semantics of a pointer in that you point them to an object, rather than them actually being the object.

    You have a really strange way of saying, "I agree." Of course the languages got rid of pointers. Don't confuse the language with the implementation details. Or whatever other pedantic dickweed thing you're trying to do here.

    Note that there's only one way to refer to something in these languages. You can't have an instance, a reference and a pointer, each with some subtle and not so subtle differences.

    @Cbuttius said:
    Java and C# don't protect you from writing WTF'y code, as the many instances of CodeSOD's in those languages on this site have shown.
    They don't prevent you from arguing with straw men, either.


  • @Cbuttius said:

    They do, they just don't call them pointers, they call them references.
     

    ?

    pointers are not references.



  • @ais523 said:

    sizeof(char *) == 1

    My C/C++ isn't that strong, but wouldn't a pointer size of 1 byte mean you're using an OS whose process space only has 256 bytes or less of addressable RAM?  Like a poiner size of 4 means you're using an OS whose process space has 4GiB or less of addressable RAM?

     


  • Discourse touched me in a no-no place

    @powerlord said:

    @ais523 said:

    sizeof(char *) == 1

    My C/C++ isn't that strong, but wouldn't a pointer size of 1 byte mean you're using an OS whose process space only has 256 bytes or less of addressable RAM? 

    Not if you take into account the last line of the post you quoted:@ais523 said:
    CHAR_BIT == 32
    You're presuming a char is always what is colloquially known as a byte which usually has 8 bits. There are/have been some real systems where a char doesn't have 8 bits.



  • @Cbuttius said:

    @Anketam said:

    It is because of things like this that the makers of Java and C# did not give programmers pointers.

    They do

    Agreed, you can use pointers if you so want, in an unsafe code block @Cbuttius said:
    they just don't call them pointers, they call them references.
    No, there is a difference @Cbuttius said:
    Java and C# don't protect you from writing WTF'y code, as the many instances of CodeSOD's in those languages on this site have shown.
    So? @boomzilla said:
    Of course the languages got rid of pointers.
    They didn't, or at least c# didn't, let all praise backward compatibility @boomzilla said:
    You can't have an instance, a reference and a pointer, each with some subtle and not so subtle differences.
    You can't? @dhromed said:
    pointers are not references.
    Agreed


  • @serguey123 said:

    @boomzilla said:
    Of course the languages got rid of pointers.

    They didn't, or at least c# didn't, let all praise backward compatibility

    You're right. I forgot about unsafe code.

    @serguey123 said:

    @boomzilla said:
    You can't have an instance, a reference and a pointer, each with some subtle and not so subtle differences.

    You can't?

    My understanding (after skimming an MSDN page) is that the pointer types are very limited, and that you generally cannot do all of those things (in the sense that they exist in C++) with any old C# object.



  • @boomzilla said:

    Note that there's only one way to refer to something in these languages. You can't have an instance, a reference and a pointer, each with some subtle and not so subtle differences.

    Try C++/CLI sometime. You get instances, managed pointers, native pointers, and C++ references.



  • @serguey123 said:

    @dhromed said:
    pointers are not references.

    Agreed
     

    IMHO, in C++ references are just syntactic sugar for pointers. They're automatically dereferenced and cannot be NULL, but they're inherently the same thing and should produce the same output binary. (Except for debugging/export symbol data)

     



  • I think we need a new language with:

    • no heap
    • no pointers
    • no memory access
    • no functions
    • pointer arithmetic

    That should make the language sufficiently complex and useless to not be misused in a tutorial, and we can work from there.



  • @topspin said:

    IMHO, in C++ references are just syntactic sugar for pointers. They're automatically dereferenced and cannot be NULL, but they're inherently the same thing and should produce the same output binary. (Except for debugging/export symbol data)

    Not exactly.

    #include <iostream>
    using namespace std;
    

    double get_salary() {
    return 1000000;
    }

    int main(int argc, char *argv[ ]) {
    const double &r = get_salary(); // Legal, if pointless
    cout << "Salary: " << r << endl;
    }

    However:

    const double *r = &get_salary(); // Illegal

    See also: GotW #88: A Candidate For the "Most Important const"



  • I guess it depends on the strictness of your definition of "syntactic sugar" (whether you care more about the syntax being similar, or the underlying compiled code being equivalent).



    Yes, this is illegal:

    const double *r = &get_salary(); 

    But this is just fine:

    double tmp = get_salary(); 
    const double *r = &tmp;

    Which, AFAIK (correct me if I'm wrong), is pretty much equivalent to your original example:

    const double &r = get_salary();

    Also, if you feel like using non-standard compound literals, you can get even closer to the original syntax (albeit with a compiler warning):

    const double *r = &(double){get_salary()}; 

    (Not sure if this is a good idea though, to take the address of a temporary object. Might be okay for a simple type like a double....)


  • @CodeSimian said:

    Also, if you feel like using non-standard compound literals, you can get even closer to the original syntax (albeit with a compiler warning):

    const double *r = &(double){get_salary()}; 

    (Not sure if this is a good idea though, to take the address of a temporary object. Might be okay for a simple type like a double....)

    At least with GCC, seems to work for more complex types too:

    #include <iostream>
    #include <string>
    #include <string.h>
    using namespace std;
    

    string get_hello() { return "Hello, world!"; }

    void fustack() {
    char blob[1024];
    memset(blob, 0, 1024);
    }

    int main(int argc, char *argv[ ]) {
    string *hello = &(string){get_hello()};
    fustack();
    cout << *hello << endl;
    }

    Compiled with -O2 -fno-inline.

    It seems to quietly avoid re-adjusting the stack pointer before returning:

    __Z9get_hellov:
    LFB1477:
    	pushq	%rbp	#
    LCFI10:
    	movq	%rsp, %rbp	#,
    LCFI11:
    	movq	%rbx, -16(%rbp)	#,
    LCFI12:
    	movq	%r12, -8(%rbp)	#,
    LCFI13:
    	subq	$32, %rsp	#,
    LCFI14:
    	movq	%rdi, %rbx	# D.30602, <result>
    	leaq	-17(%rbp), %r12	#, tmp68
    	movq	%r12, %rdi	# tmp68,
    	call	__ZNSaIcEC1Ev	#
    	movq	%r12, %rdx	# tmp68,
    	leaq	LC0(%rip), %rsi	#,
    	movq	%rbx, %rdi	# <result>, D.30158
    LEHB0:
    	call	__ZNSsC1EPKcRKSaIcE	#
    LEHE0:
    	movq	%r12, %rdi	# tmp68,
    	call	__ZNSaIcED1Ev	#
    	movq	%rbx, %rax	# <result>, <result>
    	movq	-16(%rbp), %rbx	#,
    	movq	-8(%rbp), %r12	#,
    	leave
    	ret

    Edit: Removed useless garbage about the compiler copying the double to protect it. It's returned in a register anyway. Added example that can't be returned in a register instead.



  • @Anketam said:

    It is because of things like this that the makers of Java and C# did not give programmers pointers.

    C# has pointers... http://msdn.microsoft.com/en-us/library/y31yhkeb(v=vs.110).aspx



  • @boomzilla said:

    My understanding (after skimming an MSDN page) is that the pointer types are very limited

    Compared to C/C++ yes, the idea of Net was to use managed code after all, so unsafe code is discouraged and kept apart
    @boomzilla said:
    you generally cannot do all of those things (in the sense that they exist in C++) with any old C# object.

    You lost me there, buddy
    @topspin said:
    IMHO, in C++ references are just syntactic sugar for pointers.

    I could probably make a car analogy for you.
    @topspin said:
    I'm curious how that reads when I'm sober tomorrow

    Not well



  • @serguey123 said:

    @boomzilla said:
    you generally cannot do all of those things (in the sense that they exist in C++) with any old C# object

    You lost me there, buddy

    @TFM said:


    Pointer types do not inherit from object and no conversions exist between pointer types and object. Also, boxing and unboxing do not support pointers. However, you can convert between different pointer types and between pointer types and integral types.

    ...

    A pointer cannot point to a reference or to a struct that contains references because an object reference can be garbage collected even if a pointer is pointing to it. The GC does not keep track of whether an object is being pointed to by any pointer types.

    IOW, you cannot create a pointer to any old C# object. They seem to exist mainly to help interface with outside libraries, should the need arise. I imagine it was fairly common in the early days, before the .Net ecosystem matured.



  • @PJH said:

    @powerlord said:

    @ais523 said:

    sizeof(char *) == 1

    My C/C++ isn't that strong, but wouldn't a pointer size of 1 byte mean you're using an OS whose process space only has 256 bytes or less of addressable RAM? 

    Not if you take into account the last line of the post you quoted:@ais523 said:
    CHAR_BIT == 32
    You're presuming a char is always what is colloquially known as a byte which usually has 8 bits. There are/have been some real systems where a char doesn't have 8 bits.
     

    I guess I'm confused as to how a [b]pointer to a memory location[/b] can be smaller than size of a 32-bit memory address in a 32-bit x86 program.  Or does C/C++ return something other than the size of the actual pointer when you use sizeof on a pointer?  Because I would think that sizeof(char) and sizeof(char *) should be returning 1 and 4 on an x86 system respectively.



  • @powerlord said:

    I guess I'm confused as to how a pointer to a memory location can be smaller than size of a 32-bit memory address in a 32-bit x86 program.  Or does C/C++ return something other than the size of the actual pointer when you use sizeof on a pointer?  Because I would think that sizeof(char) and sizeof(char *) should be returning 1 and 4 on an x86 system respectively.

    I guess the rest of us are confused about why you brought up x86.


  • Discourse touched me in a no-no place

    @powerlord said:

    @PJH said:

    @powerlord said:

    @ais523 said:

    sizeof(char *) == 1

    My C/C++ isn't that strong, but wouldn't a pointer size of 1 byte mean you're using an OS whose process space only has 256 bytes or less of addressable RAM? 

    Not if you take into account the last line of the post you quoted:@ais523 said:
    CHAR_BIT == 32
    You're presuming a char is always what is colloquially known as a byte which usually has 8 bits. There are/have been some real systems where a char doesn't have 8 bits.
     

    I guess I'm confused as to how a pointer to a memory location can be smaller than size of a 32-bit memory address in a 32-bit x86 program. 

    Given the stuff quoted, it wouldn't be smaller than 32 bits, it would be 32 bits. Which bit of that are you having difficulty with?



  • @PJH said:

    @powerlord said:

    @PJH said:

    @powerlord said:

    @ais523 said:

    sizeof(char *) == 1

    My C/C++ isn't that strong, but wouldn't a pointer size of 1 byte mean you're using an OS whose process space only has 256 bytes or less of addressable RAM? 

    Not if you take into account the last line of the post you quoted:@ais523 said:
    CHAR_BIT == 32
    You're presuming a char is always what is colloquially known as a byte which usually has 8 bits. There are/have been some real systems where a char doesn't have 8 bits.
     

    I guess I'm confused as to how a pointer to a memory location can be smaller than size of a 32-bit memory address in a 32-bit x86 program. 

    Given the stuff quoted, it wouldn't be smaller than 32 bits, it would be 32 bits. Which bit of that are you having difficulty with?
     

    The sizeof(char *) == 1 part... or did you not notice that in the innermost quote?

     



  • @powerlord said:

    @PJH said:

    @powerlord said:

    @PJH said:

    @powerlord said:

    @ais523 said:

    sizeof(char *) == 1

    My C/C++ isn't that strong, but wouldn't a pointer size of 1 byte mean you're using an OS whose process space only has 256 bytes or less of addressable RAM? 

    Not if you take into account the last line of the post you quoted:@ais523 said:
    CHAR_BIT == 32
    You're presuming a char is always what is colloquially known as a byte which usually has 8 bits. There are/have been some real systems where a char doesn't have 8 bits.
     

    I guess I'm confused as to how a pointer to a memory location can be smaller than size of a 32-bit memory address in a 32-bit x86 program. 

    Given the stuff quoted, it wouldn't be smaller than 32 bits, it would be 32 bits. Which bit of that are you having difficulty with?
     

    The sizeof(char *) == 1 part... or did you not notice that in the innermost quote?

    Read the whole quote. Understand the whole quote. Get back to us.


  • Discourse touched me in a no-no place

    @powerlord said:

    The sizeof(char *) == 1 part... or did you not notice that in the innermost quote?
    Yes; you seem to be ignoring the rest of the quotes - specifically the one I re-inserted after you previously removed it.



    If CHAR_BIT[1] is 32, then a 32 pointer can be stored in something the size of a char. Or put another way a char can hold a 32 bit number. Which would be the same size as a pointer in your machine. Why would you store a pointer in something bigger than a char, if a char can store a 32 bit pointer?





    [1] Hint - and I think this is the point you're deliberately ignoring/ignorant of - CHAR_BIT tells you how many bits are in a char. On most systems today, this is 8. In this theoretical setup, it's 32. You seem to be presuming it's never anything other than 8, and totally missing the point of CHAR_BIT.



  • The developer there got away with his error for the wrong reason. He forgot to add 1 for the null-terminator but because he allocated number of characters * sizeof( char * ) he allocated a lot more than he needed, even without the null terminator.

    Once he decided he had "new" available and thus was working in a C++ environment rather than C, he lost the argument completely for me. As long as the code was pure C, aside from a few minor things he wasn't going too badly but once you are in the land of C++, use strings and vectors.

     



  • @Enterprise Architect said:

    @topspin said:
    IMHO, in C++ references are just syntactic sugar for pointers. They're automatically dereferenced and cannot be NULL, but they're inherently the same thing and should produce the same output binary. (Except for debugging/export symbol data)

    Not exactly.

    #include <iostream>
    using namespace std;
    

    double get_salary() {
    return 1000000;
    }

    int main(int argc, char *argv[ ]) {
    const double &r = get_salary(); // Legal, if pointless
    cout << "Salary: " << r << endl;
    }

    However:

    const double *r = &get_salary(); // Illegal

    See also: GotW #88: A Candidate For the "Most Important const"

    I think in C++11 you will be allowed to define suffixes to indicate "units". Another step towards "strong typing" where enums don't quite work. So with monetary amounts, you can specify a currency.

     

     



  • @serguey123 said:

    @boomzilla said:
    My understanding (after skimming an MSDN page) is that the pointer types are very limited
    Compared to C/C++ yes, the idea of Net was to use managed code after all, so unsafe code is discouraged and kept apart

     and Microsoft's C++ compiler going around telling you that using the standard library is "unsafe" or even "deprecated" and you should use ther own stupid "safe" options instead. Everybody disables that warning and Microsoft have no right to deprecate features of the standard C or C++ library when compiling C or C++.

    @serguey123 said:

    @boomzilla said:
    you generally cannot do all of those things (in the sense that they exist in C++) with any old C# object.
    You lost me there, buddy @topspin said:
    IMHO, in C++ references are just syntactic sugar for pointers.
    I could probably make a car analogy for you. @topspin said:
    I'm curious how that reads when I'm sober tomorrow
    Not well

    The car analogy is probably that they are unsafe and you shouldn't drive them.

     

     


Log in to reply
 

Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.