Need help in clarifying some memory references/pointers in C - 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;
}

Related

How is it possible to access property without "->" in 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.

Confusion between Pointer Notation and Dot Notation in Structs [duplicate]

This question already has answers here:
Why does the arrow (->) operator in C exist?
(3 answers)
Closed 1 year ago.
I am trying to make all the names in the Struct lowercase so that I can compare them and remove them.
int removeNameCard(NameCard *idCard, int *size){
char name[80];
char *ptr;
char rubbish;
int a = 0, c = 0;
printf("removeNameCard():\n");
printf("Enter personName:\n");
scanf("%c", &rubbish); // Why is there a '\n' char here??
fgets(name, 80, stdin);
if((ptr = strchr(name, '\n'))){
*ptr = '\0';
}
if((*size) == 0){
printf("The name card holder is empty\n");
return 0;
}
// Convert everything to Lower Case first
while(name[a]){
name[a] = tolower(name[a]);
a += 1;
}
printf("tolower(): %s", name);
for(int b = 0; b < *size; b += 1){
// Why is this Dot Notation when I passed in a pointer to the Struct?
while (idCard[b].personName)[c]){
(idCard[b].personName)[c] = tolower((idCard[b].personName)[c]);
c += 1;
}
}
for(int i = 0; i < *size; i += 1){
if((idCard[i].personName) == name){
printf("%d. This is from Holder: %s, This is from User: %s", i,(idCard[i].personName),name);
printf("The name card is removed\n");
printf("nameCardID: %d\n", idCard[i].nameCardID);
printf("personName: %s\n", idCard[i].personName);
printf("companyName: %s\n", idCard[i].companyName);
int k = 0;
do{
idCard[i+k].nameCardID = idCard[i+k+1].nameCardID;
strcpy((idCard[i+k].personName),(idCard[i+k+1].personName));
strcpy((idCard[i+k].companyName),(idCard[i+k+1].companyName));
}while((i+k+1) != (*size + 1));
}
}
return 0;
}
However, I am rather confused why the Compiler asked me to use Dot Notation instead of Pointer Notation as I thought I passed in the address of the Struct into *idCard so it should be a pointer if I am not wrong?
And am I wrong for trying to access each individual character in every name of the Struct like this?:
(idCard[b].personName)[c]
Thank you
However, I am rather confused why the Compiler asked me to use Dot Notation instead of Pointer Notation…
idCard[i] is a structure, not a pointer to a structure, so its members are accessed as idCard[i].member, not idCard[i]->member.
idCard[i] is a structure because whenever x is a pointer, x[i] is one of the objects that x points to. It is not the address of the object. You could calculate the address of the object with x+i, and then you could reference the object with *(x+i). And x[i] is actually defined in this way; x[i] is defined to be *(x+i). (In case of expressions generally, E1[E2] is defined to be (*((E1)+(E2))).)
And am I wrong for trying to access each individual character in every name of the Struct like this?: (idCard[b].personName)[c]
This will work, but the parentheses are unnecessary. You can use idCard[b].personName[c]. Due to the C grammar, it is already grouped as (idCard[b].personName)[c].
However, I am rather confused why the Compiler asked me to use Dot Notation instead of Pointer Notation as I thought I passed in the address of the Struct into *idCard so it should be a pointer if I am not wrong?
Arrays are mostly just pointers to the first element in the array (except that the compiler may be aware of the array size).
Because arrays are mostly just pointers; for arrays of integers myInt = myIntArray[x]; is like myInt = *(myIntArray + x); - the pointer dereferencing is implied by array indexing. Note that to access a char in the middle of an int in an array, you could (not portably) use something like myChar = *((char *)(myIntArray + x)) + offset_of_char_in_int);; and this is a little bit like accessing a field inside an array of structures (in that they're both accessing something smaller within an array of larger things).
For arrays of structures; indexing the array causes dereferencing (just like it does for the array of integers); so myIDcardStruct = idCard[i]; is like myIDcardStruct = *(idcard + i);. Because array indexing has implied dereferencing, myIDcardStruct is not a pointer.
The -> operator is like adding the offset of the requested structure's field to the address, casting the address to the requested field's type, and then dereferencing. In other words myInt = myStructPointer->myIntField; is like myInt = (*myStructPointer).myIntField; which is like tempAddress = (void *)myStructPointer + offset_of_myIntField; myInt = *((int *)tempAddress);.
What this means is that if you have an array of structures (which is mostly a pointer to the first structure in the array), indexing the array causes the pointer to be implicitly dereferenced, and using -> also causes implicit dereferencing; and if you do both then you've (implicitly) dereferenced a pointer twice, which is too much dereferencing (because it's not a pointer to a pointer to a structure, or an array of pointers to structures). Because you only want it dereferenced once you have to choose between one implicit deference (array indexing) or the other implicit dereference (->); e.g. you can choose between myInt = idCard[i].nameCardID; or myInt = (idCard + i)->nameCardID;.
Of course the important thing is making code easy to read, and myInt = idCard[i].nameCardID; is easier to read than myInt = (idCard + i)->nameCardID;.

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.

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

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 );
}

