How is it possible to access property without "->" in c? - c

I've been learning c for a while, and let's say I thought I had a good understanding of pointers though this example is bugging me.
Let's say we have an array in which each element points to a structure. If we allocate space for two elements like in the example bellow:
p = (test**)malloc(2*sizeof(test*));
p[0] = (test*)malloc(sizeof(test));
p[1] = (test*)malloc(sizeof(test));
Here's the structure test:
typedef struct {
char *t;
long long p;
} test;
And now when I assign values to the variables like below:
(*p)[1].t = (char*)malloc(10*sizeof(char));
strcpy((*p)[1].t, "test");
(*p)[1].p = 10;
p[1]->t = (char*)malloc(10*sizeof(char));
p[1]->p = 20;
strcpy(p[1]->t, "test34e");
They fill completely different chunks of memory. How am I able to access property t at all in this example (*p)[1].t?

It seems you mean the following
(*p[1] ).t = (char*)malloc(10*sizeof(char));
strcpy( ( *p[1] ).t, "test");
( *p[1] ).p = 10;
That is p[1] is a pointer. So you can write for example either p[1]->t or dereferencing the pointer and getting the pointed object of the structure type ( *p[1] ).t.

Related

Referencing a variable to an existing array

I'm pretty new to C and starting to play with pointers. I haven't found a way to assign an array to multiple variables.
What I want ideally is:
char myArray[10] = "test";
char (*p)[10] = &myArray;
char anotherArray[10];
anotherArray = *p;
This doesn't work and I don't know why.
I have found a way to "copy" the array by using a for loop,
for (int i = 0; i < 10; i++)
{
anotherArray[i] = myArray[i];
}
I don't know if it's good practice to do it and if there is an easier way.
The array content is not supposed to change so I just want to have a simple way to do this:
firstArr[size] = "content";
secondArr = firstArr;
You can't assign arrays in C, neither by itself nor by dereferencing pointers to arrays, the syntax simply doesn't allow it.
Arrays are normally copied with memcpy. In case they are strings, you can also use strcpy, which copies up until it finds the string null terminator.
In your example, this would be strcpy(anotherArray, *p);. But to use an array pointer of type char (*)[10] is a bit weird practice, it is far more common to use a pointer to the first element of the array. I would recommend that you change your code to this:
#include <stdio.h>
#include <string.h>
int main(void)
{
char input[10] = "test";
char* p = input;
char anotherArray[10];
strcpy(anotherArray, p);
puts(anotherArray);
}
You can't assign an array to multiple variables, but you can assign multiple variables to point to an array.
Pointers are all about memory and the memory that they point to.
Statements such as this assign a fixed amount of memory (10 char sized bytes of memory) to the variable myArray and initialises the contents to contain "test1".
char myArray[10] = "test1";
By definition myArray is actually a pointer to the first memory location, which in this case holds a char of value 't', but it is fixed to that memory.
You can define another pointer to type char and assign it the same value as the pointer to the memory that holds the data "test1" - thus:
char *secondPtr = myArray;
Now secondPtr and myArray both point to the same memory, which contains "test1". There aren't two copies of the data, but it may appear so if you did
printf("myArray %s", myArray);
printf("secondPtr %s", secondPtr);
Now you can use either myArray or secondPtr to alter the same data, which is why pointers should be treated with care.
Now as secondPtr is just a pointer to a char and as such it isn't fixed in the same way that myArray is, so you can do this:
char myArray2[10] = "test2";
secondPtr = myArray;
printf("secondPtr %s", secondPtr);
secondPtr = myArray2;
printf("secondPtr %s", secondPtr);
To copy data from one array to another you can use memcpy, which will copy a specified number of bytes(octets) of memory from one location to another.
The same process is performed by a loop (this is basic code, but not really the best way of performing it as there are no checks on the size of the arrays nor on the number of loop iterations)e.g.
for(int i=0; i<10; i++)
{
myArray2[i] = myArray[i];
}
this can also be:
secondPtr = myArray2;
for(int i=0; i<10; i++)
{
myArray2[i] = secondPtr +i;
}

malloc causes int to change value

