How to access second member of struct via pointer? - c

I have seen the first address of struct is simultaneously the first address of first member of that struct. Now what I would like to understand is, why I need always double pointer to move around in the struct:
#include <stdio.h>
#include <stdlib.h>
struct foo
{
char *s;
char *q;
};
int main()
{
struct foo *p = malloc(sizeof(struct foo));
char ar[] = "abcd\n";
char ar2[] = "efgh\n";
*(char**)p = ar;
*(char**)((char**)p+1) = ar2; //here pointer arithmetic (char**)p+1
printf("%s\n",p->q);
}
the question is, why do I need char** instead of simple char*?
What I saw in assembler is in case of simple char*, the arithmetic would behave like normal char. That is -> the expression of (char*)p+1 would move the address p just by one byte (instead of 8 as address are 8 bytes long). But yet the type char* is address, so I don't get why the arithmetic behave like the dereference type instead (plain char -> one byte).
So the only solution for me was to add another indirection char**, where the pointer-arithmetic magically takes 8 as size. So why in structs is needed such bizarre conversion?

You are doing funny things. You should just do:
struct foo *p = malloc(sizeof(struct foo));
char ar[] = "abcd\n";
char ar2[] = "efgh\n";
p->s = ar;
p->q = ar2;

First of all, what you are doing is slightly bizarre. It's also unsafe, since there may be padding between struct members and your address calculation may be off (that's likely not true in this particular case, but it's something to keep in mind).
As to why you need multiple pointers...
The type of p is struct foo * - it's already a pointer type. Each of the members s and q have type char *. To access the s or q members, you need to dereference p:
(*p).s = ar; // char * == char *
(*p).q = ar2; // char * == char *
So if you're trying to access the first character pointed to by s through p, you're trying to access a character through a pointer (s) through another pointer (p). p does not store the address of the first character of s, it stores the address of the thing that stores the address of the first character of s. Hence the need to cast p to char ** instead of char *.
And at this point I must emphasize DON'T DO THIS. You can't safely iterate through struct members using a pointer.
The -> operator was introduced to make accessing struct members through a pointer a little less eye-stabby:
p->s = ar; // equivalent to (*p).s = ar
p->q = ar2; // equivalent to (*p).q = ar2

As the address of an object of a structure type is equal to the address of its first member then you could write for example
( void * )&p->s == ( void * )p
Here is a demonstrative program
#include <stdio.h>
#include <stdlib.h>
struct foo
{
char *s;
char *q;
};
int main(void)
{
struct foo *p = malloc(sizeof(struct foo));
printf( "( void * )p == ( void * )&p->s is %s\n",
( void * )p == ( void * )&p->s ? "true" : "false" );
return 0;
}
Its output is
true
So the value of the pointer p is equal to the address of the data member s.
In other words a pointer to the data member s is equal to the pointer p.
As the type of the data member s is char * then pointer to s has the type char **.
To assign the pointed object you need to cast the pointer p of the type struct foo * to the type char **. To access the pointed object that is the data member s you have to dereference the pointer of the type char **.
As a result you have
*(char**)p = ar;
Now the data member s (that is the pointer of the type char *) is assigned with the address of the first element of the array ar.
In the second expression the left most casting is redundant
*(char**)((char**)p+1) = ar2;
^^^^^^^^
because the expression (char**)p+1 is already has the type char **. So you could just write
*((char**)p+1) = ar2;

why do I need char** instead of simple char*
With pointer usage, the the left side of the assignment, code needs the address of the object.
*address_of_the_object = object
As the object is a char *, the type on the left side, the address of the object, needs to be type char **.
How to access second member of struct via pointer?
Better to instead use the sensible:
p->q = ar2;
... then the convoluted:
// |-- address of p->q as a char * ----|
*((char **) ((char *)p + offsetof(struct foo, q))) = ar2;
//|------------ address of p->q as a char ** ---|
OP's *(char**)((char**)p+1) = ar2; is amiss as it does the wrong pointer math and assumes no padding.
Convoluted approach details.
To portable find the offset within a struct, use offsetof(struct foo, q). It returns the byte offset and will accounts for potential padding. Add that to a char * version of the struct address to do the proper pointer addition to form the address of p->q. That sum is a char *, Convert to the type of the address of the object. Lastly de-reference it on the LHS as part of the assignment.

