Here is my code
struct ukai { int val[1]; };
struct kai { struct ukai daddr; struct ukai saddr; };
struct kai *k, uk;
uk.saddr.val[0] = 5;
k = &uk;
k->saddr.val[0] = 6;
unsigned int *p = (unsigned int *)malloc(sizeof(unsigned int));
p[0] = k;
int *vp;
vp = ((uint8_t *)p[0] + 4);
printf("%d\n", *vp);
This produces a segmentation fault. However if we replace the last line with printf("%u\n", vp) it gives the address i.e. &(k->saddr.val[0]). However I am unable to print the value present at the address using p[0] but able to print it using k->saddr.val[0].
I have to use p pointer in some way to access value at val[0], I can't use pointer k. I need help here, whether it is even possible or not please let me know.
The code makes no sense:
p[0] = k; converts the value of a pointer k to an int as p is a pointer to int. This is implementation defined and loses information if pointers are larger than type int.
vp = ((uint8_t *)p[0] + 4); converts the int pointed to by p to a pointer to unsigned char and makes vp point to the location 4 bytes beyond this pointer. If pointers are larger than int, this has undefined behavior. Just printing the the value of this bogus pointer might be OK, but dereferencing it has undefined behavior.
printf("%u\n", vp) uses an incorrect format for pointer vp, again this is undefined behavior, although it is unlikely to crash.
The problem is most likely related to the size of pointers and integers: if you compile this code as 64 bits, pointers are larger than ints, so converting one to the other loses information.
Here is a corrected version:
struct ukai { int val[1]; };
struct kai { struct ukai daddr; struct ukai saddr; };
struct kai *k, uk;
uk.saddr.val[0] = 5;
k = &uk;
k->saddr.val[0] = 6;
int **p = malloc(sizeof *p);
p[0] = k;
int *vp = (int *)((uint8_t *)p[0] + sizeof(int));
printf("%d\n", *vp); // should print 6
There is a lot of "dirty" mess with the addresses done here.
Some of this stuff is not recommended or even forbidden from the standard C point of view.
However such pointer/addresses tweaks are commonly used in low level programming (embedded, firmware, etc.) when some compiler implementation details are known to the user. Of course such code is not portable.
Anyway the issue here (after getting more details in the comments section) is that the machine on which this code runs is 64 bits. Thus the pointers are 64 bits width while int or unsigned int is 32 bits width.
So when storing address of k in p[0]
p[0] = k;
while p[0] is of type unsigned int and k is of type pointer to struct kai, the upper 32 bits of the k value are cut off.
To resolve this issue, the best way is to use uintptr_t as this type will alway have the proper width to hold the full address value.
uintptr_t *p = malloc(sizeof(uintptr_t));
Note: uintptr_t is optional, yet common. It is sufficient for a void*, but maybe not a function pointer. For compatible code, proper usage of uintptr_t includes object pointer --> void * --> uintptr_t --> void * --> object pointer.
Related
int a;
(&a+1) -&a: 1
(char*)(&a+1) -(char*)&a: 4
Could you please explain why we got a different result when we did (char *) casting?
I compiled the code and found that the addresses are the same before and after casting. But when we do arithmetic, we get different results. Why?
&a: 1283454684
&a+1: 1283454688
(char*)&a: 1283454684
(char*)(&a+1): 1283454688
When doing pointer arithmetic the C compiler uses the size of the data pointed by the pointer as the "unit of measure", given that the smallest size is a single byte.
So when you have a pointer type* p and you add n the compiler will do:
C:
p+n
ASM:
p + n * sizeof(<data type pointed by p>)
Note that this happens under the hood everytime you access an array.
struct bigStruct{
int a;
int b;
...
int z;
};
// Define array of 100 bigStructs
struct bigStruct allStructs[100];
allStructs[3] == *(&allStructs + 3)
allStructs[3] == *(&struct bigStruct)((char*)&allStructs + 3*sizeof(struct bigStruct))
I wrote a pretty simple piece of C code:
int main(void) {
void *area = malloc(2 * sizeof(int));
unsigned int *int_one = (unsigned int *) area;
unsigned int *int_two = ((unsigned int *) area) + 3;
*int_two = 4293422034;
*int_one = 2;
printf("%u\n%u\n", *int_two, *int_one);
return 0;
}
sizeof(int) is 4 on my machine. Per my understanding, shouldn't the modification of memory at address int_one have an effect on the value stored at address int_two?
Modifying *int_one alters the first 4 bytes of mem. address area (perhaps not all 4, but enough to warrant the result I'm expecting?), and the integer at address int_two starts at the last byte of integer int_one.
So, shouldn't changing memory at int_one have an effect on memory at int_two?
Yet the printf call produces 4293422034 and 2 respectively.
I made sure to use unsigned variables to avoid confusion around 2s complement and negative values, and to use a small value for *int_one to warrant the change of its last byte (don't know if this is right?)
What am I not getting?
Operator '+', when applied to a pointer, increases the pointer n times the size of the object it points to. So increasing an int* by 3 does not add 3 bytes but 3*sizeof(int) bytes.
Pointer arithmetic is scaled by the size of the type the pointer points at. (sizeof(unsigned int) in your case). You'd need to cast to (char*) before adding 3 if you want to increase the address by 3 bytes, but converting that to an unsigned* pointer would incur undefined behavior by violating alignment requirements (6.3.2.3p7) and dereferencing the pointer would make the program even "more undefined" by violating strict aliasing rules (6.5p7).
To realy do this kind of type punning right, you'd need to use memcpy (or unions).
Example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
void *area = malloc(2 * sizeof(int));
if(!area) return EXIT_FAILURE;
unsigned int *int_one_p = area;
void *int_two_p = (((char*) area) + 3); /*saving this to an (unsigned*) would be UB*/
memcpy(int_two_p,&(unsigned){4293422034},sizeof(unsigned));
memcpy(int_one_p,&(unsigned){2},sizeof(unsigned));
unsigned one,two;
memcpy(&one,int_one_p, sizeof(one));
memcpy(&two,int_two_p, sizeof(two));
printf("%u\n%u\n", two, one);
return 0;
}
Pointer1 points to 5.
Pointer2 points to 3.
I want to multiply 5*3, but I only have the pointers. How would I do this in C?
Also, what does uint32_t *pointer mean when:
pointer[2] = {1, 2};
I do not know what is so hard for the answerers to understand about this question. It is obviously about dereferencing pointers.
This is how you display the contents of the pointer that it is pointing to:
#include <stdio.h>
int main(void)
{
int num1 = 5;
int num2 = 3;
int* num1_ptr = &num1;
int* num2_ptr - &num2;
int sum = *num1_ptr * *num2_ptr;
printf("%d\n", sum);
return 0;
}
*num1_ptr and *num2_ptr takes your pointers and references what the contents of that memory address.
I can't answer the first half of your question without more information, but uint32_t* pointer is simply a pointer to an unsigned 32-bit integer value (unsigned int and uint32_t are usually equivalent types, depending on your compiler).
If I see a declaration that simply reads uint32_t* pointer without more information I'm going to assume it's a pointer to a single value, and that using the indexing operator [n] on such a pointer is basically overflowing the single-element-sized buffer. However if the pointer is assigned the result from an array or buffer function (e.g. malloc, calloc, etc) then using the indexing operator is fine, however I would prefer to see uint32_t pointer[] used as the declaration as it makes it much easier to determine the developer's intent.
uint32_t *pointer is just a pointer with garbage value unless you point it to something.
pointer[0] = 1;
pointer[1] = 2;
is only valid if you have earlier pointed it to some array of type uint32_t with atleast size two or to a block containing uint32_ts defined using malloc as follows:
uint32_t *pointer;
pointer = (uint32_t*)malloc(sizeof(int*SIZE); //SIZE > 2 here
or
uint32_t array[10];
pointer = & array[0]; // also, pointer = array; would also work.
int main(void)
{
int variableA = 5;
int variableB = 3;
int* ptr1 = &variableA; // Pointer1 points to 5.
int* ptr2 = &variableB; // Pointer2 points to 3.
int answer;
answer = (*ptr1) * (*ptr2); // I want to multiply 5*3, but I only have the pointers.
// Answer gets set to [value stored at ptr1(5)] MultipliedBy [value stored at ptr2(3)]
}
Your misconception is that pointers do not refer to values, such as 5 and 3.
pointers refer to variables, such as variableA and variableB; those variables have values which can be accessed and changed via the pointer.But the pointer only refers to the variable, not directly to the value behind it.
I'm trying to better understand c, and I'm having a hard time understanding where I use the * and & characters. And just struct's in general. Here's a bit of code:
void word_not(lc3_word_t *R, lc3_word_t A) {
int *ptr;
*ptr = &R;
&ptr[0] = 1;
printf("this is R at spot 0: %d", ptr[0]);
}
lc3_word_t is a struct defined like this:
struct lc3_word_t__ {
BIT b15;
BIT b14;
BIT b13;
BIT b12;
BIT b11;
BIT b10;
BIT b9;
BIT b8;
BIT b7;
BIT b6;
BIT b5;
BIT b4;
BIT b3;
BIT b2;
BIT b1;
BIT b0;
};
This code doesn't do anything, it compiles but once I run it I get a "Segmentation fault" error. I'm just trying to understand how to read and write to a struct and using pointers. Thanks :)
New Code:
void word_not(lc3_word_t *R, lc3_word_t A) {
int* ptr;
ptr = &R;
ptr->b0 = 1;
printf("this is: %d", ptr->b0);
}
Here's a quick rundown of pointers (as I use them, at least):
int i;
int* p; //I declare pointers with the asterisk next to the type, not the name;
//it's not conventional, but int* seems like the full data type to me.
i = 17; //i now holds the value 17 (obviously)
p = &i; //p now holds the address of i (&x gives you the address of x)
*p = 3; //the thing pointed to by p (in our case, i) now holds the value 3
//the *x operator is sort of the reverse of the &x operator
printf("%i\n", i); //this will print 3, cause we changed the value of i (via *p)
And paired with structs:
typedef struct
{
unsigned char a;
unsigned char r;
unsigned char g;
unsigned char b;
} Color;
Color c;
Color* p;
p = &c; //just like the last code
p->g = 255; //set the 'g' member of the struct to 255
//this works because the compiler knows that Color* p points to a Color
//note that we don't use p[x] to get at the members - that's for arrays
And finally, with arrays:
int a[] = {1, 2, 7, 4};
int* p;
p = a; //note the lack of the & (address of) operator
//we don't need it, as arrays behave like pointers internally
//alternatively, "p = &a[0];" would have given the same result
p[2] = 3; //set that seven back to what it should be
//note the lack of the * (dereference) operator
//we don't need it, as the [] operator dereferences for us
//alternatively, we could have used "*(p+2) = 3;"
Hope this clears some things up - and don't hesitate to ask for more details if there's anything I've left out. Cheers!
I think you are looking for a general tutorial on C (of which there are many). Just check google. The following site has good info that will explain your questions better.
http://www.cplusplus.com/doc/tutorial/pointers/
http://www.cplusplus.com/doc/tutorial/structures/
They will help you with basic syntax and understanding what the operators are and how they work. Note that the site is C++ but the basics are the same in C.
First of all, your second line should be giving you some sort of warning about converting a pointer into an int. The third line I'm surprised compiles at all. Compile at your highest warning level, and heed the warnings.
The * does different things depending on whether it is in a declaration or an expression. In a declaration (like int *ptr or lc3_word_t *R) it just means "this is a pointer."
In an expression (like *ptr = &R) it means to dereference the pointer, which is basically to use the pointed-to value like a regular variable.
The & means "take the address of this." If something is not a pointer, you use it to turn it into a pointer. If something is already a pointer (like R or ptr in your function), you don't need to take the address of it again.
int *ptr;
*ptr = &R;
Here ptr is not initialized. It can point to whatever. Then you dereference it with * and assign it the address of R. That should not compile since &R is of type lc3_word_t** (pointer to pointer), while *ptr is of type int.
&ptr[0] = 1; is not legal either. Here you take the address of ptr[0] and try to assign it 1. This is also illegal since it is an rvalue, but you can think of it that you cannot change the location of the variable ptr[0] since what you're essentially trying to do is changing the address of ptr[0].
Let's step through the code.
First you declare a pointer to int: int *ptr. By the way I like to write it like this int* ptr (with * next to int instead of ptr) to remind myself that pointer is part of the type, i.e. the type of ptr is pointer to int.
Next you assign the value pointed to by ptr to the address of R. * dereferences the pointer (gets the value pointed to) and & gives the address. This is your problem. You've mixed up the types. Assigning the address of R (lc3_word_t**) to *ptr (int) won't work.
Next is &ptr[0] = 1;. This doesn't make a whole lot of sense either. &ptr[0] is the address of the first element of ptr (as an array). I'm guessing you want just the value at the first address, that is ptr[0] or *ptr.
Ignoring padding/alignment issues and given the following struct, what is best way to get and set the value of member_b without using the member name.
struct mystruct {
int member_a;
int member_b;
}
struct mystruct *s = malloc(sizeof(struct mystruct));
Put another way; How would you express the following in terms of pointers/offsets:
s->member_b = 3;
printf("%i",s->member_b);
My guess is to
calculate the offset by finding the sizeof the member_a (int)
cast the struct to a single word pointer type (char?)
create an int pointer and set the address (to *charpointer + offset?)
use my int pointer to set the memory contents
but I get a bit confused about casting to a char type or if something like memset is more apropriate or if generally i'm aproching this totally wrong.
Cheers for any help
The approach you've outlined is roughly correct, although you should use offsetof instead of attempting to figure out the offset on your own. I'm not sure why you mention memset -- it sets the contents of a block to a specified value, which seems quite unrelated to the question at hand.
Here's some code to demonstrate how it works:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
typedef struct x {
int member_a;
int member_b;
} x;
int main() {
x *s = malloc(sizeof(x));
char *base;
size_t offset;
int *b;
// initialize both members to known values
s->member_a = 1;
s->member_b = 2;
// get base address
base = (char *)s;
// and the offset to member_b
offset = offsetof(x, member_b);
// Compute address of member_b
b = (int *)(base+offset);
// write to member_b via our pointer
*b = 10;
// print out via name, to show it was changed to new value.
printf("%d\n", s->member_b);
return 0;
}
The full technique:
Get the offset using offsetof:
b_offset = offsetof(struct mystruct, member_b);
Get the address of your structure as a char * pointer.
char *sc = (char *)s;
Add the add the offset to the structure address, cast the value to a pointer to the appropriate type and dereference:
*(int *)(sc + b_offset)
Ignoring padding and alignment, as you said...
If the elements you're pointing to are entirely of a single type, as in your example, you can just cast the structure to the desired type and treat it as an array:
printf("%i", ((int *)(&s))[1]);
It's possible calculate the offset based on the struct and NULL as reference pointer
e.g " &(((type *)0)->field)"
Example:
struct my_struct {
int x;
int y;
int *m;
int *h;
};
int main()
{
printf("offset %d\n", (int) &((((struct my_struct*)0)->h)));
return 0;
}
In this particular example, you can address it by *((int *) ((char *) s + sizeof(int))). I'm not sure why you want that, so I'm assuming didactic purposes, therefore the explanation follows.
The bit of code translates as: take the memory starting at address s and treat it as memory pointing to char. To that address, add sizeof(int) char-chunks - you will get a new address. Take the value that the address thus created and treat it as an int.
Note that writing *(s + sizeof(int)) would give the address at s plus sizeof(int) sizeof(mystruct) chunks
Edit: as per Andrey's comment, using offsetof:
*((int *) ((byte *) s + offsetof(struct mystruct, member_b)))
Edit 2: I replaced all bytes with chars as sizeof(char) is guaranteed to be 1.
It sounds from your comments that what you're really doing is packing and unpacking a bunch of disparate data types into a single block of memory. While you can get away with doing that with direct pointer casts, as most of the other answers have suggested:
void set_int(void *block, size_t offset, int val)
{
char *p = block;
*(int *)(p + offset) = val;
}
int get_int(void *block, size_t offset)
{
char *p = block;
return *(int *)(p + offset);
}
The problem is that this is non-portable. There's no general way to ensure that the types are stored within your block with the correct alignment, and some architectures simply cannot do loads or stores to unaligned addresses. In the special case where the layout of your block is defined by a declared structure, it will be OK, because the struct layout will include the necessary padding to ensure the right alignment. However since you can't access the members by name, it sounds like this isn't actually what you're doing.
To do this portably, you need to use memcpy:
void set_int(void *block, size_t offset, int val)
{
char *p = block;
memcpy(p + offset, &val, sizeof val);
}
int get_int(void *block, size_t offset)
{
char *p = block;
int val;
memcpy(&val, p + offset, sizeof val);
return val;
}
(similar for the other types).