can i use "int" as my dynamic array inside a struct? - c

In general, i'm trying to allocate values of first.a and first.b
to a array's in struct secon.
typedef struct {
int a;
int b;
} firs;
//secon is my struct which contains dynamic array
//can i use int here ?
typedef struct {
int *aa;
int *bb;
} secon;
//pointer to secon intialised to NULL;
secon* sp=NULL;
int main()
{
firs first;
//plz assume 2 is coming from user ;
sp=malloc(sizeof(secon)*2);
//setting values
first.a=10;
first.b=11;
/* what i'm trying to do is assign values of first.a and first.b to my
dynamically created array*/
/* plz assume first.a and first.b are changing else where .. that means ,not
all arrays will have same values */
/* in general , i'm trying to allocate values of first.a and first.b
to a array's in struct second. */
for(int i=0; i<2; i++) {
*( &(sp->aa ) + (i*4) ) = &first.a;
*( &(sp->bb ) + (i*4) ) = &first.b;
}
for(int i=0; i<2; i++) {
printf("%d %d \n", *((sp->aa) + (i*4) ),*( (sp->bb) +(i*4) ) );
}
return 0;
}
MY output :
10 11
4196048 0
Problems with my code:
1. whats wrong with my code?
2. can i use int inside struct for dynamic array?
3. what are the alternatives?
4. why am i not getting correct answer?

Grigory Rechistov has done a really good job of untangling the code and you should probably accept his answer, but I want to emphasize one particular point.
In C pointer arithmetic, the offsets are always in units of the size of the type pointed to. Unless the type of the pointer is char* or void* if you find yourself multiplying by the size of the type, you are almost certainly doing it wrong.
If I have
int a[10];
int *p = &(a[5]);
int *q = &(a[7]);
Then a[6] is the same as *(p + 1) not *(p + 1 * sizeof(int)). Likewise a[4] is *(p - 1)
Furthermore, you can subtract pointers when they both point to objects in the same array and the same rule applies; the result is in the units of the size of the type pointed to. q - p is 2, not 2 * sizeof(int). Replace the type int in the example with any other type and the p - q will always be 2. For example:
struct Foo { int n ; char x[37] ; };
struct Foo a[10];
struct Foo *p = &(a[5]);
struct Foo *q = &(a[7]);
q - p is still 2. Incidentally, never be tempted to hard code a type's size anywhere. If you are tempted to malloc a struct like this:
struct Foo *r = malloc(41); // int size is 4 + 37 chars
Don't.
Firstly, sizeof(int) is not guaranteed to be 4. Secondly, even if it is, sizeof(struct Foo) is not guaranteed to be 41. Compilers often add padding to struct types to ensure that the members are properly aligned. In this case it is almost a certainty that the compiler will add 3 bytes (or 7 bytes) of padding to the end of struct Foo to ensure that, in arrays, the address of the n member is aligned to the size of an int. always always always use sizeof.

It looks like your understanding how pointer arithmetic works in C is wrong. There is also a problem with data layout assumptions. Finally, there are portability issues and a bad choice of syntax that complicates understanding.
I assume that wit this expression: *( &(sp->aa ) + (i*4) ) you are trying to access the i-th item in the array by taking address of the 0-th item and then adding a byte offset to it. This is wrong of three reasons:
You assume that after sp[0].aa comes sp[1].aa in memory, but you forget that there is sp[0].bb in between.
You assume that size of int is always 4 bytes, which is not true.
You assume that adding an int to secon* will give you a pointer that is offset by specified number of bytes, while in fact it will be offset in specified number of records of size secon.
The second line of output that you see is random junk from unallocated heap memory because when i == 1 your constructions reference memory that is outside of limits allocated for *secon.
To access an i-th item of array referenced by a pointer, use []:
secon[0].aa is the same as (secon +0)->aa, and secon[1].aa is equal to (secon+1)->aa.