Related

Allocate memory without declaring a type and then assign a struct type later

I can explicitly create a struct pointer to allocated memory no problem.
widget *p = malloc(sizeof(widget));
and then access members of p like p->i.
But in the following example of allocating memory without declaring a type, I get an error trying to access i because the type of pointer is void or char and not struct.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char c[10];
int i;
double d;
} widget;
int main() {
//two ways to do this. char was convention before void type was introduced
void *p = malloc(sizeof(widget)); //base type void is not a structure or union
//char * p = malloc(sizeof(widget));//base type char is not s structure or union
widget w = {"abc", 9, 3.2};
memcpy(p, &w, sizeof(widget)); //coerced to void * pointers
printf("%d", p->i);// error here trying to access
return 0;
}
This example is from "Effective C" by Robert Seacord. Here is what the book says about the example.
In either case the object pointed to by p has no type until an object
is copied into this storage. Once this occurs the object has the
effective type of the last object copied into this storage, which
imprints the type onto the allocated object. In the following example,
the storage referenced by p has an effective type of widget following
the call to memcpy.
I tried casting p to a pointer to widget type but this made no difference.
I am probably misunderstanding or missing something. In the book the only difference is he uses a size variable in the example with no explanation as to what the value of the size should be when creating the void * pointer.
I assumed it should be of sizeof(widget) in order to hold a widget. On the memcpy line he actually uses sizeof(widget) in the book.
Also the comment //coerced to void * pointers is from the book and I don't know what it means. The rest of the comments are mine.
Can someone please explain to me why this is not working?
Update: Here are the attempts I made to cast void * to widget * after memcpy
//casting attempts
(widget *) p; //no change
widget *q = (widget *) p;
printf("%d", q->i); // works
printf("%d", ((widget *)p)->i); //also works
The so-called “imprinting” of effective type is notional: It is used only as an abstract description to describe how compilers work or may work. No actual recording of the type is made in memory.
You must provide the type that is used to access the object, but writing expressions with that type. For example, it p is declared void *p, then the type of p is void * regardless of what has been stored at the address it points to, and *p will always be void, which cannot be used to access an object. You can convert p to widget * by using a cast, (widget *) p, and then the result of that expression has type widget *, and you can use it to access an object, as width ((widget *) p)->i.
(widget *) p; //no change
The cast operator merely produces a value; the result of (widget *) p is a value that can be used further in an expression, as in an assignment expression like q = (widget *) p or a printf like printf("%d\n", ((widget *) p)->i);. It does not make any change in p.

How to get struct address inside array of structs?

I'm trying to get struct's address.
I want to get address in an int *, and I want to change address by adding numbers to the int *. I tried several ways, but I can't solve it.
struct num_d {
unsigned char data;
unsigned char pad1;
unsigned char pad2;
unsigned char pad3;
};
struct num_d **m = malloc(sizeof(struct num_d *) * row);
for (int i = 0; i < row; i++)
{
m[i] = malloc(sizeof(struct num_d) * col);
}
How can I get m[0][0]'s address in an int *?
first things first lets typedef your struct, so we can type less and be more clear:
typedef struct num_d num_d;
void pointer
A pointer to void is a "generic" pointer type. A void * can be converted to any other pointer type without an explicit cast. we cannot de-reference a void * or do pointer arithmetic with it; you must convert it to a complete data type pointer first (like int* e.g.) then do the de-refrence or the pointer arithmetic.
Now, malloc() return a void* which points to the allocated heap buffer (if malloc successed in allocation other wise null is the return value).
you code become:
num_d** m = malloc(sizeof(num_d*) * row); /*m is an array of void* pointers (not initialized)*/
for (int i = 0; i < row; i++)
{
m[i] = malloc(sizeof(num_d) * col); /*in each element in m you have a void* that points to struct num_d on the heap*/
}
the sizeof(void*) is the same as sizeof any pointer (except function pointers in some machines/os).
putting it all together
How can I get m[0][0]'s address in an int *?
This is a wrong question! because m is an array of void* to "num_d structs" (holding the num_d heap address).
if you want the start address of the i-th num_d struct in the array m, then, just return the void* in the index i in this array m[i]. and if you want to cast it just cast it (no need actually) just assign it:
int* ptr = m[i];
Take in mind that compilers will warn you, regarding the assignment above (but this assignment is supported and legal) :
warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
or (no need again):
int* ptr = (int*)m[i];
I don't know why you need such behavior, it makes more sense to cast to num_d*
if you want the address of the first data member in the struct num_d, then you must cast to the appropriate data type to get the expected data:
unsigned char data = ((num_d*)m[i])->data;
unsigned char* p_data = &((num_d*)m[i])->data;
You don't need to have the address in an int* in order to be adding to it. The way that [] works, is that it adds to the pointer and dereferences.
You can just add to *(m[0] + 1) to get the second element.
How about:
int *ptr = (int *) m[0];

