Passing a pointer to dynamic array - c

Is it a right way to pass a pointer to dynamic array? Is it going to work? If not, explain why, if it does, explain why as well. Thank you.
struct record
{
char * community_name;
double data[10];
double crimes_per_pop;
};
void allocate_struct_array(struct record *** r);
int main()
{
/* allocating pointer to an array of pointers */
struct record ** r;
/* passing its address to a function */
allocate_struct_array( &(**r) );
}
/* function gets an address */
void allocate_struct_array(struct record *** r)
{
...
}
What I was trying to do is to allocate an array of pointers, where each pointer points to structure record. Function suppose to allocate this array using just pointer to r, which was declared in main. Was playing with this code, but cannot make it to work.

I don't know what you are trying to do, but at least you have a programmatic error.
allocate_struct_array( &(**r) );
needs to be -
allocate_struct_array(&r);

In the function interface, you only need a double pointer struct record **r and not a triple pointer.
An array can be represented by a struct record *array; so a pointer to that is struct record **ptr_to_array.
You call the function with &array.
struct record
{
char * community_name;
double data[10];
double crimes_per_pop;
};
void allocate_struct_array(struct record **r);
int main()
{
struct record *r;
allocate_struct_array(&r);
}
void allocate_struct_array(struct record **r)
{
*r = malloc(23 * sizeof(struct record));
...
}

Related

Struct with pointer to function

can you please explain in details this line of code inside struct:
There is a pointer to function but why would you reference it to struct?
void (*function)(struct Structure *);
what does this mean
(struct Structure *)?
(struct Structure *)
It means that the function have a struct Structure * argument. Actually it will make more sense with (struct Structure *variable of struct).
In this way, you can use a pointer to point a struct and should put the address of the struct variable which can be used in the function.
#include <stdio.h>
typedef struct circle{
int rad;
int area;
} Circle;
void ShowCircleInfo(Circle *info)
{
printf("rad value: %d\n", info->rad);
printf("area value: %d", info->area);
}
int main(void)
{
Circle circle_one;
circle_one.rad = 2;
circle_one.area = 3;
ShowCircleInfo(&circle_one);
return 0;
}
void (*function)(struct Structure *); declares function to be a pointer to a function that has a parameter of type struct Structure * and does not return a value.
For example
#include <stdio.h>
struct Structure {
int a;
void (*function)(struct Structure *);
};
void foo(struct Structure *a) {
if (a->function == NULL) a->function = foo;
a->a++;
printf("%d\n", a->a);
}
int main(void) {
struct Structure a = {42, foo};
struct Structure b = {0}; // don't call b.function just yet!!
a.function(&b); // foo(&b)
b.function(&a); // foo(&a)
}
See code running at https://ideone.com/7E74gb
In C, function pointer declarations have almost the same structure as function headers.
Only the function name will change to have some parantheses and a "*" in it, and the arguments won't have names, because only their types are important when using pointers (we don't access the values of the arguments, so we don't need their names).
They basically look like this:
<return_value> (*<function_name>)(<argument_list>)
So, for example, the function pointer for the function
void swap(int* a, int* b);
would be
void (*swap_ptr)(int*, int*);
Notice that the name of the pointer is in the place of the name of the function, and looks a bit odd compared to normal pointer declarations.
An excellent reading on this topic (you can skip the C++ stuff): https://www.cprogramming.com/tutorial/function-pointers.html

C how to pass pointer to struct array pointer

