How Can I Use C Pointers and Structs to Manipulate Data in a Struct Voter?

  • Thread starter Firestrider
  • Start date
  • Tags
    Basics
In summary: When you don't want to have your program use resources that it doesn't need, you can free the memory by calling free().
  • #1
Firestrider
104
0
Can someone explain to me what exactly these two constructs mean:

Code:
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.
 
Technology news on Phys.org
  • #2
'struct integer' defines an object (a struct) that contains the two variables (digits and size).
It let's 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;
 
  • #3
What does the asterisk after char, int, and integer mean? I thought pointers were supposed to be before the variable like *p.
 
  • #4
white space generally doesn't matter in c, so "int *p" and "int* p" are the same - it's a matter of style.
 
  • #5
Firestrider said:
What does the asterisk after char, int, and integer mean? I thought pointers were supposed to be before the variable like *p.

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.
 
  • #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.
 
  • #7
Firestrider said:
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.
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.
 
  • #8
Like in this example:

Code:
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?
 
  • #9
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?

A pointer is nothing more than an address. See for yourself:

Code:
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)).

Why do I need to use dynamic memory allocation,

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.)

and where do I free memory in this example?

You haven't yet. Your function returns a pointer to the allocated object, which you will probably use somewhere else.
 
Last edited:
  • #10
Why do I need to use dynamic memory allocation, and where do I free memory in this example?
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.
 
  • #11
DaleSpam said:
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.

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.
 
  • #12
mgb_phys said:
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.

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.)
 
  • #13
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.
 
  • #14
mgb_phys said:
(although why they are trying to teach it using c rather than c++ I don't know)

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.
 
  • #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:
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;
  
}
 
  • #16
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:
#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;
}
 
  • #17
signerror said:
A pointer is nothing more than an address. See for yourself:

Code:
...
printf( "Address of x: %x\n", &x );

(The "%x" formatter prints in hexadecimal (base-16)).
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.
 
  • #18
jtbell said:
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().

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:
#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:
  • #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:
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:
  • #20
Firestrider: That looks correct to me! However for extra doing-it-rightness you should use strncpy() instead of strcpy(). strncpy let's 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...
 
  • #21
Firestrider said:
Also is there a simple way to swap an entire struct without going through each of its elements?
Yes, you can copy an entire struct with an assign statement, but not an array.

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


void swap(struct voter *p1, struct voter *p2) 
{
struct voter *ptemp;
    *ptemp = *p1;
    *p1 = *p2;
    *p2 = *ptemp;
}

To get around the array assignment limitation, you could make each array a structure.
I also switched to using typedefs:

Code:
typedef struct _sname    /* using sname to mean structure of type name */
{
    char name[30];
}SNAME, *PSNAME;

typedef struct _voter 
{
   SNAME first;
   SNAME last;
}VOTER, *PVOTER;

void swap(PVOTER p1, PVOTER p2) 
{
PVOTER pt;

    pt->first = p1->first;
    p1->first = p2->first;
    p2->first = pt->first;

    pt->last = p1->last;
    p1->last = p2->last;
    p2->last = pt->last;

/*  note to access the actual strings use p1->first.name */
}
 
Last edited:

1. What is a pointer in C?

A pointer in C is a variable that stores the address of another variable. It essentially "points" to the location in memory where the value of the variable is stored.

2. How do you declare a pointer in C?

To declare a pointer in C, you use the asterisk symbol (*) before the variable name. For example, to declare a pointer to an integer variable, you would write "int *ptr;".

3. What is the difference between a pointer and a regular variable in C?

The main difference between a pointer and a regular variable in C is that a pointer stores a memory address, while a regular variable stores a value. Pointers can also be used to indirectly access and modify the value of a variable.

4. What is a struct in C?

A struct in C is a user-defined data type that allows you to combine different data types into a single variable. It is often used to group related data together in a more organized way.

5. How do you access and modify data within a struct using pointers?

To access and modify data within a struct using pointers, you first need to create a pointer to the struct. Then, you can use the arrow operator (->) to access the members of the struct. To modify the data, you can use the dereference operator (*) to access the value stored at the memory address pointed to by the pointer.

Similar threads

  • Programming and Computer Science
Replies
16
Views
4K
  • Programming and Computer Science
Replies
5
Views
881
  • Engineering and Comp Sci Homework Help
Replies
2
Views
1K
  • Programming and Computer Science
Replies
12
Views
3K
  • Programming and Computer Science
Replies
6
Views
7K
  • Programming and Computer Science
Replies
23
Views
1K
  • Programming and Computer Science
Replies
4
Views
2K
  • Programming and Computer Science
Replies
5
Views
3K
  • Programming and Computer Science
Replies
9
Views
2K
  • Programming and Computer Science
2
Replies
55
Views
4K
Back
Top