Like Tree2Likes
  • 1 Post By Barney McGrew
  • 1 Post By AndiPersti

Pointers: Am I finally grokking them??

This is a discussion on Pointers: Am I finally grokking them?? within the C Programming forums, part of the General Programming Boards category; Does this code that I cranked out give some indication that I'm getting it , or am I just dreaming ...

  1. #1
    Registered User
    Join Date
    May 2011
    Location
    Alberta, Canada
    Posts
    34

    Pointers: Am I finally grokking them??

    Does this code that I cranked out give some indication that I'm getting it, or am I just dreaming in Technicolor?


    Code:
    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
    	int  myAge = 65;
    	//int *ptr = &myAge;
    	
    	int *ptr;
    	ptr = &myAge;
    	
    	printf("The pointer lives at: %p\n", (void *) &ptr);
    	printf("The pointer contain the address of where my age is stored at, which is: %p", (void *)ptr);
    	printf("\nI'm de-referencing a pointer to fetch my age which is: %d\n", *ptr);
    
       return 0;
    }
    Any and all other advise would be most welcome!
    --
    Duke

  2. #2
    Registered User
    Join Date
    Oct 2012
    Posts
    126
    **q=*ptr;

    you can always do multiple pointers, whats stored in **q would be the address to *ptr then the address of myAge would be stored in *ptr.

    You can initialize on same line also int *ptr=&myage;

  3. #3
    Registered User
    Join Date
    May 2011
    Location
    Alberta, Canada
    Posts
    34
    Quote Originally Posted by Sorinx View Post
    **q=*ptr;

    you can always do multiple pointers, whats stored in **q would be the address to *ptr then the address of myAge would be stored in *ptr.
    Thanks! I'll have to give that a try ....

    You can initialize on same line also int *ptr=&myage;
    You bet!! I have that commented out in my code. I had tried it out both ways ...

    Thanks for the input!

  4. #4
    Registered User
    Join Date
    Nov 2012
    Posts
    1,062
    Quote Originally Posted by dukester View Post
    Code:
    int *ptr;
    ptr = &myAge;
    printf("The pointer lives at: %p\n", (void *) &ptr);
    Note that in C, pointer types do not need to be cast to other pointer types. So you may write the preferred form:

    Code:
    printf("Here is a pointer: %p\n", &ptr);
    Also consider how pointers can be used in functions. Suppose you want a function that reads in two integers. We cannot return them, because in C we can only return a single value. We can write the function using pointers:

    Code:
    #include <stdio.h>
    #include <ctype.h>
    
    // getdigits(x, y): read two digits from the stdin into x,y
    // assume the digits are each one character long and do not
    // perform any error-checking
    void getdigits(int *x, int *y)
    {
        int c;
        // Skip whitespace
        while ((c = getchar()) == ' ' || c == '\n' || c == '\t')
            ;
        // Convert first digit to int
        *x = c-'0';
        // Skip whitespace
        while ((c = getchar()) == ' ' || c == '\n' || c == '\t')
            ;
        // Convert second digit to int
        *y = c-'0';
    }
    
    // main: demonstrate the getdigits() function
    int main()
    {
        printf("Please type two digits separated by whitespace: ");
        int num1, num2;
        getdigits(&num1, &num2);
        printf("First digit: %d\nSecond digit: %d\n", num1, num2);
        return 0;
    }

  5. #5
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,667
    Quote Originally Posted by Sorinx View Post
    **q=*ptr;

    you can always do multiple pointers, whats stored in **q would be the address to *ptr then the address of myAge would be stored in *ptr.

    You can initialize on same line also int *ptr=&myage;
    That doesn't seem right. Pointers to pointers are set up so that the value is another pointer's location.
    So if you were doing an assignment, you could do:
    q = &p;
    where q is a pointer to pointer and p is a pointer. If q can be dereferenced, you can instead do:
    *q = p;


    **q is the same as dereferencing p.

  6. #6
    Registered User
    Join Date
    May 2011
    Location
    Alberta, Canada
    Posts
    34
    Quote Originally Posted by c99tutorial View Post
    Note that in C, pointer types do not need to be cast to other pointer types. So you may write the preferred form:

    Code:
    printf("Here is a pointer: %p\n", &ptr);
    I've tried that, and although it compiles, I get the same warning:

    warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int **’ [-Wformat]

    So casting to (void *) makes the warning disappear.

    Also consider how pointers can be used in functions. Suppose you want a function that reads in two integers. We cannot return them, because in C we can only return a single value. We can write the function using pointers:

    [snip]
    You bet!! Pass arguments by value and by reference ....
    Not there yet, but encountered them in Oberon2 etc
    --
    duke

  7. #7
    Registered User
    Join Date
    May 2009
    Posts
    2,550
    This is a guess; but, I am thinking you are NOT using a C compiler; instead you are likely using a C++ compiler.
    Edit: Reason for my guess is that in other places C++ requires casts where C compilers do it without casts.
    Edit2: My guess appears to be wrong I even added the option -Wformat to my MinGW C++ Compiler and I can not dup your error.

    Tim S.

    Quote Originally Posted by dukester View Post
    I've tried that, and although it compiles, I get the same warning:

    warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int **’ [-Wformat]

    So casting to (void *) makes the warning disappear.



    You bet!! Pass arguments by value and by reference ....
    Not there yet, but encountered them in Oberon2 etc
    Note: tested this code and it compiled with no warnings using MinGW C and C++ Compilers.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        /* int *ptr = NULL; Tried using two stars and still no warning with MinGW GCC or G++*/
        int **ptr = NULL;
    
        printf("Here is a pointer: %p\n", &ptr);
        return 0;
    }
    The C++ Compile Command
    Code:
    mingw32-g++.exe  -std=gnu++0x -Wextra -Wall  -g  -Winvalid-pch   -Iv:\SourceCode\OpenSourceCode\Apps\IDEs\CodeBlocks\Projects\testc -c v:\SourceCode\OpenSourceCode\Apps\IDEs\CodeBlocks\Projects\testc\main.cpp -o obj\Debug\main.o
    mingw32-g++.exe  -o bin\Debug\testc.exe obj\Debug\main.o
    Code:
    mingw32-gcc.exe -Wextra -Wall  -g  -Winvalid-pch   -Iv:\SourceCode\OpenSourceCode\Apps\IDEs\CodeBlocks\Projects\testc -c v:\SourceCode\OpenSourceCode\Apps\IDEs\CodeBlocks\Projects\testc\main.c -o obj\Debug\main.o
    mingw32-g++.exe  -o bin\Debug\testc.exe obj\Debug\main.o    
    Output size is 28.36 KB
    Process terminated with status 0 (0 minutes, 0 seconds)
    0 errors, 0 warnings (0 minutes, 0 seconds)
    Last edited by stahta01; 11-11-2012 at 12:12 AM.
    "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the Universe is winning." Rick Cook

  8. #8
    Registered User
    Join Date
    Jun 2005
    Posts
    6,261
    Quote Originally Posted by c99tutorial View Post
    Note that in C, pointer types do not need to be cast to other pointer types
    That's not true. Any pointer type can be implicitly converted to a void pointer, and vice versa (i.e. without a "cast", aka type conversion).

    That does not carry across to other pointer types. There is no implicit conversion, for example, between a pointer to char and a pointer to float.


    There is also the complication that a lot of modern C compilers are actually C++ compilers, and implicit conversions to/from void pointers are not permitted in C++.


    Quote Originally Posted by dukester View Post
    I've tried that, and although it compiles, I get the same warning:

    warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int **’ [-Wformat]

    So casting to (void *) makes the warning disappear.
    That is a sign that your C compiler is actually a C++ compiler. Or (also possible, but less likely in practice) that your compiler is a bit over-zealous in checking that printf() format specifiers match the type of corresponding arguments.
    Right 98% of the time, and don't care about the other 3%.

  9. #9
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    It's an error to match an 'int *' with the %p specifier because 'int *' may have a different internal representation to 'void *'. Since printf's a variadic function, it performs no type conversion on its arguments (except for the default argument promotions) that match the ellipsis in its declaration, so an explicit cast is actually necessary in this situation.

    edit: This applies to 'int **' as well.
    Last edited by Barney McGrew; 11-11-2012 at 06:51 AM.
    laserlight likes this.

  10. #10
    Registered User
    Join Date
    Nov 2012
    Posts
    1,062
    Quote Originally Posted by Barney McGrew View Post
    It's an error to match an 'int *' with the %p specifier because 'int *' may have a different internal representation to 'void *'.
    Whether it has a different representation or not does not matter; the language guarantees that casting from (void *) to (FOO*) as well as from (FOO*) to (void*) is implicitly allowed

    Example:
    Code:
    int int_sort_asc(const void *a, const void *b) {
        const int *x = a;  // no cast needed
        const int *y = b;  // no cast needed
        return *x - *y;
    }
    
    void array_sort(int n, int a[n]) {
        qsort(a, n, sizeof(a[0]), int_sort_asc);
    }
    
    void array_pprint(int n, int a[n]) {
        printf("Array starts at address %p\n", a);  // no cast needed
    }

  11. #11
    Registered User
    Join Date
    May 2011
    Location
    Alberta, Canada
    Posts
    34
    Don't know!!! But ....

    I can tell you that I use SciTE as my go-to editor! Here's the complete output:

    Code:
    >gcc  -Os  -std=c99 -pedantic test-pointers3.c -o test-pointers3
    test-pointers3.c: In function ‘main’:
    test-pointers3.c:11:2: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result [-Wunused-result]
    >Exit code: 0

    after compiling:

    Code:
    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
    	int x;
    	int *ptr;
    	
    	ptr = &x;
    	printf("Gimme a number: ");
    	
    	(void) scanf("%d", ptr);    // or scanf("%d", &x);  same thing
    	printf("You input: %d\n", *ptr);
    	getchar();
    
       return 0;
    }
    As you can see, SciTE is set up to use gcc for C code. I made sure to nuke all references to g++ by hacking my SciTEUser.properties file. So unless somethings going on "behind the scene" which I'm not aware of, then I'd say that it's gcc that barfing the warnings.

    But..... I'm a C noob!! So what do I know?? lol
    --
    duke

  12. #12
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    @c99tutorial: The point is that it isn't converted at all when it's passed to printf. If you pass an 'int *' to printf, then printf will receive an 'int *', because it has no reason to convert it to any other type. The difference is that in your example you provide explicit types in your argument list for int_sort_asc, whereas printf doesn't. Compare the following function declarations:

    Code:
    int int_sort_asc(const void *a, const void *b);
    int printf(const char *format, ...);
    Do you see the difference?

  13. #13
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    @dukester: You should check the return value to ensure that an item was successfully converted.


    These functions return the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure. The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see ferror(3)) is set, and errno is set indicate the error.
    * scanf(3) - Linux manual page

  14. #14
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by dukester View Post
    I've tried that, and although it compiles, I get the same warning:

    warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int **’ [-Wformat]

    So casting to (void *) makes the warning disappear.
    As you have shown in post #11, you are using the -pedantic option with gcc. Thus it follows strict ISO C rules.
    The C standard says that the argument for "%p" shall be a pointer to void. The C standard doesn't guarantee that every pointer type is of the same size as a pointer to void. That's why you get the warning when you use -pedantic.
    See also this answer on StackOverflow.

    Bye, Andreas
    stahta01 likes this.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Finally, it's done!
    By dP munky in forum Game Programming
    Replies: 29
    Last Post: 05-19-2003, 08:47 AM
  2. finally
    By Magma in forum C++ Programming
    Replies: 4
    Last Post: 04-03-2003, 08:11 PM
  3. Finally!!!
    By Jeremy G in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 03-31-2003, 03:46 PM
  4. I Think I Finally Get It!
    By LordVirusXXP in forum C++ Programming
    Replies: 2
    Last Post: 12-18-2002, 01:43 PM
  5. Finally
    By Dissata in forum Game Programming
    Replies: 6
    Last Post: 02-14-2002, 06:19 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21