I realize this is most likely a syntax issue, however, I have a struct:
struct pixel{
int pixel_num;
double lowest_dist;
int centroid;
double * location;
};
and an array of these structs struct pixel * pixel_data[10]
and a method: void foo(double ** arr) and am trying to pass the address of the location pointer in an instance of the struct to update the pointer in the method foo.
I attempted to pass it like so foo(&(pixel_data[0]->location)) however this is clearly not correct as when I run through gdb the *arr values are different in foo than what they were in main() where I call foo.
Thanks.
An Example:
#define DIMENSIONS 5
//Struct is declared in header.
//max 10 pixels
struct pixel * pixel_data[10];
int main(){
double newLoc[DIMENSIONS]={1.1,2.2,3.3,4.4, 5.5};
pixel_data[0]=add_pixel(newLoc);
update_centroid_location(&(pixel_data[0]->location), 0, DIMENSIONS);
}
void update_centroid_location(double **centroid, int centroid_num, int numpix){
double * old_cent=malloc(DIMENSIONS*sizeof(double));
if(!old_cent){
perror("couldnt allocate memory");
exit(4);
}
for(int i=0;i<DIMENSIONS;i++){
old_cent[i]=*centroid[i]; //segfaults here as cannot access memory address
}
}
struct pixel * add_pixel(double * location){
struct pixel * new=malloc(sizeof(struct pixel));
if(!new){
perror("Could not allocate space for pixel");
exit(4);
}
new->lowest_dist=DBL_MAX;
new->centroid=0;
new->location=location;
return new;
}
In the line old_cent[i]=*centroid[i]; there is a misunderstanding about operator precedence.
The * operator has a lower precedence than the [].
So you are essentially doing old_cent[i]=*(centroid[i]);
Try to use parenthesis to explicitly express that you want to first dereference then add the offset for the second dereference like so:
old_cent[i]=(*centroid)[i];

Adding an array element to an array in a struct

(Proficient at C++, newbie at C) getting a segfault error from the addArray() call in main(). I've checked many posts and several texts, it compiles, but no luck running it. I'm coding it on VS2015 and all the usual handy cues are there with pointers, etc. Cleary something I'm not aware of or a syntax error. This is the distilled code that reproduces the error.
#include<stdio.h>
#include <stdlib.h>
#define TYPE int
struct arrayHolder {
TYPE data[100];
int count;
};
//prototypes.
void initArray(struct arrayHolder * );
void addArray(struct arrayHolder *, TYPE);
int main() {
struct arrayHolder * myStruct = NULL;
initArray(myStruct);
addArray(myStruct, 123);
}
/* Allocate memory for struct arrayHolder */
void initArray(struct arrayHolder * b) {
b = (struct arrayHolder *)malloc(sizeof(struct arrayHolder));
b->count = 0;
}
/* Add an element to data[] */
void addArray(struct arrayHolder * b, TYPE v) {
int count = b->count;
b->data[count] = v;
(b->count)++;
}
As #def1 observed, you are passing pointers by value. That's not an issue for addArray() -- the problem is with initArray(). That function's parameter is local to the function, so when you assign the malloc()ed pointer to it, the result is not visible in main(). Ultimately, you end up passing a NULL pointer to addArray().
There are at least two possible solutions.
In the code presented, it's not clear to me why the struct arrayholder needs to be dynamically allocated at all. If in main() you declare instead struct arrayholder myStruct; and remove the malloc() call from initArray(), then everything else should work as-is.
Alternatively, if you do need to perform dynamic allocation then either you should return a pointer to the allocated memory from initArray() (in which case that function does not require a parameter) or else you need to pass a double pointer to the function, so that main()'s pointer can be updated thereby.
The only one of those alternatives that should be at all tricky is the double pointer variant, which would look like this:
int main() {
struct arrayHolder * myStruct = NULL;
initArray(&myStruct); /* difference here */
addArray(myStruct, 123);
}
/* Allocate memory for struct arrayHolder */
void initArray(struct arrayHolder ** b) {
/* no cast is required here in C, and many account one poor style: */:
*b = malloc(sizeof(struct arrayHolder));
(*b)->count = 0;
}
void initArray(struct arrayHolder * b)
Here you pass a pointer to a struct arrayHolder to the function. The pointer is passed by value which means it is a copy. You can change the data the pointer is pointing to but when you assign the result of malloc to b you are modifying the copy of the pointer itself, which will not influence the pointer in main.
Possible solution is to use a pointer to a pointer.
void initArray(struct arrayHolder ** b) {
*b = (struct arrayHolder *)malloc(sizeof(struct arrayHolder));
(*b)->count = 0;
}

ANSI C Memory allocation for pointer to struct throws non-fatal run-time error

I am using ANSI C code, generated from a code generator that produces several layers of nested struct as well as function prototypes with argument lists that use pointers to the top layer struct for passing or accessing data located in the inner mmost struct.
Because the function prototypes pass pointers to struct, the application must allocate memory to access or write data to the inner most struct members. I am seeing the problem when attempting to allocate memory for the pointer to the second nested struct.
The actual error message I get is a non-fatal, run-time:
"Not enough space for casting expression to 'pointer to struct data'."
I am not explicitly casting anything, so I suspect the implementation of malloc() may have an assert that generates the message when it sees some condition. The wording of this error may be specific to my environment (I am using LabWindows/CVI) but I would be interested in hearing of results of other ANSI C compilers as well.
Here is a simplified, complete, code snippet that should compile, build and run (up to the error location, which is commented in-line)
I would appreciate comments on the cause of my error, and suggestions on how to fix it.
#include <ansi_c.h> //specific to LabWindows/CVI - change as needed for your environment
struct request
{
struct data *pData;
};
struct data
{
char *wsDate;
char *wsDuration;
char *wsFailures;
int __sizeM_Details;
struct details *M_Details;
};
struct details
{
char *wsStep;
char *wsTestDesc;
char *wsLowLim;
};
typedef struct request REQUEST; // from mtdf function prototype request argument (4)
typedef struct details DETAILS; // member of REQUEST - _ns1__MTDFData_MTDFDetail
void allocate(REQUEST *a, int numRecords);
void freemem(REQUEST *c, int numRecords);
int main(void)
{
REQUEST b, *pB;
pB = &b;
allocate(pB, 10);
freemem(pB, 10);
return 0;
}
void allocate(REQUEST *c, int numRecords)
{
DETAILS m_Param;
REQUEST b;
struct data d;
size_t size_c = sizeof(c);
c = malloc(size_c); //4 bytes
size_t size_c_data = sizeof(c->pData);
c->pData = malloc(size_c_data); //Breaks here - this is just a pointer,
//should it not just allocate 4 bytes
//and continue?
// Actual error message:
// "Not enough space for casting expression to 'pointer to struct data'."
c->pData->wsDate = calloc(80, sizeof(char));
c->pData->__sizeM_Details = numRecords;
c->pData->M_Details = calloc((numRecords + 1) , sizeof(m_Param));
}
void freemem(REQUEST *c, int numRecords)
{
free(c->pData->M_Details);
free(c->pData->wsDate);
free(c->pData);
free(c);
}
There's several fundamental problems, here:
In allocate(), all that memory you're malloc()ing is being lost at the end of your function, because you're assigning it to a local variable, c, which gets destroyed at the end of your function. You never use the address of the struct with automatic storage duration that you pass into the function. If you're passing the address of an object with automatic storage duration, then you should malloc() memory for the members, but not for the struct itself, since it obviously already has memory.
Then, in freemem(), you attempt to free() the memory associated with b, which is a struct with automatic storage duration. You can only free() memory that you've dynamically allocated.
You have a curious comment in allocate(), "this is just a pointer, should it not just allocate 4 bytes and continue?". If you're on a system with 32 bit pointers, then that is indeed what you allocated, but c->pData is a pointer to struct data which looks like it needs 28 bytes on a 32 bit machine, so you should be allocating a lot more than 4 bytes for it. Lines like c->pData->wsDate = ... seem to indicate that you're well aware it's a pointer to a struct data, so it's really unclear why you think you should only be allocating 4 bytes. When you allocate memory for an ANYTHING * to point to, then you need to allocate enough memory for an ANYTHING, not for an ANYTHING *, i.e. enough memory for the thing it's going to point to. The fact that you're trying to assign the memory to your pointer in the first place proves that you already have the memory for your pointer, otherwise you wouldn't be able to do that (providing that you haven't messed up some previous allocation, of course).
You never check the return from malloc() and calloc(), and you should.
Names beginning with a double underscore are always reserved for the implementation, so you should call __sizeM_Details something else.
sizeof(char) is 1 by definition, so there's never any need to use it.
It's unclear why you're allocating memory for numRecords + 1 of your struct details, rather than just numRecords as would seem intuitive. Perhaps you're looking to set that last one to NULL as a sentinel value, but if you're already storing the number of records in your struct, then this isn't really necessary.
Here's what your code ought to look like:
#include <stdio.h>
#include <stdlib.h>
struct request {
struct data * pData;
};
struct data {
char * wsDate;
char * wsDuration;
char * wsFailures;
int sizeM_Details;
struct details * M_Details;
};
struct details {
char * wsStep;
char * wsTestDesc;
char * wsLowLim;
};
typedef struct request REQUEST;
typedef struct details DETAILS;
void allocate(REQUEST * c, const int numRecords);
void freemem(REQUEST * c);
int main(void)
{
REQUEST b;
allocate(&b, 10);
freemem(&b);
return 0;
}
void allocate(REQUEST * c, const int numRecords)
{
if ( !(c->pData = malloc(sizeof *c->pData)) ) {
perror("couldn't allocate memory for c->pData");
exit(EXIT_FAILURE);
}
if ( !(c->pData->wsDate = calloc(80, 1)) ) {
perror("couldn't allocate memory for c->pData->wsDate");
exit(EXIT_FAILURE);
}
if ( !(c->pData->M_Details = calloc(numRecords + 1,
sizeof(*c->pData->M_Details))) ) {
perror("couldn't allocate memory for c->pData->M_Details");
exit(EXIT_FAILURE);
}
c->pData->sizeM_Details = numRecords;
}
void freemem(REQUEST * c)
{
free(c->pData->M_Details);
free(c->pData->wsDate);
free(c->pData);
}
If allocating automatic storage for b was a mistake, and you really do want to dynamically allocate everything, including your struct request, then it should look like this:
#include <stdio.h>
#include <stdlib.h>
struct request {
struct data * pData;
};
struct data {
char * wsDate;
char * wsDuration;
char * wsFailures;
int sizeM_Details;
struct details * M_Details;
};
struct details {
char * wsStep;
char * wsTestDesc;
char * wsLowLim;
};
typedef struct request REQUEST;
typedef struct details DETAILS;
REQUEST * allocate(const int numRecords);
void freemem(REQUEST * c);
int main(void)
{
REQUEST * b = allocate(10);
freemem(b);
return 0;
}
REQUEST * allocate(const int numRecords)
{
REQUEST * c = malloc(sizeof *c);
if ( !c ) {
perror("couldn't allocate memory for c");
exit(EXIT_FAILURE);
}
if ( !(c->pData = malloc(sizeof *c->pData)) ) {
perror("couldn't allocate memory for c->pData");
exit(EXIT_FAILURE);
}
if ( !(c->pData->wsDate = calloc(80, 1)) ) {
perror("couldn't allocate memory for c->pData->wsDate");
exit(EXIT_FAILURE);
}
if ( !(c->pData->M_Details = calloc(numRecords + 1,
sizeof(*c->pData->M_Details))) ) {
perror("couldn't allocate memory for c->pData->M_Details");
exit(EXIT_FAILURE);
}
c->pData->sizeM_Details = numRecords;
return c;
}
void freemem(REQUEST * c)
{
free(c->pData->M_Details);
free(c->pData->wsDate);
free(c->pData);
free(c);
}

Is this use of struct pointers correct?

I have this struct:
typedef struct Grades {
int grade1;
int grade2;
int grade3;
int grade4;
int grade5;
}
I created a pointer to a Grades struct using
struct Grades *pointer;
and I have a function() that returns a (void *) pointer to a specific Grades struct.
How do I set my pointer to that specific struct using the (void *) pointer?
I was thinking:
pointer = &function();
but that gives me an error: "'&' requires l-value
Any ideas? And by the way, I can't modify the function so...
If function() returns a pointer, you should be able to just do
pointer = function();
pointer = function();
If function() is returning a void pointer, you don't need to take the address of it, it's already a pointer pointing to a Grades struct.

Resources