I don't understand why I can't print out ints b and c in this way:
#include "stdio.h"
typedef struct{
int a;
int b;
int c;
} myStruct;
int main(){
myStruct MS;
MS.a = 13;
MS.b = 27;
MS.c = 39;
myStruct* pMS = &MS;
printf("pMS = %u\n", pMS );
printf("&a = %u\n", &pMS->a ); // addr of a is addr of struct
printf("&b = %u\n", &pMS->b ); // addr of b is +4 from a
printf("&c = %u\n", &pMS->c ); // addr of c is +8 from a
printf("*pMS = %d\n",*(pMS) );
printf("*pMS+4 = %d\n",*(pMS+4) );
printf("*pMS+8 = %d\n",*(pMS+8) );
}
The terminal shows bogus values for b and c (at least, I think b and c should be located at pMS+4 and pMS+8):
gcc version 4.6.3
pMS = 1926301980
&a = 1926301980
&b = 1926301984
&c = 1926301988
*pMS = 13
*pMS+4 = 32765
*pMS+8 = 32765
pMS+4 is not the address of the integer located four bytes beyond the start of the structure. Additions to pointers are scaled based on the pointer type so, if it were a pointer to an integer, it would be four integers beyond the start (16 bytes if you have 32-bit ints). See, for example:
int someInt[2] = {4, 9}; // assume 4-byte int, big-endian
int *x = &someInt[0];
// | someInt[0] # 0x1000 | someInt[1] # 0x1004 |
// | 0,0,0,4 | 0,0,0,9 |
// | x = 0x1000 | x+1 = 0x1004 |
// | *(x) = 4 | *(x+1) = 9 |
However, it's even worse in your case since your pointer is to the actual structure. That means it's scaling by the size of the entire struct, three complete integers (plus padding if needed).
This line for example
printf("*pMS+4 = %d\n",*(pMS+4) );
When you add to the pointer, it is same as indexing to array, so equal to this:
printf("*pMS+4 = %d\n", pMS[4]);
Of course there is no array, so bogus struct value is passed.
And then printf can't print structs at all, %d prints something non-sensical.
Double undefined behavior, in other words.
By perform some changes on code and implementing what #Jonathan Leffler saying on comments this way works for me.
Code
#include <stdio.h>
struct t{
int a;
int b;
int c;
};
int main(){
struct t MS;
MS.a = 13;
MS.b = 27;
MS.c = 39;
struct t* pMS = &MS;
printf("pMS =%p\n", pMS );
printf("&a = %p\n", &pMS->a ); // addr of a is addr of struct
printf("&b = %p\n", &pMS->b ); // addr of b is +4 from a
printf("&c = %p\n", &pMS->c ); // addr of c is +8 from a
printf("*pMS.a = %d\n", (* ((int *) ((void *) pMS))));//13
printf("*pMS.b = %d\n", (* ((int *) ((void *) pMS)+1)));//27
printf("*pMS.c = %d\n", (* ((int *) ((void *) pMS)+2)));//39
return 0;
}
But also this works, as you see in #hyde answer working with this way not good. structures in C are packed depending on CPU architecture, Compiler means putting struct members in packed form, for example below struct takes 8 Bytes instead of 5.
struct example {
int a;
char b;
};
I use my way because i checked before, sizeof(void *), sizeof(int *) both return 4.
Consider these lines:
printf("*pMS.a = %d\n", (* ((int *) ((void *) pMS))));//13
printf("*pMS.b = %d\n", (* ((int *) ((void *) pMS)+1)));//27
printf("*pMS.c = %d\n", (* ((int *) ((void *) pMS)+2)));//39
Why using +1 inside parenthesis cause accessing to our integers?
On my system integers numbers occupy 4 bytes, as i expressed above void * and int * have size of same 4 Bytes.
First remove void * to simplify (int *) (pMS) + 1, behave pMS like an integer size, when we add one to it jumps to next for byte address that refers to 27.
I think adding void * is for remove UB from code, as pointer have void * type pointer to structure.
For this case removing void * also works.
At last
printf("pMS =%u\n", sizeof(MS) );//12(3 * 4)
printf("pMS =%u\n", sizeof(pMS) );//4
In my platform there is no any padding or packing, as see above entire structure hold 12 byte 3 integers with 4 bytes size.
But pMs that is a pointer to first address of this structure, as first elements is integer this have 4 byte size.
ToDO
Edit post to add some further explain about pointers type and arithmetic.
Some extra things on difference between two way of using structure in this case.
Structure padding, packing depending on platform, OS, Compiler.
Why we see different address of structure when declare Global or Local inside main, that case different behavior in this case?
Related
I know this would not work, because I cannot make arithmetic on void:
int main (void) {
void *ar = malloc(25); //adress of int + adr of char + adr of int = 3 * 8 + 1 null
int a =4;
int b =6;
*(ar+0)=&a //adr of first int - 8 bytes
*(ar+8)="abc\0"; // adr of the first char - 8 bytes
*(ar+16)=&b; // adr of the second int - 8 bytes
ar[24] = NULL;
return 0;
}
So the question is , how to make an buffer with arbitrary type, only according to its byte width (specifically the buffer in this case would contains 3 addresses of arbitrary types, but that should not matter, since all addresses are 8 bytes long)?
How how to enable to compiler to do arithmetic on (void*), according to programmers intend? (because I specify how long of the buffer I want to move forward to reach the first byte to start at).
Specify the type as a pointer to a pointer to void (or as an array of pointers). The compiler knows the size of a pointer to void, allowing you to perform arithmetic as per usual.
On the stack:
void *arr[3];
Dynamically:
void **arr = malloc(sizeof(void*)*3);
Usage:
int a = 10, b = 20, c = 30;
arr[0] = &a;
arr[1] = &b;
arr[2] = &c;
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.
This may be a noob question ..but this is really confusing me..
Below is some sample code
void main() {
int a = 300;
char *ptr = &a;
int *intptr = &a;
printf("%d\n %d\n", *ptr, *intptr);
}
output:
44
300
As per my understanding,why dereferencing *ptr prints 44 is due to the fact that char pointer is one byte and so it reads only 8 bits from the address of int...
But this question:What is the size of a pointer? states Regardless of what data type they are pointing to, they have fixed size
Am i missing some thing.Why dereferencing char pointer prints 44,if pointer size is same ?
Object pointers (e.g. pointers to anything besides a function) are typically the same size on most systems you're likely to come across, however there's no guarantee of that. That being said, even though the pointers may be the same size, the types that they point to are not.
For example, on a 64-bit Windows system, pointers are typically 8 bytes in size. In your example you have char * and an int * which are most likely both 8 bytes. The difference here is that dereferencing a char * will read/write 1 byte while dereferenceing an int * will read/write 4 bytes (assuming an int is 32 bit).
Assuming little endian byte ordering, a looks like this in memory:
------------------
a | 44 | 1 | 0 | 0 |
------------------
Both ptr and intptr contain the address of a. When dereferencing ptr, which is of type char *, it only looks at the first byte. In contrast, when dereferencing intptr, which is of type int *, it looks at all 4 bytes.
First of all, your code is not valid C and it also invokes undefined behavior, so anything can happen. If your compiler didn't show you any diagnostic messages, you need to uninstall it and get a working one instead. You have the following bugs:
void main() will only work on freestanding implementations that specifically allow this form of main.
char *ptr = &a; is not a valid form of assignment in C. The pointers are not compatible(1).
Printing a character with the %d format specifier invokes undefined behavior.
After fixing these bugs, we get:
#include <stdio.h>
int main (void)
{
int a = 300;
char *ptr = (char*)&a;
int *intptr = &a;
printf("%d\n %d\n", (int)*ptr, *intptr);
}
None of this prints the size of a pointer. You print the contents of the first byte in the int a, which you translate to a char, which may or may not be signed and possibly give an incorrect result (this part is endianess-dependent). And then you print the contents of the whole int a.
What you seem to want is to print the size of the pointers themselves:
printf("%zu %zu\n", sizeof ptr, sizeof intptr);
(1) C11 6.5.16.1 emphasis mine:
Constraints
One of the following shall hold:
/--/
- the left operand has atomic, qualified, or unqualified pointer type, and (considering
the type the left operand would have after lvalue conversion) both operands are
pointers to qualified or unqualified versions of compatible types, and the type pointed
to by the left has all the qualifiers of the type pointed to by the right;
In this statement
printf("%d\n %d\n", *ptr, *intptr);
there are outputted not the pointers themselves but the data they point to.
For example 300 can be represented like 256 + 44. So 44 can be stored in one byte while 256 can be stored in another byte. And this expression *ptr gives the value 44 stored in the byte pointed to by the pointer ptr.
On the other hand the pointer intptr points to the whole object of the type int and the expression *intptr gives the value 300.
If you want to output the addresses stored in the pointers you should write
printf("%p\n %p\n", ( void * )ptr, ( void * )intptr);
To output sizes of the pointers you could write
printf("%zu\n %zu\n", sizeof( ptr ), sizeof( intptr ));
Take into account that according to the C Standard the function main without parameters shall be declared like
int main( void )
Also in this declaration you should use an explicit casting
char *ptr = ( char * )&a;
Here is a demonstrative program
#include <stdio.h>
int main(void)
{
int a = 300;
char *ptr = ( char * )&a;
int *intptr = &a;
printf( "*ptr = %d, *intptr = %d\n", *ptr, *intptr );
printf( "ptr = %p, intptr = %p\n", ( void * )ptr, ( void * )intptr );
printf( "sizeof( ptr ) = %zu, sizeof( intptr ) = %zu\n",
sizeof( ptr ), sizeof( intptr ) );
return 0;
}
Its output might look like
*ptr = 44, *intptr = 300
ptr = 0x7ffe5972613c, intptr = 0x7ffe5972613c
sizeof( ptr ) = 8, sizeof( intptr ) = 8
You introduce undefined behaviour if you cast a pointer to an object to a different type than that of the object AND access it then through this pointer.
Statement int a = 300 introduces an object of type int, char* ptr = &a introduces a pointer to an object of type char but let it point to an object of type int. This per se is not a problem, but dereferencing this pointer then through *ptr is undefined behaviour. And this does not have something to do with the printf - a statement like char x = *ptr would be UB, too. However, a statement like int x = *((int *)ptr) would be OK, as the ptr is casted back to the original type of the object it points to.
Concerning the sizes of pointers: The size of a pointer (i.e. the value necessary for storing a memory address to which the pointer points to) is fixed size; it's usually 4 bytes on a 32 bit system and 8 bytes on a 64 bit system. The size necessary for representing a memory address has nothing to do with the size of the object that resides at the respecite memory address to which the pointer points to.
The following example demonstrates this behaviour:
int main() {
int a = 300;
void *ptr = &a;
int *intptr = &a;
printf("%d %d\n", *((int*)ptr), *intptr);
}
Output:
300 300
Indeed, on a little endian architecture, the LSB would appear first in memory, thus to store 300, memory looks like
44 , 1 , 0 , 0 (for a size 4 int)
The
printf("%d\n %d\n", *ptr, *intptr);
doesn't print the pointer sizes (which are likely the same), it prints the dereferenced pointers, values of one byte, a char, then the int value.
To print the pointer sizes
printf ("%zu\n%zu\n", sizeof(ptr), sizeof(intptr));
Code
#include <stdio.h>
#include <stdint.h>
unsigned int
trans(unsigned char c){
if ('0' <=c && c <= '9') return c - '0';
if ('A' <=c && c <= 'F') return c - 'A' + 0x0A;
if ('a' <=c && c <= 'f') return c - 'a' + 0x0A;
return 0;
}
uint16_t
hex_to_uint16(const char* s) {
char *p = (char*) s;
uint16_t v = 0;
while (*p) {
if (p > s) v = v << 4;
v += trans(*p);
p++;
}
return v;
}
int main (void)
{
int n = 1;
// little endian if true
if(*(char *)&n == 1) {printf("little\n");}
int a = 300;
char *ptr = (char*)&a;
int *intptr = &a;
printf("charSize:%zu intSize:%zu\n", sizeof (char), sizeof (int));
printf("PcharSize:%zu PintSize:%zu\n", sizeof (ptr), sizeof (intptr));
//printf("Hex: %x, Decimal: %d\n", 0x2c, (int)0x2c );
//printf("int: %d\n", hex_to_uint16("2c"));
//printf("300H: %x\n", (a));
printf("PcharAddr: %p\nPintAddr: %p\n", ptr, intptr);
printf("int: %d\n", *intptr);
printf("LSB | | | MSB|\n");
printf(" 0 | 1 | 2 | 3 |\n");
printf("------------------------\n");
printf("Dec\n");
printf(" %d %d %d %d\n", *(ptr), *(ptr+1), *(ptr+2), *(ptr+3));
printf("Hex\n");
printf(" %x %x %x %x\n", *(ptr), *(ptr+1), *(ptr+2), *(ptr+3));
printf("To Big Endian:\n%.2x%x%x%x\n", (uint8_t)*(ptr+3), (uint8_t)*(ptr+2), (uint8_t)*(ptr+1), (uint8_t)*(ptr));
///https://stackoverflow.com/questions/19275955/convert-little-endian-to-big-endian
/*
* chux aswer
uint32_t num = 300;
uint8_t b[4];
b[0] = (uint8_t) (num >> 0u);
b[1] = (uint8_t) (num >> 8u);
b[2] = (uint8_t) (num >> 16u);
b[3] = (uint8_t) (num >> 24u);
printf("%x%x%x%x\n", b[3], b[2], b[1], b[0]);
*/
return 0;
}
Compile, Run
gcc -Wall -Wextra te.c -o te && ./te
no, no, no
As per my understanding,why dereferencing *ptr prints 44 is due to the fact that char pointer is one byte and so it reads only 8 bits from the address of int...
char is one byte, not char pointer. If you want to print pointer you should
printf("%p\n %p\n", ptr, intptr);
I was interested in accessing portions of memory I had allocated to get a better understanding of things, lets say I allocate 10 bytes with malloc and printf("%p", &foo) returns 0xff0a, would I be able to allocate 0xff0a->0xff1a (my hexadecimal math is bad at the moment) and access any one of those individual bytes?
I think I recall being used the keyword volatile along with a memory address for this, I am not sure what that code was able to do though..
I guess what I mean is how do I access a random byte in memory, cast as a char or integer that I can store in a pointer for accessing later on.
I'll assume you want to access a single byte from a multi-byte type such as an int or a short. The common idiom is to cast the address to a char* and deference that like so:
#include <stdio.h>
int main(void)
{
int foo = 0xDEADBEEF;
int i;
for (i = 0; i < 4; i++) {
printf("byte %d of foo is x%02X\n", i, *((unsigned char*)&foo + i));
}
return 0;
}
Output
$ ./a.out
byte 0 of foo is xEF
byte 1 of foo is xBE
byte 2 of foo is xAD
byte 3 of foo is xDE
Note The reason it looks backwards is due to x86 being little endian
printf("%p", &foo) prints the address of the pointer variable foo, not the address contained in foo (which is the one that came from malloc). You actually want:
printf("%p", (void *)foo);
If you wish to access the 10 bytes in memory pointed to by foo, you can simply use:
char *p = foo;
and then access p[0] through p[9].
If you allocate 10 bytes from 0xff0a, the address range is: 0xff0a to 0xFF14.
volatile forces the compiler to grab the stored value at that location every time. This has uses in hardware programming and multi-threaded applications.
This example stores the address of the int x into the pointer p:
int x = 5;
int * p = &x; //assign address of (operator &) x into a pointer
printf("%d\n", *p); // will display 5
You may want to use a union in order to always apply the same bunch of code to loop over the bytes area of your variable. The member 'byte' will always point to the same address as the others. You can include it into a struct in order to keep the size along with the union. A the end, you just call a function to print out or check the content of a bunch of memory...
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
union byteMap {
char* addressString;
void* addressInt;
unsigned char* byte;
};
struct structByteMap {
size_t size;
union byteMap map;
};
int main (int argc, char* argv[]) {
struct structByteMap map;
if (argc > 1) {
int temp = strtoimax(argv[1], NULL, 10);
map.map.addressInt = &temp;
map.size = sizeof(int);
} else {
map.map.addressString = "HELLO, YES HELLO";
map.size = strlen(map.map.addressString);
}
for (int i = 0; i < map.size; i++) {
printf("byte %d of param is x%02X\n", i, *(map.map.byte + i));
}
}
The Code used
#include<stdio.h>
struct st
{
char a;
short c;
int b;
};
struct st s1;
int main()
{
printf("%p %p \n",(&s1.b)-1, &s1);
}
If I print the address of &s1.b it prints 0x804a01c and &s1.b-2 prints 0x804a018
why it is printing same address 0x804a01c if i select &s1.b-1 ?
There's probably something wrong with your printing code.
#include <stdio.h>
struct st
{
char a;
short c;
int b;
};
struct st s1;
int main() {
printf("%p\n", (void*)(&s1.b));
printf("%p\n", (void*)(&s1.b - 1));
printf("%p\n", (void*)(&s1.b - 2));
}
Output:
0x403024
0x403020
0x40301c
Most likely you're printing it wrong:
#include <stdio.h>
struct st
{
char a;
short c;
int b;
};
struct st s;
int main(void)
{
printf("s: %p\n", (void *)&s);
printf("s.a: %p\n", (void *)&s.a);
printf("s.b: %p\n", (void *)&s.b);
printf("s.b-1: %p\n", (void *)(&s.b-1));
printf("s.b-2: %p\n", (void *)(&s.b-2));
return 0;
}
Prints for me:
s: 0x100001068
s.a: 0x100001068
s.b: 0x10000106c
s.b-1: 0x100001068
s.b-2: 0x100001064
Things to note:
Pointer to struct == pointer to struct's first element (guaranteed by the C standard),
I am printing the pointers with "%p" format string. "%p" needs void *, and since printf is a variadic function, I need to cast the arguments to printf to void * in this case.
What does the above program print for you?
Edit: based upon the actual code posted for printing that you posted later: you are not getting the same value for &s1.b and &s1.b-1. You are getting the same value for &s1.b-1 and &s1. The answer to that is: this happens because of chance. In your case, there is struct padding, and sizeof(short)+sizeof(char) happens to be ≤ sizeof(int). If you were on a machine where any of those assumptions were invalid, you wouldn't see that behavior. I am sure if you changed char or short to int in your code, &s1.b-1 would not equal &s1, when printed.
Finally, you should cast pointers to void * before printing:
printf("%p %p \n",(void *)((&s1.b)-1), (void *)&s1);
If the address of s1.b is 0x804a01c, then &s1.b-2 should be 0x804a014 (assuming that int is 4 bytes), not 0x804a018. Perhaps you made a mistake when you reported the address?
Thank you for posting your code. Now I see the issue. It is because of padding. To wit:
printf("sizeof(char): %d\n", sizeof(char));
printf("sizeof(short): %d\n", sizeof(short));
printf("sizeof(int): %d\n", sizeof(int));
printf("sizeof(struct st): %d\n", sizeof(struct st));
On my machine this prints
1
2
4
8
You might think, shouldn't sizeof(struct st) be 1 + 2 + 4 = 7? That's certainly a reasonable thought but because of alignment issues there is padding between a and c. Therefore, in memory, the struct looks like the following (relative to the first byte of the struct):
0x00000000: char a
0x00000001: padding
0x00000002: first byte of short c
0x00000003: second byte of short c
0x00000004: first byte of int b
0x00000005: second byte of int b
0x00000006: third byte of int b
0x00000007: fourth byte of int b
Consequently (relative to &s1):
&s1.b - 1 is ((long)&s1.b) - sizeof(int) = 4 - 4 = 0 = &s1
This is why both &s1 and &s1.b - 1 will print the same address. In particular if
&s1 = 0x804a01c
then
&s1.b = 0x804a01c + 0x00000004 = 0x804a020
and
&s1.b - 1 = 0x804a020 - 0x00000004 = 0x804a01c
and
&s1.b - 2 = 0x804a020 - 0x00000008 = 0x804a018
Note, finally, that this is implementation-specific behavior. This is not portable!