Thread: string type troubles

  1. #16
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Yes, I guess I should have seen that.

    Besides, I think I was wrong: you can't add pointers at all. I guess if I thought about it that would make sense . . . .

    (Note: you can subtract two arbitrary pointers if you want to, but you'll get undefined behaviour. )
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  2. #17
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Who says you can't?
    Here's two ways of doing it!

    Code:
    	const char* c = "c";
    	const char* d = c;
    	c = (const char*)( c - (const char*)-(int32_t)d );
    	c = d;
    	c = c + (uint32_t)d;
    I admit, it's a hack, but it's possible (although technically, you aren't adding two pointers).
    (Don't abuse it, though )
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #18
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Drat, you can't use unary minus on pointers either.
    Code:
    #include <stdio.h>
    #include <stddef.h>
    
    void *negate(void *data) {
        void *p = 0;
        return (void *)-(data - p);
    }
    
    int main() {
        void *a, *b;
        a = &b;
        b = &a;
    
        printf("&#37;p\n", (void *)(a - negate(b)));
    
        return 0;
    }
    Note that ptrdiff_t is the type you get when you subtract two pointers, in C99 at least, and apparently you can negate that . . . .
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  4. #19
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Well, not in C++. But you can cast it to an integral type, negate it and cast it back. Of course, you'd have to do the actual subtraction first since a pointer can't be signed.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #20
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Hmm, interesting. I was fiddling with my program, and I came up with this:
    Code:
    #include <stdio.h>
    #include <stddef.h>
    
    ptrdiff_t negate(void *data) {
        void *p = 0;
        return -(data - p);
    }
    
    int main() {
        void *a, *b;
        a = &b;
        b = &a;
    
        printf("&#37;p\n", a - negate(b));
    
        return 0;
    }
    It looks like I managed to add two pointers, without using any casts! Am I missing something here?
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  6. #21
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Provided you don't use -Werror, I guess you're ok. (I got the warnings "pointer of type 'void *' used in subtraction" and "pointer of type 'void *' used in arithmetic", but then I have -pedantic turned on.) And I suppose it's a little bit of luck that negate does the right thing, but I would be surprised to be on a system where it didn't.

    Edit to add: although g++ didn't compile the program at all -- "pointer of type 'void *' used in arithmetic" is an error, not a warning, to g++.

  7. #22
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by dwks View Post
    It looks like I managed to add two pointers, without using any casts! Am I missing something here?
    Yes.

    1) Undefined behaviour from subtracting the null pointer from a dereferenceable pointer.
    2) As far as the compiler is concerned, you're not adding pointers. You're subtracting pointers, yielding an integer, and you're subtracting an integer from a pointer, yielding a pointer.
    3) Why the complicated negate stuff?
    Code:
    int main() {
        int i, j;
        int *a, *b, *n = 0;
        a = &i;
        b = &j;
    
        printf("&#37;p\n", a + (b - n));
    
        return 0;
    }
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  8. #23
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    If you're passing an integer type to printf, you should use &#37;x, not %p.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  9. #24
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    But the code is passing a pointer.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  10. #25
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by dwks View Post
    Hmm, interesting. I was fiddling with my program, and I came up with this:

    It looks like I managed to add two pointers, without using any casts! Am I missing something here?
    That's very C-ish. A c++ compiler would complain the instant you ran that program.
    In C++, void** != void*. And it could probably turn up a few other errors, as well.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #26
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Edit to add: although g++ didn't compile the program at all -- "pointer of type 'void *' used in arithmetic" is an error, not a warning, to g++.
    Indeed. I only tried it with GCC . . . . I didn't even think try to it as C++, because I though ptrdiff_t was C99-only.

    In C++, void** != void*.
    I know you hate command lines, but bear with me here.
    Code:
    $ cat ppvoid.cpp
    #include <iostream>
    
    int main() {
        void *a, *b;
        a = &b;
        b = &a;
        return 0;
    }
    $ g++ -W -Wall -ansi -pedantic ppvoid.cpp -o ppvoid
    $
    No warnings at all.

    It's true that something like this is invalid
    Code:
        void *p = 0;
        void **pp = p;  // error: invalid conversion from ‘void*’ to ‘void**’
    but the code I used above compiles for some reason. Another thing:
    Code:
        void ***ppp = 0;
        void **pp = ppp;  // g++ doesn't like this
        void *p = pp;  // but is fine with this
    Anyway . . . .

    2) As far as the compiler is concerned, you're not adding pointers. You're subtracting pointers, yielding an integer, and you're subtracting an integer from a pointer, yielding a pointer.
    That's true.

    3) Why the complicated negate stuff?
    I have no idea.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  12. #27
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    You can convert any pointer to void* implicitly, even in C++.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  13. #28
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It seems to accept any type, even void*** -> void*. Sillyness, really.
    At least it could try to differentiate between pointer levels.
    Oh well. It's not like we use void* in C++ very often.
    (Yay for templates!)
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #29
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Elysia View Post
    It seems to accept any type, even void*** -> void*. Sillyness, really.
    At least it could try to differentiate between pointer levels.
    Oh well. It's not like we use void* in C++ very often.
    (Yay for templates!)
    If you need to cast among unrelated pointer types, prefer casting via void* instead of using reinterpret_cast directly.

  15. #30
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    C++ casts are too long to type.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C++ ini file reader problems
    By guitarist809 in forum C++ Programming
    Replies: 7
    Last Post: 09-04-2008, 06:02 AM
  2. Can you check what is wrong with this code
    By Ron in forum C++ Programming
    Replies: 4
    Last Post: 08-01-2008, 10:59 PM
  3. Using VC Toolkit 2003
    By Noobwaker in forum Windows Programming
    Replies: 8
    Last Post: 03-13-2006, 07:33 AM
  4. Question on l-values.
    By Hulag in forum C++ Programming
    Replies: 6
    Last Post: 10-13-2005, 04:33 PM
  5. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM