C Struct Pointers - c

Default struct given:
struct counter {
long long counter;
};
struct instruction {
struct counter *counter;
int repetitions;
void(*work_fn)(long long*);
};
static void increment(long long *n){
n++;
}
My line:
n = 2;
struct counter *ctest = NULL;
int i;
if( ctest = malloc(sizeof(struct counter)*n){
for( i=0; i<n ;i++){
ctest[i].counter = i;
}
for( i=0; i<n ;i++){
printf("%lld\n", ctest[i].counter);
}
}
struct instruction itest;
itest.repetitions = 10;
itest.counter = ctest; //1. This actually points itest.counter to ctest[0] right?
//2. How do I actually assign a function?
printf("%d\n", itest.repetitions);
printf("%lld\n", itest.counter.counter); // 3. How do I print the counter of ctest using itest's pointer?
So I am trying to get those three things working.
Thanks

itest.counter = ctest; // This
actually points itest.counter to
ctest[0] right?
Right. itest.counter == &ctest[0]. Also, itest.counter[0] refers directly to the first ctest object, itest.counter[1] refers the 2nd, etc.
How do I actually assign a function?
itest.work_fn = increment;
How do I
print the counter of ctest using
itest's pointer?
printf("%lld\n", itest.counter->counter); // useful if itest.counter refers to only one item
printf("%lld\n", itest.counter[0].counter); // useful if itest.counter refers to an array

This points to addres of ctest. (which is same as addres of it's first element)
You should declare some function whith same signatur (say void f(long long *)) and here write itest.work_fn = f;
for(int i = 0; i < n; ++i) printf("%lld\n", itest.counter[i].counter);

Yes it does. But maybe it is more clear like this:
iter.counter = &ctest[0];
itest.work_fn = increment;
printf("%lld\n", itest.counter->counter);
That is if you plan to have only one counter. From your code you want multiple and maybe you should store the number in struct instruction.
If so, then it would be:
for (i = 0; i < itest.n; i++)
printf("%lld\n", itest.counter[i].counter);
In this case the function should also be changed.

Related

C Programming: String arrays - how to check equality? [duplicate]

This question already has answers here:
How do I properly compare strings in C?
(10 answers)
Closed 4 years ago.
I have a struct such as this:
struct car{
char parts[4][10];
};
I initialize them in my main() function, as though:
char fill[10] = "none";
struct car c;
int i = 0;
for (i; i< 4; i++){
memcpy(c.parts[i], fill, 10);
}
At this point, each string in the array has "none", like this:
int j = 0;
for (j; j<4; j++){
printf("%s\n", c.parts[j]);
}
*OUTPUT*
none
none
none
none
This is correct - this is what I want. Now, however, I want to write a function and pass a pointer to c. Inside the function, I want to:
check if an element in the "parts" array is equal to "none".
if it is, then set that equal to "wheel".
Here is how I have attempted this:
void fun(struct car* c){
char fill[10] = "wheel";
int i = 0;
for (i; i<4; i++){
if (c->parts[i] == "none"){
memcpy(c->parts[i], fill, 10);
}
}
}
int main(){
char fill[10] = "none";
struct car c;
int i = 0;
for (i; i< 4; i++){
memcpy(c.parts[i], fill, 10);
}
struct car* c2 = c;
fun(c2);
return 0;
}
However, the if statement inside the function never gets hit! It keeps saying that each element in the array IS NOT equal to "none". However, I try printing it out RIGHT ABOVE the if statement - and sure enough, it says "none"! Not sure why?
EDIT
I tried the suggested methods in the "possible duplicate" post (strcmp), but to no avail. I'm still not getting what I want to achieve.
Use strcmp() from <string.h> to compare in fun() as shown below:
void fun(struct car* c){
char fill[10] = "wheel";
int i = 0;
for (i; i<4; i++){
if (!strcmp(c->parts[i], "none")) {
memcpy(c->parts[i], fill, 10);
}
}
}

How to increment a variable when strstr finds the specified string

I'm wanting to have my variable houseTot increment by one every time strstr finds a string with "house" in it. I've essentially done this in my code:
struct Owner1_def
{
int totProps;
char type[40];
float monthlyPrice;
float maintenance;
int bedrooms;
int bathrooms;
};
typedef struct Owner1_def Owner1;
int main(void)
{
char *ptr;
int i = 0;
ptr = strstr(database[i].hometype, "house");
for(i = 0; i <= 3; ++i)
{
if (ptr != NULL)
houseTot++;
}
return 0;
}
But when the program prints houseTot's value, it's still at it's initialized value 0. I don't know much about strstr, but from what I've read, this should work.
The call to strstr() should be moved inside the loop so that the value stored in database[i].hometype can be checked on each iteration:
for(i = 0; i <= 3; ++i) {
ptr = strstr(database[i].hometype, "house");
if (ptr != NULL)
houseTot++;
}
Note that posted code has no definition for the array of structs database[], and the struct provided has no hometype field.

Assign and dereference void * to an array pointer in C

I have a pointer to array of fixed size integer elements. After populating that array, I assigned it to void *pBuff. Later on, I need to access array elements through void pointer which I failed in doing so.
Here is the code using C:
void * pBuff = NULL;
int
set_data(void *pBuff)
{
int ptr = 10, i;
int phy_bn[8] = {0};
int (*pPB)[8];
for(i=0; i<8; i++){
phy_bn[i] = ptr;
}
pPB = &phy_bn;
pBuff = pPB;
return 0;
}
int main()
{
int i;
set_data(&pBuff);
for(i =0 ; i <8; i++){
printf("\ndata : %d\n", *(int *)pBuff[i]);
}
return 0;
}
It prompts an error cast of 'void' term to non-'void' against *(int *)pBuff[i].
Any help will be really appreciated.
Thanks,
-Sam
Apart from the fact that you need to use:
((int*)pBuff)[i]
What you have in your code is Undefined Behavior.
pBuff = pPB;
pBuff points to a array which is local to the function and its lifetime does not exist beyond the function scope. So you have a pointer pointing to something that does not need to exist but may seemingly exist sometimes.
You should probably dereference with * or [], not both at the same time :-)
If your intent is to get the integer at that i position of a void pointer which points to ints, use:
((int*)pBuff)[i]
The ((int*)pBuff) turns pBuff into a pointer to an integer and the [i] following that grabs the i'th integer at that location.
So your loop would be:
for (i = 0 ; i < 8; i++)
printf ("\ndata : %d\n", ((int*)pBuff)[i]);
Another thing you should probably watch out for is returning pointer to stack-based variables. Those variables disappear when the function exits at which point dereferencing pointers to them is undefined behaviour.
pBuff[i] is illegal, since pBuff is a void*. It's a matter of operator precedence:
((int *)pBuff)[i]
You don't need to dereference pBuff again with the first * because [i] already does that.
It should be
void * pBuff = NULL;
int
set_data(void *pBuff)
{
int ptr = 10, i;
int *phy_bn = (int*)malloc(sizeof(int)*8);
//this is needed so that it is valid for pBuff to point phy_bn even if it is getting out of scope
for(i=0; i<8; i++){
phy_bn[i] = ptr;
}
pBuff = phy_bn;
return 0;
}
int main()
{
int i;
set_data(&pBuff);
for(i =0 ; i <8; i++){
printf("\ndata : %d\n", ((int*)pBuff)[i]);
}
return 0;
}

store value from a for-loop into an array

I would like to store values read from a for-loop to an array
char A[];
int x;
int y=5;
for( int i=0; int i =1000; i++) {
x = x+y;
// then store/append x as elements of the char array, A.... what is the syntax?
}
By looking at your code I am assuming that you are trying to build a static array, so I will demonstrate that (so you don't have to focus on concepts like malloc for the time being). There is however, several problems with your code that I will go over now.
First off your array declaration:
char A[];
to me it looks like your for loop is filling an array of integers, so this array should be declared as an integer, furthermore you are not setting the size of the array, since your code has i increment until it is 1000 you should just declare an integer array with 1000 elements:
int A[1000];
Second your for loop:
for(int i = 0, int i = 1000; i++)
you're better off just declaring i with the rest of your variables, although you can declare it in a for loop I personally wouldn't suggest doing it. Also you declare i twice in this loop. Finally your condition to continue the loop (i = 1000) will abort the loop immediatly since i will never be equal to 1000 since you set it to 0. Remember a for loop only loops while the middle statement is true. So with that in mind you should now have:
int A[1000], i, x, y = 5;
for(i = 0; i < 1000; i++)
And now we can use the = statement and the value of i to set each array element for A:
int A[1000], i, x, y = 5;
for(i = 0; i < 1000; i++)
{
x += y;
A[i] = x;
}
it's that simple!
There are multiple issues with your code
char A[1000]; // Need to specify a compile time constant for the array size
int x=0;
int y=5;
for( int i=0; i < 1000; i++) { // Condition was wrong
x = x+y;
// then store/append x as elements of the char array, A.... what is the syntax?
A[i] = x; // Add the value
}
Also, the char datatype won't be able to hold values over a certain size, and will cause overflow making the values wrap around. You might want to declare A as int A[1000] instead.
Arrays need to be of a constant size, or you will need to allocate them using malloc
The second part of the loop cannot redeclare i again. It also will loop forever if you have an assignment statement in it like you do. I assume you want to loop up to 1000 instead
The actual question, to assign into an array use the [] operator.
x was not initialized to anything, making it contain a garbage value. You need to assign values to variables upon declaring them. C does not do this for you automatically.
If you want to add an element in C, you have several methods.
Static array
A static array is declared with a number of elements you're unable to edit. So it's perfect if you know exactly the number of elements you'll have. #Dervall did explain that well.
Dynamic array
A dynamic array is declared with malloc function. And the size can be changed. It's difficult and hard to maintain though. But :
int *A = NULL;
int *tmp; // to free ex allocated arrays
int i;
int j;
int x = 0;
int y = 5;
for (i = 0 ; i < 1000 ; i++) {
// saving temporarly the ex array
tmp = A;
// we allocate a new array
if ((A = malloc(sizeof(int) * (i + 1))) == NULL) {
return EXIT_FAILURE;
}
// we fill the new array allocated with ex values which are in tmp
for (j = 0; j < i; j++) {
A[j] = tmp[j];
}
// if it's not the first time, we free the ex array
if (tmp != NULL)
free(tmp);
x = x + y;
A[i] = x;
}
Better to split it into a function of course :)
You can use the realloc function as well ! Which is made for that, but I find it interesting to develop like this
There's a lot of stuff wrong with your snippet. Here's a compilable example
char *A = malloc(sizeof(*A) * NUM_ELEMENTS); // you shouldn't declare on the stack
int x = 0; // initialize
int y=5;
for( int i = 0; i < NUM_ELEMENTS; i++) { // proper for loop syntax
x = x+y;
A[i]=x; // assign element of array
}
And a better version:
char *A = malloc(sizeof(*A) * NUM_ELEMENTS);
for (int i = 0; i < NUM_ELEMENTS; ++i)
A[i] = 5 * i;

using malloc for block of structs

I am trying to allocate a block of memory, and store a list of structures without using multiple mallocs for each... this is just a generic example, I don't have the original code I was working with earlier, but this is the general idea, but my problem was that I was getting heap corruption when other parts of my code executed after the InitPoints() function call. I don't know what part of my code is illegal, but I suspect it is in the for loop of the InitPoints() function. I am trying to use this as table, then I can create additional tables of defined size if I ran out of memory and link them together... so kind of like a dynamic expanding array if that makes any sense.
typedef struct Tb{
POINT points;
POINT *next;
} TABLE;
typedef struct Pt{
int x;
int y;
}POINT;
POINT *mypoints;
int main() {
int size = 10;
int i = 0;
mypoints = InitPoints(size);
for(i=0; i < size; i++)
{
printf("mypoint [%d] = (%d,%d)\n",i, mypoints->x, mypoints->y);
mypoints = mypoints + sizeof(POINT);
}
// some other code...
// i.e. createThread(....)
return 0;
}
POINT* InitPoints(int size)
{
POINT *tmp;
POINT *orig;
int a = 10;
int b = 1000;
orig = (POINT*) malloc (sizeof(POINT) * size);
if(orig == NULL)
return NULL;
tmp = orig;
for (i = 0; i < size; i++)
{
tmp->x = a++;
tmp->y = b++;
tmp = tmp + sizeof(POINT);
}
return orig;
}
This is wrong:
mypoints = mypoints + sizeof(POINT);
You should review pointer arithmetic in C. Just use:
mypoints += 1; /* or something similar */
(There is a similar problem in your InitPoints function)
Here's one referemce:
http://www.eskimo.com/~scs/cclass/notes/sx10b.html
The problem is in this line:
tmp = tmp + sizeof(POINT);
It should be
++tmp;
The latter says to increment the pointer by one element; since it points to the structure, it increments by the size of the structure. The original code instead increments by n elements where n is the number of bytes in the structure. For example, if int is 32-bits, it will advanced by 8 elements.
This is why I would do it
for (i = 0; i < size; i++)
{
orig[i].x = a++;
orig[i].y = b++;
}
In C, adding an integer to a POINT* pointer advances the pointer not by that number of bytes, but by that number of POINT structures.
You have two places in your code where you add sizeof(POINT) to your pointer. Instead you should just add 1.

Resources