pointer to pointer for struct

I have the following code
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int age;
} data;
int storage (data **str) {
*str = malloc(4 * sizeof(**str));
(*str)[0].age = 12;
return 0;
}
int main() {
data *variable = NULL;
storage(&variable);
return 0;
}
I took it from a website source. I think I have a misunderstanding about a basic pointer to pointer concept because here in this code, we have a pointer to a struct, variable, and we are passing this to storage function, which expects pointer to pointer of struct type. After memory was malloced, I don't understand this assignment
(*str)[0].age = 12
It was assigned as if, str was of (*)[] type. I dont understand how this assignment works, like str is now a pointer to an array of structs?
First, a note about C syntax for dereferencing pointers:
a[b] is equivalent to *(a + b), is equivalent to *(b + a), is equivalent to b[a].
Now, in
int main() {
data *variable = NULL;
storage(&variable);
return 0;
}
variable is of type "pointer to data", therefore its address &variable is of type "pointer to pointer to data". This is passed to int storage(data **str), and is the correct type for the argument str.
int storage (data **str) {
*str = malloc(4 * sizeof(**str));
(*str)[0].age = 12;
return 0;
}
Here, str is dereferenced, yielding an lvalue of type data * designating the same object as main()s variable. Since it is an lvalue, it can be assigned to.
malloc() allocates memory without declared type, large enough (and sufficiently aligned) to contain four contiguous objects of type data. It returns a pointer to the beginning of the allocation.
(*str)[0] is now an lvalue designating an object of type data, and by accessing the memory malloc() allocated through this expression, the effective type of the memory becomes data. (*str)[0].age = 12; assigns the value 12 to the age-member of this object, leaving the other members of the struct (and the rest of the allocated memory) uninitialized.
It can be illustrated like this
main:
data* variable = NULL; //variable is a pointer
storage(&variable) //the address of the pointer is &variable
the storage(data**) allows the function to take the address
of the pointer variable
this allows storage to change what variable points to
In storage, the following statement changes what variable points to by dereferencing (since we did pass the address of variable):
*str = malloc(4 * sizeof(**str) )
The malloc allocates a memory block containing four structs (which each has the size sizeof(struct data) bytes)
A struct is just a convenient way to access a part of memory, the
struct describes the layout of the memory. The statement
(*str)[0].age = 12;
is the equivalent of
data* d = *str;
d[0].age = 12;
or you can write it as a ptr with offset:
data* d = *str;
*(d + 0).age = 12;
edit: a clarification about malloc
malloc returns a block of memory allocated in bytes, the return type of malloc is void* so per definition it has no type and can be assigned to a pointer of arbitrary type:
T* ptr = malloc(n * sizeof(T));
After the assignment to ptr, the memory is treated as one or more elements of type T by using the pointer T*
Well, I think your code is simply identical to:
#include <stdlib.h>
#include <stdio.h>
typedef struct
{
int age;
} data;
int main()
{
data *variable = NULL;
variable = malloc(4 * sizeof(*variable));
*(variable + 0).age = 12;
return 0;
}
So variable is malloced with a block of memory, which is large enough to hold 4 datas(from variable[0] to variable[3]). That's all.
This piece of code might help illustrate what's happening, the really interesting line is
assert(sizeof(**str2) == sizeof(data));
Your numbers may vary form mine but first lets create a struct with a rather dull but hard to fake size for testing purposes.
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct {
uint8_t age;
uint8_t here_as_illustartion_only[1728];
} data;
int main() {
data str;
data * str1 = &str;
data ** str2 = &str1;
printf("sizeof(str) =%*zu\n", 5, sizeof(str));
printf("sizeof(str1) =%*zu\n", 5, sizeof(str1));
printf("sizeof(str2) =%*zu\n", 5, sizeof(str2));
printf("sizeof(*str2) =%*zu\n", 5, sizeof(*str2));
printf("sizeof(**str2) =%*zu\n", 5, sizeof(**str2));
assert(sizeof(**str2) == sizeof(data));
return 0;
}
On my machine this prints the following
sizeof(str) = 1729
sizeof(str1) = 8
sizeof(str2) = 8
sizeof(*str2) = 8
sizeof(**str2) = 1729
Note the size of the pointer to pointer ie sizeof(**) is the dull number we're looking for.

constant pointer vs pointer on a constant value [duplicate]

This question already has answers here:
What is the difference between char * const and const char *?
(19 answers)
Closed 7 years ago.
What is the difference between the following declarations?
char * const a;
const char * a;
In order to understand the difference I wrote this small program:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
char a = 'x';
char b = 'y';
char * const pc1 = &a;
const char * pc2 = &a;
printf ("Before\n");
printf ("pc1=%p\n", pc1);
printf ("*pc1=%c\n", *pc1);
printf ("pc2=%p\n", pc2);
printf ("*pc2=%c\n", *pc2);
*pc1 = b;
/* pc1 = &b; */
/* *pc2 = b; */
pc2 = &b;
printf ("\n\n");
printf ("After\n");
printf ("pc1=%p\n", pc1);
printf ("*pc1=%c\n", *pc1);
printf ("pc2=%p\n", pc2);
printf ("*pc2=%c\n", *pc2);
return EXIT_SUCCESS;
}
I compiled the program (with gcc 3.4) and ran it. The output highlights the difference rather well:
Before
pc1=ffbfd7e7
*pc1=x
pc2=ffbfd7e7
*pc2=x
After
pc1=ffbfd7e7
*pc1=y
pc2=ffbfd7e6
*pc2=x
However, I had to write the small program to get the answer. In case I'm away from the machine (at an interview for instance), I wouldn't be able to answer the question.
Can someone please explain, by commenting the above example, how the const keyword operates?
char * const a;
means that the pointer is constant and immutable but the pointed data is not.
You could use const_cast(in C++) or c-style cast to cast away the constness in this case as data itself is not constant.
const char * a;
means that the pointed data cannot be written to using the pointer a.
Using a const_cast(C++) or c-style cast to cast away the constness in this case causes Undefined Behavior.
To parse complicated types, you start at the variable, go left, and spiral outwards. If there aren't any arrays or functions to worry about (because these sit to the right of the variable name) this becomes a case of reading from right-to-left.
So with char *const a; you have a, which is a const pointer (*) to a char. In other words you can change the char which a is pointing at, but you can't make a point at anything different.
Conversely with const char* b; you have b, which is a pointer (*) to a char which is const. You can make b point at any char you like, but you cannot change the value of that char using *b = ...;.
You can also of course have both flavours of const-ness at one time: const char *const c;.
char * const a;
*a is writable, but a is not; in other words, you can modify the value pointed to by a, but you cannot modify a itself. a is a constant pointer to char.
const char * a;
a is writable, but *a is not; in other words, you can modify a (pointing it to a new location), but you cannot modify the value pointed to by a.
Note that this is identical to
char const * a;
In this case, a is a pointer to a const char.
Now that you know the difference between char * const a and const char * a. Many times we get confused if its a constant pointer or pointer to a constant variable.
How to read it? Follow the below simple step to identify between upper two.
Lets see how to read below declaration
char * const a;
read from Right to Left
Now start with a,
1 . adjacent to a there is const.
char * (const a);
---> So a is a constant (????).
2 . Now go along you get *
char (* (const a));
---> So a is a constant pointer to (????).
3 . Go along and there is char
(char (* (const a)));
---> a is a constant pointer to character variable
a is constant pointer to character variable.
Isn't it easy to read?
Similarily for second declaration
const char * a;
Now again start with a,
1 . Adjacent to a there is *
---> So a is a pointer to (????)
2 . Now there is char
---> so a is pointer character,
Well that doesn't make any sense!!! So shuffle pointer and character
---> so a is character pointer to (?????)
3 . Now you have constant
---> so a is character pointer to constant variable
But though you can make out what declaration means, lets make it sound more sensible.
a is pointer to constant character variable
The easiest way to understand the difference is to think of the different possibilities. There are two objects to consider, the pointer and the object pointed to (in this case 'a' is the name of the pointer, the object pointed to is unnamed, of type char). The possibilities are:
nothing is const
the pointer is const
the object pointed to is const
both the pointer and the pointed to object are const.
These different possibilities can be expressed in C as follows:
char * a;
char * const a;
const char * a;
const char * const a;
I hope this illustrates the possible differences
The first is a constant pointer to a char and the second is a pointer to a constant char. You didn't touch all the cases in your code:
char * const pc1 = &a; /* You can't make pc1 point to anything else */
const char * pc2 = &a; /* You can't dereference pc2 to write. */
*pc1 = 'c' /* Legal. */
*pc2 = 'c' /* Illegal. */
pc1 = &b; /* Illegal, pc1 is a constant pointer. */
pc2 = &b; /* Legal, pc2 itself is not constant. */
I will explain it verbally first and then with an example:
A pointer object can be declared as a const pointer or a pointer to a const object (or both):
A const pointer cannot be reassigned to point to a different object from the one it is initially assigned, but it can be used to modify the object that it points to (called the "pointee").
Reference variables are thus an alternate syntax for constpointers.
A pointer to a const object, on the other hand, can be reassigned to point to another object of the same type or of a convertible type, but it cannot be used to modify any object.
A const pointer to a const object can also be declared and can neither be used to modify the pointee nor be reassigned to point to another object.
Example:
void Foo( int * ptr,
int const * ptrToConst,
int * const constPtr,
int const * const constPtrToConst )
{
*ptr = 0; // OK: modifies the "pointee" data
ptr = 0; // OK: modifies the pointer
*ptrToConst = 0; // Error! Cannot modify the "pointee" data
ptrToConst = 0; // OK: modifies the pointer
*constPtr = 0; // OK: modifies the "pointee" data
constPtr = 0; // Error! Cannot modify the pointer
*constPtrToConst = 0; // Error! Cannot modify the "pointee" data
constPtrToConst = 0; // Error! Cannot modify the pointer
}
Happy to help! Good Luck!
Above are great answers. Here is an easy way to remember this:
a is a pointer
*a is the value
Now if you say "const a" then the pointer is const. (i.e. char * const a;)
If you say "const *a" then the value is const. (i.e. const char * a;)
You may use cdecl utility or its online versions, like https://cdecl.org/
For example:
void (* x)(int (*[])());
is a
declare x as pointer to function (array of pointer to function returning int) returning void
Trying to answer in simple way:
char * const a; => a is (const) constant (*) pointer of type char {L <- R}. =>( Constant Pointer )
const char * a; => a is (*) pointer to char constant {L <- R}. =>( Pointer to Constant)
Constant Pointer:
pointer is constant !!. i.e, the address it is holding can't be changed. It will be stored in read only memory.
Let's try to change the address of pointer to understand more:
char * const a = &b;
char c;
a = &c; // illegal , you can't change the address. `a` is const at L-value, so can't change. `a` is read-only variable.
It means once constant pointer points some thing it is forever.
pointer a points only b.
However you can change the value of b eg:
char b='a';
char * const a =&b;
printf("\n print a : [%c]\n",*a);
*a = 'c';
printf("\n now print a : [%c]\n",*a);
Pointer to Constant:
Value pointed by the pointer can't be changed.
const char *a;
char b = 'b';
const char * a =&b;
char c;
a=&c; //legal
*a = 'c'; // illegal , *a is pointer to constant can't change!.
const char * a;
This states pointer to constant character.
For eg.
char b='s';
const char *a = &b;
Here a points to a constant char('s',in this case).You can't use a to change that value.But this declaration doesn't mean that value it points to is really a constant,it just means the value is a constant insofar as a is concerned.
You can change the value of b directly by changing the value of b,but you can't change the value indirectly via the a pointer.
*a='t'; //INVALID
b='t' ; //VALID
char * const a=&b
This states a constant pointer to char.
It constraints a to point only to b however it allows you to alter the value of b.
Hope it helps!!! :)