This is a complete mess. If you want to access an array of secons, use []
for(int i=0;i<2;i++)
{
sp[i].aa = &first.a; // Same pointer both times
sp[i].bb = &first.b;
}
You have two copies of pointers to the values in first, they point to the same value
for(int i=0;i<2;i++)
{
sp[i].aa = malloc(sizeof(int)); // new pointer each time
*sp[i].aa = first.a; // assigned with the current value
sp[i].bb = malloc(sizeof(int));
*sp[i].bb = first.b;
}
However the compiler is allowed to assume that first does not change, and it is allowed to re-order these expressions, so you are not assured to have different values in your secons
Either way, when you read back the values in second, you can still use []
for(int i=0;i<2;i++)
{
printf("%d %d \n",*sp[i].aa ),*sp[i].bb );
}

Related

Assigning the value of a pointer at a certain index in C

I'm trying to understand this code:
struct mys {
double d[128];
};
void my_func(int iters) {
int i;
struct mys *ptr = malloc(iters *sizeof(struct mys));
for(i = 0; i < iters; i++) {
ptr[i].d[0] = (double)i;
}
free(ptr);
}
What I know:
mys is of size 8 * 128 (size of double is 8, it's an array of 128 doubles)
*ptr is of size iters * (8 * 128)
What is going on here:
ptr[i].d[0] = (double)i;
?
What I know:
// ptr->d is the address of the first part of d
// same as (*ptr).d
// BECAUSE d IS A STRUCT
// ptr->d[i] is the actual value. so, 0.0000
// same as (*ptr).d[i]
Thanks in advance.
ptr[i] is the value at index i, so starts at 0.0000.
d is not initialized, it is just the name of the member of a struct. How can we just d here?
What I think:
*ptr is multiple (iters) structs.
So, ptr[0] is the first struct, ptr[1] is the second struct, etc.
ptr[i].d access the ith struct's d array.
ptr[i].d[0] accesses the first index of the d array. So the line above sets that number to double(i).
So this really only sets the first element of each struct to be 0. Am I right?
But when iters is 2, and I try:
for(int i = 0; i < iters; i++) {
printf("%p\n", ptr[200].d);
}
it still prints an address. Why is that?
What is going on here: ptr[i].d[0] = (double)i;?
This:
struct mys *ptr = malloc(iters *sizeof(struct mys));
allocates memory for an array of structs, called ptr.
This line of code:
ptr[i].d[0] = (double)i;
assigns i to the first cell of the array d, of the i-th struct, in the array ptr.
i is casted to double, because d is an array of doubles, and i is declared as int.
when iters is 2, and I try: for(int i = 0; i < iters; i++) { printf("%p\n", ptr[200].d); } it still prints an address. Why is that? Shouldn't it be out of range since ptr is only 2 structs?
This is definitely out of range, since arrays are 0-indexed.
However, that attempt invokes Undefined Behavior (UB), which means that you don't know how the code is going to behave. For example, in your computer it prints an address, in my computer it might cause a segmentation fault, and so on...
So this really only sets the first element of each struct to be 0. Am I right?
It copies the index i, converted to type double, into the first element of each struct. Otherwise you are right.
Regarding the expression ptr[200].d, this is the same as &(ptr[200]) because the array d[] is the sole element of a mys object. Because a double is eight bytes wide, each mys object occupies (8 bytes)(128) = 1 kiB. Therefore, &(ptr[200]) == ptr + 200*1024. The last is an address 200 kiB past the beginning of *ptr. Whether the address has meaning depends on whether anything meaningful is stored there.

Use array annotation with pointers

I have currently trouble understanding the following scenario:
I have a multidimensional array of Strings and I want to address it by using pointers only but I always get a Segmentation Fault when using the array annotation on the pointer. This is just an example code I want to use the 3D array in a pthread so I want to pass it in via a structure as a pointer but it just doesn't work and I would like to know why? I thought pointers and arrays are functionally equivalent? Here is the sample code:
#include <stdio.h>
void func(unsigned char ***ptr);
int main() {
// Image of dimension 10 times 10
unsigned char image[10][10][3];
unsigned char ***ptr = image;
memcpy(image[0][0], "\120\200\12", 3);
// This works as expected
printf("Test: %s", image[0][0]);
func(image);
return 0;
}
void func(unsigned char ***ptr) {
// But here I get a Segmentation Fault but why??
printf("Ptr: %s", ptr[0][0]);
}
Thanks in advance for your help :)
I think maybe strdup confuses the issue. Pointers and arrays are not always equivalent. Let me try to demonstrate. I always avoid actual multi-dimension arrays, so I may make a mistake here, but:
int main()
{
char d3Array[10][10][4]; //creates a 400-byte contiguous memory area
char ***d3Pointer; //a pointer to a pointer to a pointer to a char.
int i,j;
d3Pointer = malloc(sizeof(char**) * 10);
for (i = 0; i < 10; ++i)
{
d3Pointer[i] = malloc(sizeof(char*) * 10);
for (j = 0; j < 4; ++j)
{
d3Pointer[i][j] = malloc(sizeof(char) * 4);
}
}
//this
d3Pointer[2][3][1] = 'a';
//is equivalent to this
char **d2Pointer = d3Pointer[2];
char *d1Pointer = d2Pointer[3];
d1Pointer[1] = 'a';
d3Array[2][3][1] = 'a';
//is equivalent to
((char *)d3Array)[(2 * 10 * 4) + (3 * 4) + (1)] = 'a';
}
Generally, I use the layered approach. If I want contiguous memory, I handle the math myself..like so:
char *psuedo3dArray = malloc(sizeof(char) * 10 * 10 * 4);
psuedo3dArray[(2 * 10 * 4) + (3 * 4) + (1)] = 'a';
Better yet, I use a collection library like uthash.
Note that properly encapsulating your data makes the actual code incredibly easy to read:
typedef unsigned char byte_t;
typedef struct
{
byte_t r;
byte_t g;
byte_t b;
}pixel_t;
typedef struct
{
int width;
int height;
pixel_t * pixelArray;
}screen_t;
pixel_t *getxyPixel(screen_t *pScreen, int x, int y)
{
return pScreen->pixelArray + (y*pScreen->width) + x;
}
int main()
{
screen_t myScreen;
myScreen.width = 1024;
myScreen.height = 768;
myScreen.pixelArray = (pixel_t*)malloc(sizeof(pixel_t) * myScreen.height * myScreen.width);
getxyPixel(&myScreen, 150, 120)->r = 255;
}
In C, you should allocate space for your 2D array one row at a time. Your definition of test declares a 10 by 10 array of char pointers, so you don't need to call malloc for it. But to store a string you need to allocate space for the string. Your call to strcpy would crash. Use strdup instead. One way to write your code is as follows.
char ***test = NULL;
char *ptr = NULL;
test = malloc(10 * sizeof(char **));
for (int i = 0; i < 10; i++) {
test[i] = malloc(10 * sizeof(char *));
}
test[0][0] = strdup("abc");
ptr = test[0][0];
printf("%s\n", ptr);
test[4][5] = strdup("efg");
ptr = test[4][5];
printf("%s\n", ptr);
Alternatively, if you want to keep your 10 by 10 definition, you could code it like this:
char *test[10][10];
char *ptr = NULL;
test[0][0] = strdup("abc");
ptr = test[0][0];
printf("%s\n", ptr);
test[4][5] = strdup("efg");
ptr = test[4][5];
printf("%s\n", ptr);
Your problem is, that a char[10][10][3] is something very different from a char***: The first is an array of arrays of arrays, the later is a pointer to a pointer to a pointer. The confusions arises because both can be dereferenced with the same syntax. So, here is a bit of an explanation:
The syntax a[b] is nothing but a shorthand for *(a + b): First you perform pointer arithmetic, then you dereference the resulting pointer.
But, how come you can use a[b] when a is an array instead of a pointer? Well, because...
Arrays decay into pointers to their first element: If you have an array declared like int array[10], saying array + 3 results in array decaying to a pointer of type int*.
But, how does that help to evaluate a[b]? Well, because...
Pointer arithmetic takes the size of the target into account: The expression array + 3 triggers a calculation along the lines of (size_t)array + 3*sizeof(*array). In our case, the pointer that results from the array-pointer-decay points to an int, which has a size, say 4 bytes. So, the pointer is incremented by 3*4 bytes. The result is a pointer that points to the fourths int in the array, the first three elements are skipped by the pointer arithmetic.
Note, that this works for arrays of any element type. Arrays can contain bytes, or integers, or floats, or structs, or other arrays. The pointer arithmetic is the same.
But, how does that help us with multidimensional arrays? Well, because...
Multidimensional arrays are just 1D arrays that happen to contain arrays as elements: When you declare an array with char image[256][512]; you are declaring a 1D array of 256 elements. These 256 elements are all arrays of 512 characters, each. Since the sizeof(char) == 1, the size of an element of the outer array is 512*sizeof(char) = 512, and, since we have 256 such arrays, the total size of image is 256*512. Now, I can declare a 3D array with char animation[24][256][512];...
So, going back to your example that uses
char image[10][10][3]
what happens when you say image[1][2][1] is this: The expression is equivalent to this one:
*(*(*(image + 1) + 2) + 3)
image being of type char[10][10][3] decays into a pointer to its first element, which is of type char(*)[10][3] The size of that element is 10*3*1 = 30 bytes.
image + 1: Pointer arithmetic is performed to add 1 to the resulting pointer, which increments it by 30 bytes.
*(image + 1): The pointer is dereferenced, we are now talking directly about the element, which is of type char[10][3].
This array again decays into a pointer to its first element, which is of type char(*)[3]. The size of the element is 3*1 = 3. This pointer points at the same byte in memory as the pointer that resulted from step 2. The only difference is, that it has a different type!
*(image + 1) + 2: Pointer arithmetic is performed to add 2 to the resulting pointer, which increments it by 2*3 = 6 bytes. Together with the increment in step 2, we now have an offset of 36 bytes, total.
*(*(image + 1) + 2): The pointer is dereferenced, we are now talking directly about the element, which is of type char[3].
This array again decays into a pointer to its first element, which is of type char*. The size of the element is now just a single byte. Again, this pointer has the same value as the pointer resulting from step 5, but a different type.
*(*(image + 1) + 2) + 1: Pointer arithmetic again, adding 1*1 = 1 bytes to the total offset, which increases to 37 bytes.
*(*(*(image + 1) + 2) + 1): The pointer is dereferenced the last time, we are now talking about the char at an offset of 37 bytes into the image.
So, what's the difference to a char***? When you dereference a char***, you do not get any array-pointer-decay. When you try to evaluate the expression pointers[1][2][1] with a variable declared as
char*** pointers;
the expression is again equivalent to:
*(*(*(pointers + 1) + 2) + 3)
pointers is a pointer, so no decay happens. Its type is char***, and it points to a value of type char**, which likely has a size of 8 bytes (assuming a 64 bit system).
pointers + 1: Pointer arithmetic is performed to add 1 to the resulting pointer, which increments it by 1*8 = 8 bytes.
*(pointers + 1): The pointer is dereferenced, we are now talking about the pointer value that is found in memory at an offset of 8 bytes of where pointers points.
Further steps depending on what actually happened to be stored at pointers[1]. These steps do not involve any array-pointer-decay, and thus load pointers from memory instead.
You see, the difference between a char[10][10][3] and a char*** is profound. In the first case, the array-pointer-decay transforms the process into a pure offset computation into a multidimensional array. In the later case, we repeatedly load pointers from memory when accessing elements, all we ever have are 1D arrays of pointers. And it's all down to the types of pointers!