I'm a bit new to C, and have been working on a project when I came across a weird behavior which I'd love to understand. (Probably something I'm missing).
I have the following structs:
typedef struct {
char *name;
int status;
int strength;
} Pig;
typedef struct {
char *name;
char color[10];
int injuryPower;
int penType;
} Bird;
When I allocate the pig, like this, it works normally:
Pig *pig_1 = malloc(sizeof(Pig *));
pig_1->status = 2;
pig_1->strength = 7;
pig_1->name = malloc(sizeof(char) * 11);
pig_1->name = "PigA\0";
But when I allocate the bird, in a similar manner, I have this weird behavior:
Bird *bird_1 = malloc(sizeof(Bird *));
1) bird_1->penType = 2;
2) bird_1->injuryPower = 5;
3) bird_1->name = malloc(sizeof(char) * 6);
bird_1->name = "BirdA\0";
bird_1->color[0] = 'R';
bird_1->color[1] = 'e';
bird_1->color[2] = 'd';
bird_1->color[3] = '\0';
In line (1) pen type is getting defined to 2.
In line (2) pen type is still 2.
In line (3) pen type gets changed according to the value I define in the bracets, so in this example it'll change to 35.
I am using Cygwin 64 bit as my compiler.
Could someone please explain what I am missing here, why is the value of pen type changing even though I am not altering it?
Is it due to malloc? Am I doing something incorrectly?
Thanks a lot!
Pig *pig_1 = malloc(sizeof(Pig *));
...
Bird *bird_1 = malloc(sizeof(Bird *));
You're allocating the size of a pointer not the size of the structure.
Pig *pig_1 = malloc(sizeof(Pig));
...
Bird *bird_1 = malloc(sizeof(Bird));
Will reserve enough space for the whole structure.
Because you are only allocating enough memory for the first member of your structure (also a pointer), the other members are in an area of memory that could be reserved for other variables. What you are seeing is the value of another variable being changed and reflected in your structure.

Create pointers array from unknown type array in c