Confused About Pointers in C and changing data at memory addresses

I think I will understand this concept better if someone can assist me in a current project that I'm working on. I want to use C to edit data at specific memory addresses, using pointers. Specifically, I have two character arrays (strings) which I need to both read data from at specific locations, and also write to at specific locations.
I'm mostly confused about syntax of pointers, such as * and -> and &.
From my understanding, the * refers to the data kept at the current memory address of the pointer. So, for example, if I wanted to edit the data at the beginning memory address of a char *p, I would do something like: (*p) = 'c';
Now, what if I wanted do to alter a character at the 2nd memory address from the beginning of p?
Also, I understand that & refers to the location of the pointer. But I don't know how to use this syntax.
Here is my example:
int orig_length = strlen(original_string); //-1 for \0?
char *poriginal, *pnew_string;
poriginal = &original_string;
while(orig_length>0) {
k = 0;
j = 0;
while(isalpha(*(poriginal+j))) {
j++;
k++;
}
while(k > 0) {
*(pnew_string+(j-k)) = toupper(*(poriginal+k-1)); //toupper
k--;
}
if(*(poriginal+(j)) == '_') {
*(pnew_string+(j)) = ' ';
}
else {
*(pnew_string+(j)) = *(poriginal+(j));
}
orig_length = orig_length - j;
}
*(pnew_string+strlen(pnew_string)) = '\0'; //Syn? Is this actually necessary?
... //program continues...
By the way, this program is meant to take one string "now_i_understand!" and reverse each word, capitalize each word, switch _ to ' ', and leave other punctuation alone: "WON I DNATSREDNU!"
If what you are dealing with is an array of characters (and it is), use array syntax:
pnew_string[j+1] = poriginal[j+1];
Note that this syntax is equivalent to:
*(pnew_string + j + 1) = *(poriginal + j + 1);
but is more readable.
Dealing with most of the other cases you've got should be obvious given this example.
The * and & operators are inverses of each other. A pointer object hold the address of some other object in memory (or it old a null pointer, which doesn't point to any object).
The unary * operator takes a pointer operand, and gives you the object that it points to; this is called dereferencing.
The unary & operator takes an operand that refers to an object of any type, and gives you a pointer to that object. & is the address-of operator.
For example:
int obj = 42; /* obj is an object of type int; it currently holds the value 42 */
int *ptr; /* ptr is a pointer to an int */
ptr = &obj; /* ptr now holds the address of obj */
printf("obj = %d\n", obj); /* prints 42 */
printf("*ptr = %d\n", *ptr); /* also prints 42; *ptr is another name for obj */
The -> operator is shorthand for dereferencing a pointer and accessing a member of what it points to. The prefix must be a pointer to a struct or union. foo->bar means the same thing as (*foo).bar, where foo is a pointer and bar is the name of a member of what foo points to.
You can also perform arithmetic on pointers. If ptr is a pointer pointing to an element of an array, then ptr + 1 points to the next element of the array, ptr + 2 points to the element after that, and so forth.
The [] array indexing operator is actually defined in terms of pointer arithmetic. ptr[2] means exactly the same thing as *(ptr+2). Combine that with the fact that an array name, in most contexts, decays to a pointer to the array's first element, and with a little thought you'll see how arr[2] refers to the third element of the array arr (third because indexing starts at 0).
I strongly recommend sections 4 (Pointers) and 6 (Arrays and Pointers) of the comp.lang.c FAQ; it will likely explain this stuff better than I have.

Resources