Understanding the purpose of pointers

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 = &num;
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.

Pointer to struct elements

I need to write a function that sums monoms with the same power,
the monoms are defined by the following struct:
typedef struct monom {
int coefficient;
int power;
}MONOM;
And the function I wrote from the job is:
int sumMonomsWithSamePower(MONOM** polynomial, int size)
{
int i, powerIndex = 0;
for (i = 0; i < size; i++)
{
if ((polynomial[powerIndex])->power == (polynomial[i])->power)
{
if (powerIndex != i)
(polynomial[powerIndex])->coefficient += (polynomial[i])->coefficient;
}
else
powerIndex++;
}
powerIndex++;
*polynomial = (MONOM*)realloc(polynomial, powerIndex);
return powerIndex;
}
Which is being called with the following call:
*polySize = sumMonomsWithSamePower(&polynomial, logSize);
polynomial array is being sent to the function as a sorted array of MONOMs (sorted ascending by powers).
My problem is that on the 7th line of sumMonomsWithSamePower() the function crashes since it can't see the elements in the array by the following way. When I put the elements of the array in Watch list in my debugger I also can't see them using polynomial[i], but if I use (polynomial[0]+i) I can see them clearly.
What is going on here?
I assume outside sumMonomsWithSamePower() you have allocated polynomial with something like polynomial = malloc( size * sizeof(MONOM) ); (everything else wouldn't be consistant to your realloc()). So you have an array of MONOMs and the memory location of polynomial[1] is polynomial[0] + sizeof(MONOM) bytes.
But now look at polynomial in sumMonomsWithSamePower() In the following paragraph I will rename it with ppoly (pointer to polynomial) to avoid confusing it with the original array: here it is a MONOM **, so ppoly[1] addresses the sizeof(MONOM *) bytes at the memory location ppoly[0] + sizeof(MONOM *) and interpretes them as pointer to a MONOM structure. But you have an array of structs, not an array of pointers. Replace your expressions by (*ppoly)[i].power (and all the others accordingly of course) and that part will work. By the way that's excactly the difference of the two debugger statements you have mentioned.
Besides, look at my comments concerning the use of powerIndex

Is this code doing what I want it to do?

I want to create an integer pointer p, allocate memory for a 10-element array, and then fill each element with the value of 5. Here's my code:
//Allocate memory for a 10-element integer array.
int array[10];
int *p = (int *)malloc( sizeof(array) );
//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %d\n", sizeof(array));
while (i < sizeof(array)){
*p = 5;
printf("Current value of array: %p\n", *p);
*p += sizeof(int);
i += sizeof(int);
}
I've added some print statements around this code, but I'm not sure if it's actually filling each element with the value of 5.
So, is my code working correctly? Thanks for your time.
First:
*p += sizeof(int);
This takes the contents of what p points to and adds the size of an integer to it. That doesn't make much sense. What you probably want is just:
p++;
This makes p point to the next object.
But the problem is that p contains your only copy of the pointer to the first object. So if you change its value, you won't be able to access the memory anymore because you won't have a pointer to it. (So you should save a copy of the original value returned from malloc somewhere. If nothing else, you'll eventually need it to pass to free.)
while (i < sizeof(array)){
This doesn't make sense. You don't want to loop a number of times equal to the number of bytes the array occupies.
Lastly, you don't need the array for anything. Just remove it and use:
int *p = malloc(10 * sizeof(int));
For C, don't cast the return value of malloc. It's not needed and can mask other problems such as failing to include the correct headers. For the while loop, just keep track of the number of elements in a separate variable.
Here's a more idiomatic way of doing things:
/* Just allocate the array into your pointer */
int arraySize = 10;
int *p = malloc(sizeof(int) * arraySize);
printf("Size of array: %d\n", arraySize);
/* Use a for loop to iterate over the array */
int i;
for (i = 0; i < arraySize; ++i)
{
p[i] = 5;
printf("Value of index %d in the array: %d\n", i, p[i]);
}
Note that you need to keep track of your array size separately, either in a variable (as I have done) or a macro (#define statement) or just with the integer literal. Using the integer literal is error-prone, however, because if you need to change the array size later, you need to change more lines of code.
sizeof of an array returns the number of bytes the array occupies, in bytes.
int *p = (int *)malloc( sizeof(array) );
If you call malloc, you must #include <stdlib.h>. Also, the cast is unnecessary and can introduce dangerous bugs, especially when paired with the missing malloc definition.
If you increment a pointer by one, you reach the next element of the pointer's type. Therefore, you should write the bottom part as:
for (int i = 0;i < sizeof(array) / sizeof(array[0]);i++){
*p = 5;
p++;
}
*p += sizeof(int);
should be
p += 1;
since the pointer is of type int *
also the array size should be calculated like this:
sizeof (array) / sizeof (array[0]);
and indeed, the array is not needed for your code.
Nope it isn't. The following code will however. You should read up on pointer arithmetic. p + 1 is the next integer (this is one of the reasons why pointers have types). Also remember if you change the value of p it will no longer point to the beginning of your memory.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define LEN 10
int main(void)
{
/* Allocate memory for a 10-element integer array. */
int array[LEN];
int i;
int *p;
int *tmp;
p = malloc(sizeof(array));
assert(p != NULL);
/* Fill each element with the value of 5. */
printf("Size of array: %d bytes\n", (int)sizeof(array));
for(i = 0, tmp = p; i < LEN; tmp++, i++) *tmp = 5;
for(i = 0, tmp = p; i < LEN; i++) printf("%d\n", tmp[i]);
free(p);
return EXIT_SUCCESS;
}
//Allocate memory for a 10-element integer array.
int array[10];
int *p = (int *)malloc( sizeof(array) );
At this point you have allocated twice as much memory -- space for ten integers in the array allocated on the stack, and space for ten integers allocated on the heap. In a "real" program that needed to allocate space for ten integers and stack allocation wasn't the right thing to do, the allocation would be done like this:
int *p = malloc(10 * sizeof(int));
Note that there is no need to cast the return value from malloc(3). I expect you forgot to include the <stdlib> header, which would have properly prototyped the function, and given you the correct output. (Without the prototype in the header, the C compiler assumes the function would return an int, and the cast makes it treat it as a pointer instead. The cast hasn't been necessary for twenty years.)
Furthermore, be vary wary of learning the habit sizeof(array). This will work in code where the array is allocated in the same block as the sizeof() keyword, but it will fail when used like this:
int foo(char bar[]) {
int length = sizeof(bar); /* BUG */
}
It'll look correct, but sizeof() will in fact see an char * instead of the full array. C's new Variable Length Array support is keen, but not to be mistaken with the arrays that know their size available in many other langauges.
//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %d\n", sizeof(array));
while (i < sizeof(array)){
*p = 5;
*p += sizeof(int);
Aha! Someone else who has the same trouble with C pointers that I did! I presume you used to write mostly assembly code and had to increment your pointers yourself? :) The compiler knows the type of objects that p points to (int *p), so it'll properly move the pointer by the correct number of bytes if you just write p++. If you swap your code to using long or long long or float or double or long double or struct very_long_integers, the compiler will always do the right thing with p++.
i += sizeof(int);
}
While that's not wrong, it would certainly be more idiomatic to re-write the last loop a little:
for (i=0; i<array_length; i++)
p[i] = 5;
Of course, you'll have to store the array length into a variable or #define it, but it's easier to do this than rely on a sometimes-finicky calculation of the array length.
Update
After reading the other (excellent) answers, I realize I forgot to mention that since p is your only reference to the array, it'd be best to not update p without storing a copy of its value somewhere. My little 'idiomatic' rewrite side-steps the issue but doesn't point out why using subscription is more idiomatic than incrementing the pointer -- and this is one reason why the subscription is preferred. I also prefer the subscription because it is often far easier to reason about code where the base of an array doesn't change. (It Depends.)
//allocate an array of 10 elements on the stack
int array[10];
//allocate an array of 10 elements on the heap. p points at them
int *p = (int *)malloc( sizeof(array) );
// i equals 0
int i = 0;
//while i is less than 40
while (i < sizeof(array)){
//the first element of the dynamic array is five
*p = 5;
// the first element of the dynamic array is nine!
*p += sizeof(int);
// incrememnt i by 4
i += sizeof(int);
}
This sets the first element of the array to nine, 10 times. It looks like you want something more like:
//when you get something from malloc,
// make sure it's type is "____ * const" so
// you don't accidentally lose it
int * const p = (int *)malloc( 10*sizeof(int) );
for (int i=0; i<10; ++i)
p[i] = 5;
A ___ * const prevents you from changing p, so that it will always point to the data that was allocated. This means free(p); will always work. If you change p, you can't release the memory, and you get a memory leak.

Resources