I need to write a function the takes:
an unknown type array, size of the array and size of the elements
and return an array of pointers: first the negative value and then the positive values. this is what Iv done so far:
void *mix(void *A, int nElementsA, int sizeOfAnElement) {
char** res = (char**)malloc(sizeof(char*)*nElementsA*sizeOfAnElement);
char* p = (char *)A;
char* bStart = res[0];
char* bEnd = res[nElementsA*sizeOfAnElement - sizeOfAnElement];
while (p<(char*)A + nElementsA*sizeOfAnElement) {
if (*(int*)p>0) {
bStart = p;
bStart += sizeOfAnElement;
}
else {
bEnd = p;
bEnd -= sizeOfAnElement;
}
p += sizeOfAnElement;
}
return res;
}
and i get array full of rubbish,
what Iv dove wrong?
First of all: What you are trying to do is impossible and makes little sense.
You say that you have: an unknown type array Therefore you can not access any elements of the array. Doing:
(*(int*)p
means that you assume the elements to be of type int (or compatible). This obviously conflict with the type being unknown.
Besides that....
This line
malloc(sizeof(char*)*nElementsA*sizeOfAnElement);
allocates too much memory. It shall only allocate a pointer for each element, i.e.
malloc(sizeof(char*)*nElementsA);
Fixed:
void *mix(void *A, int nElementsA, int sizeOfAnElement,
int (*isPositive)(const void *)) {
// Allocate a `char*` array containing `nElementsA` pointers.
char **res = malloc(nElementsA * sizeof *res);
// &p[i] == &A[i]
char (*p)[sizeOfAnElement] = A;
// bStart points to the first result element.
char **bStart = &res[0];
// bEnd points to the last result element.
char **bEnd = &res[nElementsA - 1];
// Loop through the array,
// adding &A[i] at the start of the result array if positive,
// else at the end of the result array.
for (int i = 0; i < nElementsA; i++) {
if (isPositive(p[i])) {
*bStart = p[i];
bStart++;
}
else {
*bEnd = p[i];
bEnd--;
}
}
return res;
}
Your understanding of what needed to be allocated and how to use your pointers was wrong.
If you want to create an array of pointers, then you need only allocate nElementsA pointers, not nElementsA * sizeOfAnElement pointers (you're storing pointers, not copies of the objects to which they point).
Then you created and used bStart and bEnd incorrectly. If you want to move through an array of int objects, then you need an int* object. In the case of bStart and bEnd, you want to move through an array of char*, so you need a char**.
I added a function pointer parameter, so you can work with types other than int (else what's the point of using void *A and sizeOfAnElement instead of int *A?) If you need help with that, there are plenty of answers here and tutorials for you to find via search engine.
I also took the liberty of changing p to a pointer to an array, so the compiler can perform the pointer arithmetic for you rather than you doing it yourself. You can change it back if you like. If you want to use pointers in the loop (i.e. you can't use i), here's a version of the loop that does that:
// I added the typedef for more easily understood declarations of `p` and `end`.
typedef char array_alias_t[sizeOfAnElement];
// p's type is the same as in the previous code (char (*)[sizeOfAnElement]).
array_alias_t *p = A;
// p + x == &p[x], and &p[nElementsA] is one element past the end of A,
// which is allowed by ISO C, provided you don't dereference the pointer
// (i.e. *end is not allowed).
for (array_alias_t *end = p + nElementsA; p != end; p++) {
if (isPositive(*p)) {
*bStart = *p;
bStart++;
} else {
*bEnd = *p;
bEnd--;
}
}

variable may be used before being set

I am getting "variable may be used before being set" when I create a pointer to a structure example *e. If I use a variable instead example e, I am not getting the error. Is this because I haven't allocated memory for the pointer?
typedef struct example {
int a;
}example;
void test (){
example *e;
e->a=1;
printf_all("val %d",e->a);
}
e is NOT pointing to anything. You are using an uninitialized pointer. You "set" through an invalid pointer, and then trying to access it.
Your pointer should point to an example instance. For example:
example exampleInstance;
example * examplePointer = &exampleInstance;
The pointer has an indeterminate value. As result the program has undefined behaviour.
You should allocate memory for an object of type example where you are going to write data. For example
example *e = malloc( sizeof( *e ) );
e->a = 1;
In this case you should free the memory when it will not be needed any more.
Or
example obj;
example *e = &obj;
e->a = 1;

Need help in clarifying some memory references/pointers in C

Can you explain the difference between
&var -> a[var -> count]
and
var -> a[var -> count]
p = &x[i]
p = a[i]
&p = &a[i]`
Can we do the following
var -> *mem
or
*var -> mem
or
*var -> mem
or
*(*var) -> mem
or
var -> *(mem) = 2;
What above examples mean?
Let's see if I can take a go at this. First off, I recommend getting a simple, free c compiler to try these examples out. Most of these examples can be tested that way.
1. var -> a[var -> count] vs &var -> a[var -> count]
Beware that 'var' is a pointer to a data structure. We can assume that the structure at the very least has two elements: an array of 'a', and a value 'count'. With this in mind "var->a[var->count]" represents the VALUE of the 'count'(plus 1) element of the 'a' array within the structure pointed to by var. I say the 'count' (+1) value because the first element of the array is a[0], as you know. The term "&var->a[var->count]" represents the ADDRESS of the 'count'(plus 1) element of the 'a' array within the structure pointed to by var.
2. p = &x[i]
This is setting p to the ADDRESS of the ith value of the 'x' array. '&varname' should be interpreted as (ADDRESS of varname).
p = a[i]
Here 'p' is set to the VALUE of the ith value of the 'a' array.
&p = &a[i]`
This does not work. First the back-tick means nothing. Also, the attempt is to set the address of the pre-defined variable 'p' to a new value. 'p' itself is a variable that can hold many different values, but the ADDRESS of p is NOT variable. In case you're
wondering, the expression should be read as "the address of p is equal to the address of a[i]".
3. var->*mem
Looks terribly wrong. I would say this is an attempt to write...
*var->mem
Which is a the VALUE of some variable pointed to by 'var->mem'. In this case, 'var' is a pointer to a structure, which contains the pointer 'mem'. In code it might look like this:
int j;
struct example
{
int *mem; // mem is an integer pointer.
} x;
struct example *var;
j = 3; // some value.
x.mem = &j; // mem is set to point to j mem=ADDRESS of j;
var = &x; // var is pointing to the structure 'x'
printf("%d\n",*var->mem); // should print "3"
This next example is the same mistake as the first example.
var -> *(mem) = 2;
The parenthesis do nothing for you. Good luck getting this to compile. That said, there is nothing stopping you from doing this:
*var->mem = 2;
but in the above code example, that's the same as 'j=2'
*(*var)->mem
This example is really tricky. It reads as the value of the value pointed to by var, which itself is a pointer to a structure containing 'mem'. This implies that var would be declared as
struct ***var;
var is thus a pointer to a pointer to a pointer. I created a code snippet which compiles and illustrates how this could be used, but I don't recommend actually using this level of indirection in your own code, especially if there's any chance someone will read it. If you do, prepare to be hunted down and burnt at the stake like a witch.
#include <stdio.h>
struct lkj
{
int *mem;
};
int main(void)
{
int j;
struct lkj bob;
struct lkj ***var,**floyd,*sam;
j = 3;
bob.mem = &j;
sam = &bob;
floyd = &sam;
var = &floyd;
printf("bob.mem = 0x08%lX *bob.mem=%d j=%d\n",
(unsigned int)bob.mem,
*bob.mem,j);
printf("&bob = 0x08%lX\n",(unsigned int)&bob);
printf("sam = 0x08%lX &sam=0x%08lX\n",
(unsigned int)sam,(unsigned int)&sam);
printf("floyd = 0x08%lX &floyd=0x%08lX\n",
(unsigned int)floyd,(unsigned int)&floyd);
printf("var = 0x%08lX *(*var) = 0x%08lX\n",
(unsigned int)var,(unsigned int)*(*var));
printf("(*(*var))->mem = 0x%08lX *(*(*var))->mem=%d\n",
(unsigned int)(*(*var))->mem,
*(*(*var))->mem);
printf("(**var)->mem = 0x%08lX *(**var)->mem=%d\n",
(unsigned int)(**var)->mem,
*(**var)->mem);
return 0;
}

Resources