Good morning!
I must handle a struct array (global variable) that simulates a list. In practice, every time I call a method, I have to increase the size of the array 1 and insert it into the new struct.
Since the array size is static, my idea is to use pointers like this:
The struct array is declared as a pointer to a second struct array.
Each time I call the increaseSize () method, the content of the old array is copied to a new n + 1 array.
The global array pointer is updated to point to a new array
In theory, the solution seems easy ... but I'm a noob of c. Where is that wrong?
struct task {
char title[50];
int execution;
int priority;
};
struct task tasks = *p;
int main() {
//he will call the increaseSize() somewhere...
}
void increaseSize(){
int dimension = (sizeof(*p) / sizeof(struct task));
struct task newTasks[dimension+1];
for(int i=0; i<dimension; i++){
newTasks[i] = *(p+i);
}
free(&p);
p = newTasks;
}
You mix up quite a lot here!
int dimension = (sizeof(*p) / sizeof(struct task));
p is a pointer, *p points to a struct task, so sizeof(*p) will be equal to sizeof(struct task), and dimension always will be 1...
You cannot use sizeof in this situation. You will have to store the size (number of elements) in a separate variable.
struct task newTasks[dimension+1];
This will create a new array, yes – but with scope local to the current function (so normally, it is allocated on the stack). This means that the array will be cleaned up again as soon as you leave your function.
What you need is creating the array on the heap. You need to use malloc function for (or calloc or realloc).
Additionally, I recomment not increasing the array by 1, but rather duplicating its size. You need to store the number of elements contained in then, too, though.
Putting all together:
struct task* p;
size_t count;
size_t capacity;
void initialize()
{
count = 0;
capacity = 16;
p = (struct task*) malloc(capacity * sizeof(struct task));
if(!p)
// malloc failed, appropriate error handling!
}
void increase()
{
size_t c = capacity * 2;
// realloc is very convenient here:
// if allocation is successful, it copies the old values
// to the new location and frees the old memory, so nothing
// so nothing to worry about except for allocation failure
struct task* pp = realloc(p, c * sizeof(struct task));
if(pp)
{
p = pp;
capacity = c;
}
// else: apprpriate error handling
}
Finally, as completion:
void push_back(struct task t)
{
if(count == capacity)
increase();
p[count++] = t;
}
Removing elements is left to you – you'd have to copy the subsequent elements all to one position less and then decrease count.
I have been reading a number of questions on this site about how to duplicate structs in C. I've been playing around with some code, trying to understand the differences between 'shallow' copying (where the new struct is simply assigned a pointer to the memory address of the first struct) and 'deep' copying (where the data is copied member-by-member into a new chunk of memory).
I created the following code, assuming that it would show the 'shallow' copying behavior:
#include <stdio.h>
struct tester
{
int blob;
int glob;
char* doob[10];
};
int main (void)
{
//initializing first structure
struct tester yoob;
yoob.blob = 1;
yoob.glob = 2;
*yoob.doob = "wenises";
//initializing second structure without filling members
struct tester newyoob;
newyoob = yoob;
//assumed this line would simply copy the address pointed to by 'yoob'
//printing values to show that they are the same initially
printf("Before modifying:\n");
printf("yoob blob: %i\n", yoob.blob);
printf("newyoob blob: %i\n", newyoob.blob);
//modifying 'blob' in second structure. Assumed this would be mirrored by first struct
newyoob.blob = 3;
//printing new int values
printf("\nAfter modifying:\n");
printf("yoob blob: %i\n", yoob.blob);
printf("newyoob blob: %i\n", newyoob.blob);
//printing memory addresses
printf("\nStruct memory addresses:\n");
printf("yoob address: %p\n", &yoob);
printf("newyoob address: %p\n", &newyoob);
}
Output on running:
Before modifying:
yoob blob: 1
newyoob blob: 1
After modifying:
yoob blob: 1
newyoob blob: 3
Struct memory addresses:
yoob address: 0x7fff3cd98d08
newyoob address: 0x7fff3cd98cb0
Is this code create a deep copy, as it appears, or am I misunderstanding what's happening here?
The shallow vs. deep copy problem is only relevant to pointers. Given a type struct foo:
struct foo a = /* initialize */;
struct foo b = a;
All the values in a are copied to b. They are not the same variable.
However, with pointers:
struct foo *p = calloc(1, sizeof *p);
struct foo *q = p;
q now points to the same memory as p; no copying has taken place (and you run the risk of a dangling pointer once one gets freed). This is a pointer alias. In order to do a shallow copy, one would do:
struct foo *p = calloc(1, sizeof *p);
/* assign to p's fields... */
struct foo *q = calloc(1, sizeof *q);
*q = *p;
Now q has the same field values as p but points to a different block of memory.
A deep copy requires additional effort; any pointers in the structure must be traversed and have their contents copied as well. See this post for a good explanation.
When you use newyoob = yoob; the compiler create code to copy the structure for you.
An important note about the copying: It's a shallow. That means if you have e.g. a structure containing pointers, it's only the actual pointers that will be copied and not what they point to, so after the copy you will have two pointers pointing to the same memory.
Your concept of "shallow copy" is wrong. The code
newyoob = yoob;
is in fact creating a shallow copy of yoob to newyoob. Your variables yoob and newyoob are separate memory allocations.
Now if you did this
struct tester* newyoob = &yoob;
Then newyoob and yoob are "the same" - but again, two variables referencing the same memory region is not considered a copy.
Suppose this
typedef struct tester {
int someInt;
char* someString;
} tester;
Shallow copying
Then you assign one instance to another:
tester a = {1, "hohohahah"};
tester b = a;
The members of a will be copied by value, including the pointer. This means:
a.someString == b.someString // True: comparing addresses and addresses are the same.
b is a shallow copy of a because the pointed members point to the same memory.
Deep copying
A deep copy means that the pointed members are also duplicated. It would go along these lines:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct tester {
int someInt;
char* someString;
} tester;
void deepcopy_tester(tester *in, tester *out) {
out->someInt = in->someInt;
out->someString = malloc(strlen(in->someString)+1);
strcpy(out->someString, in->someString);
}
int main() {
tester t1 = {1, "Yo"};
tester t2 = {0, NULL};
deepcopy_tester(&t1, &t2);
printf("%s\na", t2.someString);
}
This code should work, just tested with gcc.
I'm stuck, maybe on a very simple question.
In university we have to make our own malloc-function in C. I only have a problem when saving the pointer Address on the dereferenced pointer. Im working on heap and there is enough memory left.
void *actual_pointer = sbrk(sizeof(Node));
*(char*)actual_pointer = 'O';
actual_pointer = actual_pointer+sizeof(char);
*(char*)actual_pointer = 'K';
actual_pointer = actual_pointer+sizeof(unsigned int);
*(unsigned int*)actual_pointer = size;
actual_pointer = actual_pointer+sizeof(unsigned int);
*(unsigned int*)actual_pointer = 0;
actual_pointer = actual_pointer+sizeof(unsigned int);
*actual_pointer = actual_pointer;
The last line doesn't work. I tried everything. Isn't it possible to store some pointer Address to the dereferenced pointer?
typedef struct _Node_
{
char checkCorruption_[2];
unsigned int size_;
unsigned int status_;
char *location_;
struct Node *next_;
struct Node *prev_;
} Node;
This is the structure of my double-linked list representing the momory structure.
My Idea was the following:
We need to make a simple mallocfunction. From main function for example data[1] = malloc(100 * sizeof(int)) is called. Then I will create in the mallocfunction one Node and store the "checkCorruption"-Value 'OK' in it. After it the size, in my example "100 * sizeof(int)". After this I store a 0 for used or a 1 for free in it. Then I will store the location which is returned to data[0] - the storage gets reserved with sbrk(100*sizeof(int)) and begins at the location. Then i will store the Pointer to the next Node and the previous.
I always check the OK-value if some other malloc had an overflow and overwrited it - then i will exit with an error.
Is my Idea totally bullshit or is it ok?
Edit2:
When I will use now Node instead of void I can store also my location pointer to the node.
Node *actual_pointer = sbrk(sizeof(Node));
actual_pointer->checkCorruption_[1] = 'O';
printf("actual_pointer: %p\n", actual_pointer);
printf("actual_O: %c\n", actual_pointer->checkCorruption_[1]);
printf("actual_pointer_before: %p\n", actual_pointer);
actual_pointer = actual_pointer+sizeof(char);
printf("actual_pointer_after: %p\n", actual_pointer);
Output:
actual_pointer: 0x1ad4000
actual_O: O
actual_pointer_before: 0x1ad4000
actual_pointer_after: 0x1ad4028
But now I have some problems with actual_pointer = actual_pointer+sizeof(char);. This command should add the size of char to the actual_pointer but it increases the pointer with 40 bytes? I don't understand this?
Thanks in Advance,
Philipp
It is impossible to store value into a void...
Try replacing the last line with
*(unsigned int*)actual_pointer = (unsigned int*)actual_pointer
I'm reading a book on data structures and having difficulty grasping the concept of pointers. Let me preface this by saying that I don't have a lot of experience with C. But here goes....
If I do the following:
int num = 5;
int *ptrNum;
ptrNum = #
It is my understanding that the pointer reserves enough memory for a 32 bit int along with the memory required for the actual pointer although its value is simply the memory address of the variable.
What is the purpose of doing this if the same amount of memory is reserved? Why would I use the pointer instead of the variable, num? Am I totally off base here?
You use pointers in situations where a value won't work. In your example, you're correct; there's no benefit. The archtetypal border-line useful example is a swap function:
void swap_int(int *i1, int *i2)
{
int t1 = *i1;
*i1 = *i2;
*i2 = t1;
}
Calling sequence:
int main(void)
{
int v1 = 0;
int v2 = 31;
printf("v1 = %d; v2 = %d\n", v1, v2);
swap_int(&v1, &v2);
printf("v1 = %d; v2 = %d\n", v1, v2);
return 0;
}
If you write that without using pointers — like this:
void swap_int(int i1, int i2)
{
int t1 = i1;
i1 = i2;
i2 = t1;
}
int main(void)
{
int v1 = 0;
int v2 = 31;
printf("v1 = %d; v2 = %d\n", v1, v2);
swap_int(v1, v2);
printf("v1 = %d; v2 = %d\n", v1, v2);
return 0;
}
then you simply swap two local variables in the function without affecting the values in the calling function. Using pointers, you can affect the variables in the calling function.
See also:
scanf()-family of functions
strcpy() et al
It is my understanding that the pointer reserves enough memory for a 32 bit int along with the memory required for the actual pointer although its value is simply the memory address of the variable.
What you appear to be describing is as if:
int *p1;
does the same job as:
int _Anonymous;
int *p1 = &_Anonymous;
It doesn't; this is C. Creating p1 allocates enough space for the pointer. As first written, it doesn't initialize it, so it points to an indeterminate location (or no location). It (the pointer) needs to be initialized before it is used. Hence:
int i1 = 37;
int *p1 = &i1;
But the allocation of p1 only reserves enough space for a pointer (normally, 32-bits for a 32-bit compilation, 64-bits for a 64-bit compilation); you have to allocate the space it points at separately, and you have to initialize the pointer. Another way of initializing pointers is with dynamically allocated memory:
int *p2 = malloc(1000 * sizeof(*p2));
if (p2 != 0)
{
...use p2 as an array of 1000 integers...
free(p2);
}
Have you covered structures yet? If not, examples covering structures, such as trees or linked lists, won't help. However, once you have covered structures too, you'll be able to use trees or linked lists:
struct list
{
int data;
struct list *next;
};
struct tree
{
int data;
struct tree *l_child;
struct tree *r_child;
};
Such structures rely heavily on pointers to connect entries correctly.
A couple of the other answers focus on taking the address of a variable and storing it in a pointer. That's only one use for pointers. An entirely different use for pointers is to point to dynamically allocated storage, and for structuring that storage.
For example, suppose you want to read in a file and work on it in memory. But, you don't know how big the file is ahead of time. You could put an arbitrary upper limit in your code:
#define MAX_FILE_SIZE (640 * 1024) /* 640K should be large enough for anyone */
char data[ MAX_FILE_SIZE ];
That wastes memory for smaller files, and isn't large enough for larger files. A better approach would be to actually allocate what you need. For example:
FILE *f = fopen("myfile", "rb");
off_t len;
char *data;
fseek(f, 0, SEEK_END); /* go to the end of the file */
len = ftell(f); /* get the actual file size */
fseek(f, 0, SEEK_SET); /* rewind to the beginning */
data = malloc( len ); /* Allocate just as much as you need */
Another major use of pointers is to structure data, say in lists, or trees, or other fun structures. (Your data structures book will go into many of these.) If you want to reorganize your data, moving pointers is often much cheaper than copying data around. For example, suppose you have a list of these:
struct mystruct
{
int x[1000];
int y[1000];
};
That's a lot of data. If you just store that in an array, then sorting that data might be very expensive:
struct mystruct array[1000];
Try qsort on that... it will be very slow.
You can speed this up by instead storing pointers to elements and sorting the pointers. ie.
struct mystruct *array[1000];
int i;
struct mystruct *temp;
/* be sure to allocate the storage, though: */
temp = malloc( 1000 * sizeof( struct mystruct ) );
for (i = 0; i < 1000; i++)
array[i] = temp + i;
Now if you had to sort those structures, you'd swap pointers in array[] rather than entire structures.
I won't go into the fancier data structures that are better covered by your book. But, I thought I might give you a taste of some other uses for pointers.
How would add an element to a dynamic list? By creating a new array each time?
You just add pointer to next element instead and link the previous cell's next pointer to it.
Without pointers, you are constrained to order of arrays and alignment of variables.
With pointers, you can select any address in the allocated area to have any alignment of you like, you can have list elements pointing to and from any area you allocated.
So, pointers give you more freedom while needing only 32 or 64 bit space per pointer.
Pointers serve 3 main purposes in C:
Fake pass-by-reference semantics;
Track dynamically-allocated memory;
Build dynamic data structures.
Fake pass-by-reference semantics: in C, all function arguments are passed by value. Given the following snippet:
void foo( int a, int b )
{
a = 1;
b = 2;
}
void bar( void )
{
int x=0, y=1;
foo( x, y );
printf( "x = %d, y = %d\n", x, y );
}
The formal parameters a and b in foo are different objects in memory from the actual parameters x and y in bar, so any changes to a and b are not reflected in x and y. The output will be "x = 0, y = 1". If you want foo to alter the values of x and y, you will need to pass pointers to those variables instead:
void foo( int *a, int *b )
{
*a = 1;
*b = 2;
}
void bar( void )
{
int x = 0, y = 1;
foo( &x, &y );
printf( "x = %d, y = %d\n", x, y );
}
This time, the formal parameters a and b are pointers to the variables x and y; writing to the expressions *a and *b int foo is equivalent to writing to x and y in bar. Thus, the output is "x = 1, y = 2".
This is how scanf() and scores of other library functions work; they use pointers to reference the actual memory we want to operate on.
Track dynamically allocated memory: The library functions malloc, calloc, and realloc allow us to allocate memory at runtime, and all three return pointers to the allocated memory (as of C89, all three return void *). For example, if we want to allocate an array of int at run time:
int *p = NULL;
size_t numItems;
// get numItems;
p = malloc( sizeof *p * numItems );
if ( p )
{
// do stuff with p[0] through p[numItems - 1];
}
free( p );
The pointer variable p will contain the address of the newly allocated block of memory large enough to hold numItems integers. We can access that memory by dereferencing p using either the * operator or the [] subscript operator (*(p+i) == p[i]).
So why not just declare an array of size numItems and be done with it? After all, as of C99, you can use a variable-length array, where the size doesn't have to be known until runtime:
// get numItems
int p[numItems];
Three reasons: first, VLA's are not universally supported, and as of the 2011 standard, VLA support is now optional; second, we cannot change the size of the array after it has been declared, whereas we can use realloc to resize the memory block we've allocated; and finally, VLAs are limited both in where they can be used and how large they can be - if you need to allocate a lot of memory at runtime, it's better to do it through malloc/calloc/realloc than VLAs.
A quick note on pointer arithmetic: for any pointer T *p, the expression p+1 will evaluate to the address of the next element of type T, which is not necessariy the address value + 1. For example:
T sizeof T Original value of p p + 1
- -------- ------------------- -----
char 1 0x8000 0x8001
int 4 0x8000 0x8004
double 8 0x8000 0x8008
Build dynamic data structures: There are times when we want to store data in such a way that makes it easy to insert new elements into a list, or quickly search for a value, or force a specific order of access. There are a number of different data structures used for these purposes, and in almost all cases they use pointers. For example, we can use a binary search tree to organize our data in such a way that searching for a particular value is pretty fast. Each node in the tree has two children, each of which points to the next element in the tree:
struct node {
T key;
Q data;
struct node *left;
struct node *right;
};
The left and right members point to other nodes in the tree, or NULL if there is no child. Typically, the left child points to a node whose value is somehow "less than" the value of the current node, while the right child points to a node whose value is somehow "greater than" the current node. We can search the tree for a value like so:
int find( struct node *root, T key, Q *data )
{
int result = 0;
if ( root == NULL ) // we've reached the bottom of the tree
{ // without finding anything
result = 0;
}
else if ( root->key == key ) // we've found the element we're looking for
{
*data = root->data;
result = 1;
}
else if ( root->key < key )
{
// The input key is less than the current node's key,
// so we search the left subtree
result = find( root->left, key, data );
}
else
{
// The input key is greater than the current node's key,
// so we search the right subtree
result = find( root->right, key, data );
}
return result;
}
Assuming the tree is balanced (that is, the number of elements in the left subtree is equal to the number of elements in the right subtree), then the number of elements checked is around log2 N, where N is the total number of elements in the tree.
I have below code. In below code the value 5 gets stored in variable a(i.e abc.a). But I would like to intialize the value in c (i.e abc.c). How to do that? My requirement is to fill the data for c not for a.
typedef struct abc
{
int a;
int b;
int c;
}abc;
typedef struct def{
int *ptr;
abc strpt;
}def;
typedef struct xyz{
int *pointer;
}xyz;
int main()
{
int *temp, tmp;
abc* ab;
tmp = 5;
temp = &tmp;
ab = (abc*)malloc(sizeof(abc));
xyz *x = (xyz*)malloc(sizeof(xyz));
def *de = (def*)malloc(sizeof(def));
x->pointer = (xyz*)temp;
ab = (abc*)x->pointer;
return 0;
}
Please help me.
I'm Affraid some serious lack of understanding pointers manifests in your code. Let me dissect it line by line to make clear where problems occur.
I numbered the statements in order to make easy references, assuming the type declarations as above.
int main()
{
int *temp, tmp;
abc* ab;
/* 1 */ tmp = 5;
/* 2 */ temp = &tmp;
/* 3 */ ab = (abc*)malloc(sizeof(abc));
/* 4 */ xyz *x = (xyz*)malloc(sizeof(xyz));
/* 5 */ def *de = (def*)malloc(sizeof(def));
/* 6 */ x = (xyz*)temp;
/* 7 */ ab = (abc*)x;
return 0;
}
First of all: You never clean up the memory allocated in 3, 4 and 5. Even for a simple test program, you should always take care of stuff like this.
Your first problem is line 6 where you blindly cast a pointer to an object of type int (4 bytes in memory) into a pointer to a structure of type xyz (4 or 8 bytes in memory, different type). What you do here is a complicated way to write x = (xyz*)&tmp;.
An action like that leads to following serious problems:
You just allocated memory in line 4. Now you overwrite this pointer with a pointer to your stack variable. Therefore you can't free the allocated memory anymore ==> Memory leak
Your newly assigned pointer to the stack variable becomes invalid after exiting the scope and can cause undefined behaviour.
Any write attempt to elements of x after line 6 can lead to corruption of the stack (and therefore undefined behaivour) due to a possible size mismatch of elements.
By line 7 you get the same problems again and even worse. The estimated sizeof(abc) is possibly 12 bytes. Accessing any element of abc after this line can lead to stack corruption again.
I still don't understand what you really are looking for but if you "have to" initialize a structure element through pointers there are a several ways:
If the struct ist known you can do it like this:
abc * ab = malloc(sizeof(abc));
if (ab != NULL) {
ab->c = 5;
// -- do other stuff
free(ab); ab = NULL;
}
If you need a pointer to the element 'c' you can do it like this:
int * c_ptr = NULL;
abc * ab = malloc(sizeof(abc));
if (ab != NULL) {
c_ptr = &(ab->c);
*c_ptr = 5;
//-- do other stuff
free(ab); ab = NULL;
}
Are you asking for this:
abc s;
s.c = 5;
That makes c 5. Or you could do thos:
abc s = {0,0,5};
That means, the first two members are initialized to 0, and third one (which is c) is initialized to 5.
Or if you've pointer, then you can do this:
abc *p = malloc(etc);
p->c = 5;
But then avoid using pointers and malloc. Use it when you really need them. In your code, I don't see any reason why you would need it. Use automatic variables, not pointers.
I think you would need to add this before return in your main() to get what you need.
ab->c = *(x->pointer);