Given the address of a pointer, how do I get what it points to?

If I am given the address of a pointer, how do I get what the pointer points to?
You might mean:
/**
* #param pointer_to_pointer_to_int: the address of a pointer to an integer.
**/
void function_that_takes_pointer_to_pointer(int **pointer_to_pointer_to_int) {
int the_int = **pointer_to_pointer_to_int;
printf("The pointer points to %d\n", the_int);
}
Assuming it is a valid pointer, you can dereference it using the unary * operator:
int *ptr = ...;
int x;
x = *ptr;
The unary * operator.
int *ptr = malloc(sizeof(int));
*ptr = 45;
printf("address: %p, value: %d", ptr, *ptr);
The most common way to be given the address of a pointer is through a pointer to a pointer. If the value the pointer points to is an integer, the type of the address of the pointer is int **.
To get the pointer to the integer, you need to dereference the double pointer. Then you can dereference the integer pointer to get the integer value.
To dereference a pointer, use the * operator.
int **double_pointer = given;
int *int_pointer = *double_pointer;
int value = *int_pointer;
You can also chain the dereferences to do that on one line.
int **double_pointer = given;
int value = **double_pointer;
The unary * operator returns or sets the value at a memory location.
For example:
int val = 42;
int* ptr = &val;
assert(val == *ptr);
If you have the address of a pointer, you would write **pointerpointer.
Going off of RedX's comment, If you have a situation like
void foo(void *ptr)
{
...
}
where the value of ptr is a pointer to a pointer to int, for example, you could do something like
void foo(void *ptr)
{
int x = **((int **) ptr);
...
}
Basically, you cast ptr to int **, then double-dereference it.
If you don't know what the target type is ahead of time (e.g., the function is meant to handle pointers to multiple types), then you're going to have to figure out a way to encode that type information in a second argument and pass it to the function.
There are two possible answers to your question depending on whether the compiler has a clue about the data that's referred or not.
Declaring a pointer of type int *, char * or mytype * instructs the compiler that a later attempt to dereference it using the unary * operator must yield a result of int, char or mytype respectively.
In the other case you would normally store a pointer either in a void * (generic, untyped pointer) or in a uintptr_t (an unsigned int the same size of a pointer, but without pointer semantics). In such a case the compiler doesn't have a clue how to interpret the dereferencing operator, so you must explicitly cast such a pointer to another pointer type, and only then dereference it:
int x = 5;
void *p = &x; /* p now points to an int, but the compiler doesn't know it */
printf("%d\n", *((int *) p)); /* we know what we did and don't rely on the compiler */
printf("%d\n", *p); /* compile-time error, dereferencing has undefined semantics */
Note that in compiled, unmanaged languages like C there is no runtime information about what kind of data a pointer is pointing to, unlike languages like Java where you can use the instanceof operator to check what a reference is really pointing to at runtime.

Resources