I have written this code:
#include "stdio.h"
static int static_int;
static char static_char;
static float static_float;
static char *static_pointer;
static double static_double;
static int static_end;
int main()
{
printf("static int =%d\nstatic char = %c\nstatic float = %f\nstatic pointer =0x%x\nstatic doub le =%f\n",
static_int,static_char,static_float,static_pointer,static_double);
printf("\n\n");
printf("static int =0x%x\nstatic char =0x%x\nstatic float =0x%x\nstatic pointer =0x%x\nstatic_doub le =0x%x\nstatic end =0x%x\n",
&static_int,&static_char,&static_float,&static_pointer,&static_double,&static_end);
return 0;
}
And I get this result:
static int =0
static char =
static float = 0.000000
static pointer =0x0
static double =0.000000
static int =0x804a030
static char =0x804a034
static float =0x804a038
static pointer =0x804a03c
static_double =0x804a040
static end =0x804a048
I am confused.
First, why does a char hold 4 byte memory (should it only take one?)?
And why does a float only take 4 byte memory? I think it will transform to double automatically. And a double takes 8 bytes.
PS: I use SUSE and GCC.
byte not bit.
char holds just one byte, the next variable is stored 4 byte address away because of padding.
float taked 4 bytes on most modern systems. It have nothing to do with conversion to double.
Why char hold 4 bit memory(should it only take one?)?
It doesn't. char always is exactly one byte wide, as specified by the C standard. (What makes you think it's 4 bytes long?)
And . Why float only take 4 bit memory?
I think you mean 4 bytes? No conforming C implementation has 4-bit types (the smallest type is char which is at least 8 bits wide). Again, on most modern systems, float is a 32-bit (and 4-byte, assuming an 8-bit byte) single precision IEEE-754 floating-point number, and double is a 64-bit (8-byte) double-precision IEEE-754 floating-point number.
So float is typically 4 bytes long - and the size of a float object doesn't change, even if it's implicitly converted to a double when passed to a variadic function. In C, function arguments are passed by value, so conversion to double essentially means that a copy of type double of your float variable is made (and passed to the function).
(But anyway, where did you get the information about the sizes? I don't see you using the sizeof operator anywhere...)
I am too confused by your question. So, I am answering assuming that you really meant byte when you meant bit in the above questions.
First.Why char hold 4 bit memory(should it only take one?)?
Nothing in the result shows that char is holding a 4 bytes in the memory. What you actually printed are the addresses at which the variables are stored. Not the sizes. The compiler assigning a 4-byte word to for char doesn't necessarily mean that char is occupying 4 bytes. Char only occupies 1 byte of the assigned 4 byte word and the remaining 3 bytes are padded with zeroes.
If you are talking about the char pointer, then as you are aware, the pointer stores the address of the char variable it is pointing to. And this address is a unsigned integer which is 4 bytes in size.
To get the size of the variables use sizeof operator
And . Why float only take 4 bit memory? I think it will transform to double auto ! Ant double take 8 bit!
The size of Float is 4-bytes (on 32-bit systems). So the compiler assigned 4 bytes. The size of double is always twice that of float. So the compiler assigned a 8 byte address space to store the value. I don't understand why you think that float will be transformed to double. The program doesn't require any such auto conversion.
The compiler assigns addresses in 4-byte words because the computer accesses memory one word at a time for efficiency. The general rule is that this 'access length' (which is 4 bytes in this case) must be at least the size of the lowest size primitive data type (which is char - 1 byte length)
Related
I am trying to get the bytes and pointers and how they are stored can any one explain or answer some of my questions. Thank you
int num = 513; <-- allocating a 4 bit memory by initializing
//[01][02][00][00] <-- (numbers are sorted and shown as litle endian)
char * ptr = # //char is (one byte)
↓
//[01][02][00][00]
// pointer always start from the [0] (as in this array byte length)
// in the allocated address in the memory ptr[0] is in this case = [01]
// (printed as %x02 "printf("the byte %02x\n",ptr[0]);" - if it's only
//single number 1 a zero will be added on the length so it prints out as 01)
int * ptr = # //now creating a pointer with the type of int (four bytes)
↓ ↓ ↓ ↓
//[01][02][00][00]
how can i access the first byte of this int pointer? [question01]
is there a way to see the bites inside the of the first byte([01])? [question02]
where does the pointer save the address? does it have to allocate a memory space in the ram to save whe address such as 0x233828ff21 and if so this(0x233828ff21) address requires a lot of bytes? [question03]
where does this int pointer stores it's type length (4bytes)? [question05]
what happens if i declare a type with longer byte memory allocation such as long long * ptr = # [01][02][00][00][00][00][00][00]
since i am pointing a long long to a 4 byte int, can those 4 last already been allocated by another program and in use? can i read it? [question06]
binary are only 0 and 1 and whether one of those(0 or 1) is called a bite? [question07]
one byte is 8 bits right? why am i getting 16 bits 0000000000000001 when converting the number 1 in this website (https://www.rapidtables.com/convert/number/decimal-to-binary.html) shouldn't it be 8? [question08]
Note: char * ptr = # should really be unsigned char * ptr = (unsigned char *)# to avoid compiler warnings and to ensure that the bytes are treated as unsigned values.
how can i access the first byte of this int pointer? [question01]
If you really want to access the first byte of a pointer, you can use:
unsigned char *ptr2 = (unsigned char *)&ptr;
then ptr2[0] is the first byte of the pointer ptr.
is there a way to see the bites inside the of the first byte([01])? [question02]
I assume you mean the bits inside the first byte. Bits are not directly addressable, so you need an expression (usually with bit-wise operators) to get the value each bit. For example, (ptr[m] >> n) & 1 will be the value of the nth bit of the mth byte of an object (where ptr is an unsigned char * pointing to the start of the object).
where does the pointer save the address? does it have to allocate a memory space in the ram to save whe address such as 0x233828ff21 and if so this(0x233828ff21) address requires a lot of bytes? [question03]
Addresses are stored in pointer variables in the same way as numbers are stored in variables of numeric type. At the CPU instruction level, there is no difference between a stored pointer value and a stored integer value, other than the width.
The most typical sizes of pointer types are 8 bytes or 4 bytes, depending on the target architecture of the compiler.
(There is no question04.)
where does this int pointer stores it's type length (4bytes)? [question05]
It doesn't store the length of the type, but the compiler knows that a TYPE * points to an object that is sizeof(TYPE) bytes long.
what happens if i declare a type with longer byte memory allocation such as long long * ptr = # [01][02][00][00][00][00][00][00] since i am pointing a long long to a 4 byte int, can those 4 last already been allocated by another program and in use? can i read it? [question06]
If the pointer is not correctly aligned for the referenced type (long long) then the behavior is undefined. Otherwise it can be converted back to the original pointer type int *. In any case, accessing *ptr will result in undefined behavior (unless long long is the same width as int, which is not typical).
binary are only 0 and 1 and whether one of those(0 or 1) is called a bite? [question07]
It is called a bit. There is also a type called _Bool. Expressions of type _Bool always have the value 0 or 1.
one byte is 8 bits right? why am i getting 16 bits 0000000000000001 when converting the number 1 in this website (https://www.rapidtables.com/convert/number/decimal-to-binary.html) shouldn't it be 8? [question08]
Who cares what some random web-site displays?
What C calls a "byte" is any type where sizeof(type) is 1, including char, signed char and unsigned char. It is at least 8 bits wide, but is wider than 8 bits on some exotic systems.
A pointer of character type (char *, signed char * or unsigned char *) can be used to access the individual bytes within any object, but that might not be true for pointers of other size 1 types, and is certainly not true for pointer to _Bool (_Bool *)!
• how can i access the first byte of this int pointer? [question01]
Generally, it is preferable to use unsigned char rather than char to access arbitrary bytes, so let’s do that.
After unsigned char *ptr = #, ptr is a pointer to unsigned char, and you could access the first byte of the int with *ptr or ptr[0], as in printf("The first byte, in hexadecimal, is 0x%02hhx.\n", *ptr);.
If instead you have int *ptr = #, there is no direct way to access the first byte. ptr here is a pointer to an int, and, to access an individual byte, you need a pointer to an unsigned char or other single-byte type. You could convert ptr to a pointer to unsigned char, as with (unsigned char *) ptr, and then you can access the individual byte with * (unsigned char *) ptr.
• is there a way to see the bites inside the of the first byte([01])? [question02]
The C standard does not provide a way to display the individual bits of a byte. Commonly programmers print the values in hexadecimal, as above, and read the bits from the hexadecimal digits. You can also write your own routine to write binary output from a byte.
• where does the pointer save the address? does it have to allocate a memory space in the ram to save whe address such as 0x233828ff21 and if so this(0x233828ff21) address requires a lot of bytes? [question03]
A pointer is a variable like your other int and char variables. It has space of its own in memory where its value is stored. (This model of variables having memory is used to specify the behavior of C programs. When a program is optimized by a compiler, it may change this.)
In current systems, pointers are commonly 32 or 64 bits (four or eight 8-bit bytes), depending on the target architecture. You can find out which with printf("The size of a 'char *' is %zu bytes.\n", sizeof (char *));. (The C standard allows pointers of different types to be different sizes, but that is rare in modern C implementations.)
• where does this int pointer stores it's type length (4bytes)? [question05]
The compiler knows the sizes of pointers. The pointer itself does not store the length of the thing it is pointing to. The compiler simply generates appropriate code when you use the pointer. If you use *ptr to get the value that a pointer points to, the compiler will generate a load-byte instruction if the type of ptr is char *, and it will generate a load-four-byte instruction of the type of ptr is int * (and int is four bytes in your C implementation).
• what happens if i declare a type with longer byte memory allocation such as long long * ptr = # [01][02][00][00][00][00][00][00] since i am pointing a long long to a 4 byte int, can those 4 last already been allocated by another program and in use? can i read it? [question06]
When long long is an eight-byte integer, and you have a long long *ptr that is pointing to a four-byte integer, the C standard does not define the behavior when you attempt to use *ptr.
In general-purpose multi-user operating systems, the memory after the int cannot be allocated by another program (unless this program and the other program have both arranged to share memory). Each process is given its own virtual address space, and their memory is kept separate.
Using this long long *ptr in your program may access memory beyond that of the int. This can cause various types of bugs in your program, including corrupting data and alignment errors.
• binary are only 0 and 1 and whether one of those(0 or 1) is called a bite? [question07]
One binary digit is a “bit”. Multiple binary digits are “bits”.
The smallest group of bits that a particular computer operates on as a unit is a “byte”. The size of a byte can vary; early computers had bytes of different sizes. Modern computers almost all use eight-bit bytes.
If your program includes the header <limits.h>, it defines a macro named CHAR_BIT that provides the number of bits in a byte. It is eight in almost all modern C implementations.
• one byte is 8 bits right? why am i getting 16 bits 0000000000000001 when converting the number 1 in this website (https://www.rapidtables.com/convert/number/decimal-to-binary.html) shouldn't it be 8? [question08]
The web site is not merely converting to one byte.
It seems to show at least 16 bits, choosing the least of 16, 32, or 64 bits that the value fits in as a signed integer type.
in my system,
sizeof(void*) = 8 bytes
size of all pointer types is 8 bytes.
I have this struct
struct element{void* value};
so this struct is jus a pointer value of 8 bytes.
since all type of pointers have 8 bytes, I should be able to just assign the physical address of any type of variable to this void* value
also,
sizeof(double) = 8 bytes;
question is how do I obtain the physical address of any pointer as a double value and then assign this value to any other 8 byte pointer.
so say,
int i;
int *p = &i;
struct element e;
double phy_address = ?? // the 8 byte value of p (when we print it as %d)
/*now copy this 8 byte phy_address to 8 byte void pointer e.value. */
Is it possible to typecast it as int* or any other pointer type? its jus an address...
On most systems there is an integer type that is the same size as a void *. Usually this type is int or long int or long long int. Most compilers will provide the type, intptr_t (and its unsigned cousin uintptr_t), that is a typedef of one of these types. I think people prefer to use uintptr_t because negative address values usually don't make sense. Anyway you should probably use this type instead of double.
Remember that uintptr_t is just one of the regular integer types, so once you get the pointer value into a variable of this type, you can do any integer arithmetic you like. As for how to get the pointer value into a uintptr_t, see this question/answer, Converting a non-`void` pointer to `uintptr_t` and vice-versa.
I use= these values can be used as unique identifier in a table.
OK. This information is necessary because there is no possibility to convert a pointer into a floating-point number with any meaningful value; the floating-point number will have a meaningless value in any way.
There are two possibilities to convert a pointer to a (meaningless) floating-point value but in both cases you are not guaranteed that two floating-point numbers are unique for two different pointers!
Possibility 1:
Convert the pointer to an integer and the integer to floating-point:
phy_address = (double)(uintptr_t)p;
However as Weather Vane already mentioned in his comment double values have a limited precision.
The integer values (addresses) 1234567890123456780 and 1234567890123456790 would both be rounded to 1234567890123456768.0.
Possibility 2:
Because both double and pointers are 64 bits wide you could generate a floating-point number that has the same bits as the pointer:
union {
void *p;
double d;
} u;
...
u.p = p;
phy_address = u.d;
However there are numbers (for example the 0) which have two different representations in the double data type. This means that there are two different combinations of bits (and therefore two different addresses) that will generate the same number.
For this reason there cannot be any method to convert a 64-bit value into a double value resulting in an unique double value: The data type double has less than 2^64 different values!
And it is even worse:
There are special values - so called "NaN" values. And there are a lot of them!
I just did the following test:
// Write a "NaN" value to a
...
b = a;
if(a == b) puts("equal");
if(a != b) puts("not equal");
// Check if a and b still contain the same value
...
... and I get the result "not equal" although the check at the end says that a and b still contain the same value!
Depending on your environment some NaN values (so-called "signalling NaN" values) might even cause your program to crash!
Conclusion
Personally I would never use floating-point data types as "unique identifier".
In your case I would directly use void * as "unique identifier". If this is not possible I would use some 64-bit integer data type as "Stuart" already suggested in his answer.
I was trying some basic c questions when a query struck me. I tried the following code to resolve it:
#include<stdio.h>
typedef float mytype;
mytype q=1;
mytype *x=&q;
mytype *y=&q;
mytype *z=&q;
mytype *a=&q;
mytype *b=&q;
mytype *arr[5]={x,y,z,a,b};
int main()
{
printf("********************");
//printf("%u\n",sizeof(int*));
printf("%u\n",sizeof(double*));
printf("********************\n");
for(int i=0;i<5;i++)
{
printf("%p\n",arr[i]);
printf("%p\n",arr[i]+1);
printf("***********");
}
}
when i execute it,sizeof float pointer is 8bytes but incrementing it results in an address that is only 4 bytes away.Can anyone please explain why that is so ??
The size of your pointer is 8 bytes on a 64 bit system.The size of what the pointer is referencing to is 4 bytes.
Eg, on 64 bit systems float foo:
sizeof(&foo) is 64 bits
sizeof(foo) is 32 bits
You are running on a 64-bit system. The size of a pointer to a memory address is 8 bytes, but the size of a float is only 4 bytes (as a float is a single precision floating point number).
On a 64-bit system, all pointers are 8 bytes in length to allow memory addresses > 4GB to be addressed.
When you increment the pointer, you increment it by the size of a single float, which is 4 bytes in length, so the pointer is incremented by 4 bytes.
As range of "unsigned int" is equal to range of " int *" or any pointer since both take 4Bytes in 64bit platform. Can pointer in C can be replaced by unsigned int ??
There is no such guarantee for unsigned int. A special type uintptr_t was introduced in C99 to hold a pointer, regardless of the platform. You need to include <stdint.h> header to use this type.
Absolutely not. Pointers may be eight bytes, not four, on a 64-bit platform! You can sometimes get away with casting between long long and a 64-bit pointer, but even that is questionable.
You cant even be sure that int is 4 Bytes in 64Bit arch! as the type limits are absolutly implementation and enviroment defined. The standard only gives a limitation of which value has to have at least which range. Thats all. int could even be 8 Bytes on 64 Bit it could be 10 Bytes, or it could be 13 Bytes or it could be What ever the enviroment wants its size to have. So ofcourse you can replace it. But it could end in invalid alignments or cause data loss.
As each assignement of types of different size can have.
But at least you can assign a pointer value to an int value. But also this is the only conversion from value type to pointer type which is valid by ISO/IEC9899.
Short answer: no.
Slightly longer answer: there's no guarantee that unsigned int will be able to hold a valid pointer value for a given platform (several people have already pointed out that 64-bit platforms will likely have address values that fall outside of the range of unsigned int). This is further complicated by the fact that pointers to different types may have different sizes and representations.
Pointers don't just encode an address value; they also encode a type. This matters for pointer arithmetic and array subscripting. For example, assume the declarations:
char *cp = 0x4000;
int *ip = 0x4000;
float (*dap)[10] = 0x4000;
All three pointers (cp, ip, dap) start out with the same value: 0x4000. However, adding 1 to each pointer will give different results. Assuming 32-bit int and float types, we'd get:
cp + 1 == 0x4001
ip + 1 == 0x4004;
dap + 1 == 0x4028;
Adding 1 to cp gives us the address of the next char object (0x4001), adding 1 to ip gives us the address of the next int object (0x4004), and adding 1 to dap gives us the address of the next 10-element array of float object (0x4028). This allows us to use the [] operator on each pointer: we can write cp[i] and ip[i] and get the result we expect (the i'th element following the pointer). If you typed all those pointers as unsigned int, however, you wouldn't be able to use the subscript operator, and adding 1 to them would only give you the next byte address, not necessarily the address of the next object.
What Is the difference between how the char datatype is stored or represented in 32bit vs 64bit in C?
There is no difference.
One char occupies one byte.
One byte has CHAR_BIT bits.
#include <limits.h>
#include <stdio.h>
int main(void) {
printf("a char occupies 1 byte of %d bits.\n", CHAR_BIT);
return 0;
}
One possible difference is that chars might be aligned on 64bit rather than 32bit boundaries.
struct {
char a;
char b;
}
Might take up 2 * 4 bytes on 32bit and 2 * 8 bytes on 64bit.
edit -actually it wouldn't. Any sane complier would repack a struct with only chars on byte boundary. However if you added a 'long c;' in the end anything could happen. That's why a) you have sizeof() and b) you should be careful doing manual pointer stuff in c.