Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

C pointers/structs basics

  1. Jan 18, 2009 #1
    Can someone explain to me what exactly these two constructs mean:

    Code (Text):

    struct integer
    {
        int* digits;
        int size;
    };

    struct integer* read_integer(char* stringInt);
     
    I'm supposed to read in all the characters of a long integer (up to 200 digits) and return a pointer. How can I access the size and digits in the struct integer? How can I determine whether I've reached white space? How can I convert a character into an integer?

    Thank you for your help.
     
  2. jcsd
  3. Jan 18, 2009 #2

    mgb_phys

    User Avatar
    Science Advisor
    Homework Helper

    'struct integer' defines an object (a struct) that contains the two variables (digits and size).
    It lets you treat these two as a single lump and so is easier to pass around than two separate variables,
    In this case you can pass back a new 'integer' object from the read_integer call.

    You access individual members of the struct with a dot,
    eg
    struct interger my_interger;
    my_interger.size = 100;
     
  4. Jan 18, 2009 #3
    What does the asterisk after char, int, and integer mean? I thought pointers were supposed to be before the variable like *p.
     
  5. Jan 18, 2009 #4

    mgb_phys

    User Avatar
    Science Advisor
    Homework Helper

    white space generally doesn't matter in c, so "int *p" and "int* p" are the same - it's a matter of style.
     
  6. Jan 19, 2009 #5

    chiro

    User Avatar
    Science Advisor

    A pointer is just going to be a byte offset into some memory location. Ignoring memory mapping for the moment, it represents a number from zero to memorysize - 1.

    To get the address (pointer) of a variable structure we use the & operator. To dereference a pointed variable back to its object we use the * operator. We can access pointed elements in a pointer structure using the -> command rather than using the . operator for non-heap objects.

    so LPBYTE p = &byte and *p is your byte. But declarations are another matter. Like the above poster said you can declare say int* p and int *p and they are equivalent.
     
  7. Jan 25, 2009 #6
    Just for a clarification:

    1. int* variable is the value that variable is pointing to of type int?
    2. &variable is the address of the value of variable?
    3. *struct_variable.piece is the same thing as variable->piece?
    4. struct_variable.piece accesses a piece of the struct for assignment?
    5. when a parameter of the a function is a pointer, do I pass in addresses?
    6. when/why would you use dynamic memory allocation (like in this example) instead of static memory allocation?
    7. when do you free the memory after a malloc?
    8. why would you pass by reference and not pass by value in this example?

    Thanks for the help.
     
  8. Jan 25, 2009 #7

    Dale

    Staff: Mentor

    1) yes
    2) I don't know what you mean by "the address of the value"
    3) struct_variable->piece is shorthand for (*struct_variable).piece
    4) yes, provided piece is a public member of struct_variable which is the default for structs
    5) yes
    6) when you don't want to have your program use resources that it doesn't need
    7) when you are done using it
    8) in C/C++ you can pass by value, reference, or pointer. IMO, you should use pass by pointer for any variable that will be modified by the function, pass by value for primitive data type variables that will not be modified by the function, and pass by const reference for non-primitive variables that will not be modified by the function.
     
  9. Jan 25, 2009 #8
    Like in this example:

    Code (Text):

    struct integer* read_integer(char* stringInt)
    {
           struct integer* temp;
           temp = malloc(sizeof(struct integer));
           temp->size = strlen(stringInt);
           temp->digits = malloc(temp->size * sizeof(int));
           return temp;
    }
     
    Why do I need to use dynamic memory allocation, and where do I free memory in this example?

    What I think is that all variables have an address and a value in memory. Are the addresses and values stored in different cells in memory from each other? Is a pointer separate from the address stored in memory or is it THE address, and without a pointer a programmer would not have access to the address?
     
  10. Jan 25, 2009 #9
    A pointer is nothing more than an address. See for yourself:

    Code (Text):

    int x;
    int * px;

    px = &x;

    printf( "Address of x: %x\n", &x );
    printf( "Value of px: %x\n", px );
     
    (The "%x" formatter prints in hexadecimal (base-16)).

    You don't. Exercise: rewrite the program without dynamic memory, and compare. You will not be able to create arbitrary-sized integers: you will have to set a compile-time limit, in order to create statically-allocated arrays of digits. Additionally, you will suffer a performance penalty, as your functions will pass around very large objects instead of pointers, and this will involve a complete copying of the entire integer struct every time you assign one or return one from a function. (It is not possible to simply return the address of an automatic variable (statically defined in a function) like "return &x;", because such variables' memory is freed when the function exits.)

    You haven't yet. Your function returns a pointer to the allocated object, which you will probably use somewhere else.
     
    Last edited: Jan 25, 2009
  11. Jan 25, 2009 #10

    mgb_phys

    User Avatar
    Science Advisor
    Homework Helper

    Because the read_integer function builds a 'integer' object it has to also make somewhere permanent to put it, if it was just struct integer temp inside the function then as soon as the function ended that memory would be lost. Think of is as a factory building cars(='integer's) and putting them in a parking lot, the pointer it returns is the number of the lot.
    The main program that receives the pointer is respnsible for deleting the memory (scrapping the car) when it has finished with the object, after deleteting the pointer still exists but there is no car in the lot (no struct at that address) when you delete an objectit is good practice to set the pointer=NULL to make it clear that it is no longer pointing to anything.
     
  12. Jan 25, 2009 #11
    There's differences between and C and C++. You do not have references in C. You can "pass by reference" though, but this is accomplished differently from C++: in C "pass by reference" means passing pointers to objects, whereas C++ actually has a reference type which can be passed around. Also, the 'const' modifier does not exist in C; it is a C++ feature.
     
  13. Jan 25, 2009 #12
    That's not technically true - you could allocate statically, using the usual syntax throughout. The difference is that each assignment and function return would involve a full memory copy of the entire struct, which is fine for primitives like 'char' and 'int' but a huge waste of time for large objects. (Also, you would be limited to fixed-sized arrays instead of arbitrary-length lists - but this is more of a C quirk than a fundamental programming limitation. For instance, C++ STL containers let you have dynamically-sized vectors, although internally they use pointers and malloc/realloc.)
     
  14. Jan 25, 2009 #13

    mgb_phys

    User Avatar
    Science Advisor
    Homework Helper

    Yes - the sane way to do it would be for the caller to pass in a pointer to a struct, then the function doesn't have to know where it came from. But this is obviously an excercise supposed to teach factory patterns. (although why they are trying to teach it using c rather than c++ I don't know)

    I was just warning aginst the OP putting a stack 'struct integer temp' in the function and passing a pointer back to the caller - something that would appear to work but would be a bugger to unersand why it is going wrong.
     
  15. Jan 25, 2009 #14
    Probably because C++ syntax is an obfuscation of C: it liberally uses shorthands to cover up the inner workings of C to make programming simpler, but by hiding the functionality it is more difficult to learn how it works.
     
  16. Feb 6, 2009 #15
    Does anyone know why I get a compile error (116 C:\Users\Sean\Desktop\test.c incompatible types in assignment) in this code? Shouldn't p1->first be a character array? Also is there a simple way to swap an entire struct without going through each of its elements? That is what I'm trying to accomplish.

    Code (Text):

    struct voter
    {
       char first[30];
       char last[30];
       char gender[2];
       char race[2];
       int age;
    };


    void swap(struct voter *p1, struct voter *p2)
    {
       int tempAge;
       char tempString[30];
       
       tempString = p1->first;
       p1->first = p2->first;
       p2->first = tempString;
     
    }
     
     
  17. Feb 6, 2009 #16

    jtbell

    User Avatar

    Staff: Mentor

    You cannot copy arrays (including character arrays) by simple assignment. If a character array contains a null-terminated string, you can copy it using strcpy().

    You can copy structs that contain "plain old data," by simple assignment.

    Code (Text):

    #include <iostream>

    using namespace std;

    struct voter
    {
       char first[30];
       char last[30];
       char gender[2];
       char race[2];
       int age;
    };

    int main ()
    {
        voter alice, bob, temp;

        strcpy (alice.first, "Alice");
        strcpy (bob.first, "Bob");

        cout << "Alice's first name is " << alice.first << "." << endl;
        cout << "Bob's first name is " << bob.first << "." << endl;

        cout << "Now we swap 'em..." << endl;

        temp = alice;
        alice = bob;
        bob = temp;

        cout << "Alice's first name is " << alice.first << "." << endl;
        cout << "Bob's first name is " << bob.first << "." << endl;

        return 0;
    }
     
     
  18. Feb 6, 2009 #17

    Hurkyl

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    Actually, this is wrong. There is another part to the semantics of %x: that is "assume the next argument to printf is actually an unsigned int". Since the next argument really isn't an unsigned int, all sorts of strange things are allowed to happen. The correct format specifier to print the value of a pointer is %p.
     
  19. Feb 6, 2009 #18

    jtbell

    User Avatar

    Staff: Mentor

    If you're using C++, you really should investigate using the standard 'string' data type to hold character data. Unlike arrays, you can copy strings by assignment. Also, you don't have to worry about how long the string is going to be, because it automatically expands dynamically as necessary, to hold whatever you put into it.

    Likewise as a "replacement" for arrays in general, C++ has a dynamic data type called 'vector' which makes many array-related programming tasks much simpler. For example, you can copy vectors by assignment.

    Code (Text):

    #include <iostream>
    #include <string>

    using namespace std;

    struct voter
    {
       string first;
       string last;
       string gender;
       string race;
       int age;
    };

    int main ()
    {
        voter alice, bob, temp;

        alice.first = "Alice";
        bob.first = "Bob";

        cout << "Alice's first name is " << alice.first << "." << endl;
        cout << "Bob's first name is " << bob.first << "." << endl;

        cout << "Now we swap 'em..." << endl;

        temp = alice;
        alice = bob;
        bob = temp;

        cout << "Alice's first name is " << alice.first << "." << endl;
        cout << "Bob's first name is " << bob.first << "." << endl;

        return 0;
    }
     
     
    Last edited: Feb 6, 2009
  20. Feb 6, 2009 #19
    Thanks for the help but I have to do this all in C for class, and all the work has to be done in swap. Would this be equivalent:

    Code (Text):


    void swap(struct voter *p1, struct voter *p2)
    {
       int tempAge;
       char tempString[30];
       
       strcpy(tempString, p1->first);
       strcpy(p1->first, p2->first);
       strcpy(p2->first, tempString);
       
       strcpy(tempString, p1->last);
       strcpy(p1->last, p2->last);
       strcpy(p2->last, tempString);
       
       strcpy(tempString, p1->gender);
       strcpy(p1->gender, p2->gender);
       strcpy(p2->gender, tempString);
       
       strcpy(tempString, p1->race);
       strcpy(p1->race, p2->race);
       strcpy(p2->race, tempString);
       
       tempAge = p1->age;
       p1->age = p2->age;
       p2->age = tempAge;
     
    }
     
     
    Last edited: Feb 6, 2009
  21. Feb 7, 2009 #20
    Firestrider: That looks correct to me! However for extra doing-it-rightness you should use strncpy() instead of strcpy(). strncpy lets you specify a number that says "don't copy more than this number of characters". Imagine what would happen if p1->first contained more than 30 letters...
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?



Similar Discussions: C pointers/structs basics
  1. C++ structs and classes (Replies: 23)

Loading...