Thread: Difference between Reference and Pointer?

  1. #1
    Registered User
    Join Date
    Sep 2011
    Posts
    4

    Difference between Reference and Pointer?

    Hey so I've been working on this assignment and came across something that's a little confusing to me.

    My understanding of pointers isn't the strongest (I tend to just try stuff till it works) I skimmed through this References vs. Pointers but I didn't pick up on why I'm having an issue.

    So I was wondering what the difference between these two scenarios are.

    1st. I have a global pointer, that points to an array in the main. I then create a thread using pthread_create. In the thread function I then can set the value of the array[0] by using
    Code:
    *ptr = 35;
    that then changes array[0] to 35.

    2nd. I have an array that I create. I pass the array by reference to the thread function. It should create a pointer to the array.
    Code:
    *fibbs = 35;
    gives me "warning: derefencing 'void *' pointer
    error: invalid use of void expression"

    Why is that? Aren't they the same thing?

    Heres a trimmed version of my program for you to take a look at:
    Code:
    #include <pthread.h>
    #include <stdio.h>
    
    int size = 0;
    int *ptr;
    void *fibseq(void *fibbs);
    
    int main(int argc, char *argv[])
    {
        if (argc > 1) {
            size = atoi(argv[1]);
        }
        
        int fiblist[size];
        ptr = &fiblist[0];
        fiblist[0] = 10;
        fiblist[1] = 15;
    
        pthread_t tid;
        pthread_attr_t attr;
    
        pthread_attr_init(&attr);
        pthread_create(&tid, &attr, fibseq, &fiblist[0]);
        pthread_join(tid, NULL);
        
    }
    
    void *fibseq(void *fibbs) {
        int i;
        *fibbs = 35;
        printf("blargh %d\n", fibbs); 
        *ptr = 35;
        printf("grrgah %d\n", ptr); //Prints the same address space as blargh
    }
    I try hard to learn as much on my own and figure stuff out, but sometimes I just can't find the appropriate information. So any explanations as to how the two are different would be greatly appreciated. Thanks

    If you have any questions, comments, suggestions, need more info, etc... I'll reply back in the morning when I wake up in a couple hours.
    Last edited by DarkMage530; 09-20-2011 at 04:06 AM.

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    We just had *ahem* polite discussion on this the other day. Read this thread: Bubble sort algorithm


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by DarkMage530 View Post
    Hey so I've been working on this assignment and came across something that's a little confusing to me.

    My understanding of pointers isn't the strongest (I tend to just try stuff till it works) I skimmed through this References vs. Pointers but I didn't pick up on why I'm having an issue.
    The active term being "skimmed" rather than "studied"....

    FWIW... C does NOT do pass by reference... it only passes a copy of the value of the pointer into your function. Inside your function you can choose to treat this as a pointer and thus can influence data outside the function... But, be aware, an address in C is merely a number... nothing special.


    So I was wondering what the difference between these two scenarios are.
    1st. I have a global pointer, that points to an array in the main. I then create a thread using pthread_create. In the thread function I then can set the value of the array[0] by using
    Code:
    *ptr = 35;
    that then changes array[0] to 35.

    2nd. I have an array that I create. I pass the array by reference to the thread function. It should create a pointer to the array.
    Code:
    *fibbs = 35;
    gives me "warning: derefencing 'void *' pointer
    error: invalid use of void expression"
    You cannot dereference void pointers... void pointers have no size so the compiler cannot determine how much data to copy.
    This is one of those rare situations where you do need to typecast ... *((int*)fibbs) = 35; ... now the compiler knows to copy sizieof(int) bytes.


    Why is that? Aren't they the same thing?
    No they are different types.


    [

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    Not to mention all the possible values of size which will cause grief should you fail to supply a command line parameter, or a suitable command line parameter.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by DarkMage530 View Post
    So I was wondering what the difference between these two scenarios are.
    Since C does not officially support "references", there are not two different scenarios. However, while:

    Quote Originally Posted by CommonTater View Post
    C does NOT do pass by reference...
    is literally true, colloquially, it is not uncommon to refer to "passing by reference" in C to refer to using pointers. In that sense, using references and pointers refers to exactly the same thing.

    Many languages which do not use pointers have "references" which accomplish the same thing (because they are actually pointers under the hood). C++ has pointers and references, but C++ references are just sugary pointers (they are more convenient in cases where the exact value stored in a pointer -- a memory address -- is irrelevant to the programmer, which can be fairly often).

    So the difference between a pointer and a reference depends upon what you mean by "reference", but in practical terms a C pointer is a form of reference. The variable it "points" to is the variable it can be said to "refer" to. Which is why you can deference a pointer to get the value it points to.

    The term "reference" is used in other languages refers to a type where the significance of explicit memory addressing has been abstracted away. It is essentially just a shift in semantics.
    Last edited by MK27; 09-20-2011 at 09:09 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  6. #6
    Registered User
    Join Date
    Sep 2011
    Posts
    4
    @Quzah: Ah, I see. Sorry, I didn't realize this was a recently discussed topic. I've read through your discussion with Mr.Lnx and also took a look at the link you posted within the Bubble Sort Topic.

    I think I understand. So in C there is only passing by value. In the following example:
    Code:
    int foo(int *ptr, int num) //Line B
    ....
    foo(&bar, bar2); //Line A
    At Line A the memory address of bar is being passed into foo as a value. bar2 is having it's value passed as a value. Both 'values' have been copied so they can be used by foo.

    In Line B, because the first parameter is int *ptr, the memory address of bar is now being pointed to by ptr. And bar2's value was copied to int num.
    Is that accurate?

    @CommonTater: Let me start off by clarifying. When I say skim I actually mean: read a little bit, if irrelevant jump down a few lines or a paragraph, read a little bit, if irrelevant jump down a few lines. Continue until relevant information is found. So I suppose I should of said Selectively Read instead of skimmed.

    I think I understand the memory address as just a number. Check the above example to see if my understanding is correct.

    I see so the problem I was having was not with "passing by reference"/pointer but that the pointer type isn't quite right. Since pthread_create casts the parameter as void*, it must be cast to an int* prior to dereferencing a value. I did a little experimenting
    Code:
    ...
        fiblist[0] = 13;
        fiblist[1] = 17;
        fiblist[2] = 23;
    ...
    void *fibseq(void *fibpts) {
        printf("fibpts%d - %d\n", *((int*)fibpts), fibpts);
        fibpts++;
        printf("fibpts%d - %d\n", *((int*)fibpts), fibpts);
        fibpts++;
        printf("fibpts%d - %d\n", *((int*)fibpts), fibpts);
        fibpts++;
        printf("fibpts%d - %d\n", *((int*)fibpts), fibpts);
        fibpts++;
        printf("fibpts%d - %d\n", *((int*)fibpts), fibpts);
        fibpts += 4;
        printf("fibpts%d - %d\n", *((int*)fibpts), fibpts);
        *((int*)fibpts) = 300;
        printf("ptr%d - %d\n", *ptr, ptr);
        ptr++;
        printf("ptr%d - %d\n", *ptr, ptr);
        ptr++;
        *ptr = 65;
        printf("ptr%d - %d\n", *ptr, ptr);
    OutPut:
    fibpts 13 - 2673856
    fibpts 285212672 - 2673857
    fibpts 1114112 - 2673858
    fibpts 4352 - 2673859
    fibpts 17 - 2673860
    fibpts 23 - 2673864
    ptr 13 - 2683856
    ptr 17 - 2683860
    ptr 65 - 2683864

    So tell me if this is correct. I was baffled at first as to why fibpts++ increments only one byte instead of to the next int array element like with the ptr. But since fibpts is originally declared as a void*, when the value of fibpts (the memory address of fiblist[0]) is incremented by one it isn't cast specifically as an int and the memory address is incremented by one number which corresponds to one byte. (No different than if I took the memory address and just added one)

    Since ptr is of int and each int in a 32 bit enviornment is 4 bytes, when incrementing by one it automatically add's one 4 byte int, so it moves down 4 memory address spaces.

    Does that sound right?

    @Salem: Well for now this is just a program for myself to help understand how to use threads which turned into learning about pointers. Of course if this were to be used by others outside of just me, then I would include some error checking.
    Last edited by DarkMage530; 09-20-2011 at 10:33 AM.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Quote Originally Posted by DarkMage530
    So tell me if this is correct. I was baffled at first as to why fibpts++ increments only one byte instead of to the next int array element like with the ptr. But since fibpts is originally declared as a void*, when the value of fibpts (the memory address of fiblist[0]) is incremented by one it isn't cast specifically as an int and the memory address is incremented by one number which corresponds to one byte. (No different than if I took the memory address and just added one)
    Actually, your code is wrong. It may compile and work as described due to a language extension of your compiler, but otherwise it is invalid: pointer arithmetic is forbidden for pointers to void.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by DarkMage530 View Post
    So tell me if this is correct. I was baffled at first as to why fibpts++ increments only one byte instead of to the next int array element like with the ptr. But since fibpts is originally declared as a void*, when the value of fibpts (the memory address of fiblist[0]) is incremented by one it isn't cast specifically as an int and the memory address is incremented by one number which corresponds to one byte. (No different than if I took the memory address and just added one)

    Since ptr is of int and each int in a 32 bit enviornment is 4 bytes, when incrementing by one it automatically add's one 4 byte int, so it moves down 4 memory address spaces.

    Does that sound right?
    Yes. However, don't do it that way, because an int isn't necessarily four bytes on all systems. You could use sizeof(int), but there is also laserlight's caveat to consider, and you cannot cast an lvalue. The best way to deal with this is to assign back to the correct type:

    Code:
    void *fibseq(void *data) { 
        int *fibpts = data;
    Now everything will work the way it should, and by the book.
    Last edited by MK27; 09-20-2011 at 10:47 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    Registered User
    Join Date
    Sep 2011
    Posts
    4
    @laserlight: so your saying the line
    Code:
    fibpts++;
    is invalid in actual c. I'm using cygwin and editing with notepad++.

    Sorry I'm trying to understand what you mean exactly. So because fibpts is declared as a void, to do any arithmetic on it is illegal. Correct?

    So if I want to increment fibpts so it points to the next item in the array I should do something like...
    Code:
    fibpts = &fibpts + 4;
    fibpts is getting set to the address of the previous fibpts plus 4 memory spaces.

    Like I said in the initial post, my understanding of pointers isn't very strong.

    @MK27: I see, this is also starting to make more sense. I appreciate the help so far.

  10. #10
    Registered User
    Join Date
    Sep 2011
    Posts
    4
    Quote Originally Posted by MK27 View Post
    Yes. However, don't do it that way, because an int isn't necessarily four bytes on all systems. You could use sizeof(int), but there is also laserlight's caveat to consider, and you cannot cast an lvalue. The best way to deal with this is to assign back to the correct type:

    Code:
    void *fibseq(void *data) { 
        int *fibpts = data;
    Now everything will work the way it should, and by the book.
    AH! Okay, wow that is actually really simple. I just tried that out in the code and it works great. And it makes sense. Since data is the memory address of fiblist you are essentially setting fibpts to point directly to the array's memory address.

    Thanks everyone, I think I have a better understanding of how pointers work and how they interact!

  11. #11
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by DarkMage530 View Post
    @CommonTater: Let me start off by clarifying. When I say skim I actually mean: read a little bit, if irrelevant jump down a few lines or a paragraph, read a little bit, if irrelevant jump down a few lines. Continue until relevant information is found. So I suppose I should of said Selectively Read instead of skimmed.
    I used to do this too... and one day, after several failed attemtps at geting one of Windows bassackwards function calls to work, I forced myself to read every single word on the page... and there tucked into a parenthetical comment half way down the page --where I had not previously even glanced-- was my answer. The lesson was that technical documentation is not casual reading and sometimes "selective" or "subjective" reading comes back to bite you. Since then I've altered my strategy; unless it's something I'm familiar with already, there is no such thing as insignificant information on a page.

    I see so the problem I was having was not with "passing by reference"/pointer but that the pointer type isn't quite right. Since pthread_create casts the parameter as void*, it must be cast to an int* prior to dereferencing a value. I did a little experimenting
    Correct... in your experiment the pointer only incremented one position because it didn't know it was pointing at integers. The solution is simple enough... make a copy of the pointer, in the correct type...
    Code:
    ...
        fiblist[0] = 13;
        fiblist[1] = 17;
        fiblist[2] = 23;
    ...
    void *fibseq(void *fibpts) {
    
         int *xpts = fibpts;  // pointer to int* 
    
        printf("fibpts%d - %d\n", *xpts, xpts);
        xpts++;
    
        // and so on
    What output does it give you now?

    So tell me if this is correct. I was baffled at first as to why fibpts++ increments only one byte instead of to the next int array element like with the ptr. But since fibpts is originally declared as a void*, when the value of fibpts (the memory address of fiblist[0]) is incremented by one it isn't cast specifically as an int and the memory address is incremented by one number which corresponds to one byte. (No different than if I took the memory address and just added one)

    Since ptr is of int and each int in a 32 bit enviornment is 4 bytes, when incrementing by one it automatically add's one 4 byte int, so it moves down 4 memory address spaces.
    Yep... that's pretty much it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Difference between character pointer
    By sarathius in forum C Programming
    Replies: 10
    Last Post: 06-01-2011, 04:05 PM
  2. difference between pointer and array
    By zcrself in forum C Programming
    Replies: 4
    Last Post: 04-25-2010, 09:10 AM
  3. Replies: 3
    Last Post: 10-30-2009, 04:41 PM
  4. Replies: 2
    Last Post: 05-04-2003, 11:55 AM
  5. Difference between macro and pass by reference?
    By converge in forum C++ Programming
    Replies: 2
    Last Post: 02-26-2002, 05:20 AM

Tags for this Thread