why incrementing a float has different results than expected ?? - c

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.

Related

how is the size of every pointer variable being 8 bytes on a 64-bit machine justified?

I went through pointer arithmetic and the fact that you can't assign pointer of one data type to another data type. for example, below declaration is incorrect.
double x = 10;
int *ptrInt = &x;
We've assigned the address of double variable to a "pointer to integer". Double takes 8 bytes as compared to an integer, that takes 4 bytes and therefore an integer pointer will truncate those extra 4 bytes.
But how come, the size of any pointer variable is 8 bytes and that also means it will not truncate those extra 4 bytes and should work correctly(even though it doesn't).
I have this doubt. Can anybody help me with the clarification?
how come, the size of any pointer variable is 8 bytes ? pointer variable contains address & size of address is 8 byte on 64-bit system irrespective of whether pointer variable points to int or char or float objects as 64-bit pointer supports 8 byte address space.

Size of Next pointer in linked list?

Hello All given a node of linked list as,
struct node
{
int data;
struct node* next;
};
Consider int with 4 bytes.What will be the size of pointer next?
And also i have the following ,
void * ptr;
printf("%d",sizeof(ptr));
Size of pointer is 8 bytes.
I am getting the sizeof(struct node) as 12,how is the size of next pointer's size in the given struct node is 12.Please help me to understand.
Thank You in advance.
On typical systems, the size of a pointer is independent of the size of the data it points to. On a 32-bit system, pointers are 32 bits (4 bytes), and on a 64-bit system, pointers are 64 bits (8 bytes).
Your structure is 12 bytes presumably because it holds a 4-byte int and an 8-byte pointer. However, this is platform-specific and can vary. Many systems require values to be aligned to a whole multiple of their size — that is, a 64-bit pointer must begin at an address that's a multiple of 8 bytes. Compilers will insert padding between structure members to meet alignment requirements.
On my x86-64 Linux system, the size of your structure is 16 bytes: 4 bytes for the int, 4 bytes of padding to reach an 8-byte boundary, and 8 bytes for the pointer.
sizeof(pointer) is a constant regardless of the plain old data type it points to on most common, modern systems. Since you did:
sizeof(ptr)
and got 8 bytes i would hazard a guess that you are on a 64bit system. This indicates to me that your sizeof(struct node) will be 12 bytes because you have the following:
struct node {
int data; // 4 Bytes (32 bit, a common size for `int`s)
struct node* next; // 8 Bytes, as are all pointers on your system
}; // total size of 12 bytes.
What will be the size of pointer next?
The size is sizeof(struct node*)
Code should not be written to depend on a particular result.
The result could be 4 or 8, or 1 or 16 or others.
Writing portable C code relies on not know precisely the answer other than is is of some sane range like 1 to 64.
OP has not mentioned the reason for needing to know value of the size of sizeof(ptr), but the answer is simply the size of a pointer is sizeof(ptr). Code should use sizeof(ptr) rather than a magic number like 4 or 8.
To print the size of a pointer, use
some_type* ptr;
// printf("%d",sizeof(ptr));
printf("%zu",sizeof(ptr));
z Specifies that a following d, i, o, u, x, or X conversion specifier applies to a size_t C11dr §7.21.6.1 7
The size of a pointer like int *, const int *, void *, int (*)() may differ. Portable code does not assume all pointers to various types are of the same size.
Size of a pointer is the number of bytes needed to store the address:
printf("%zu",sizeof(ptr));
printf("%zu",sizeof(struct node *));
printf("%zu",sizeof &abc);
Each of the above should return 8 on a machine with 64-bit addresses and 4 on a machine with 32-bit addresses.
Size of a node can be obtained by dereferencing the pointer:
struct node abc;
void *ptr = &abc;
printf("%zu",sizeof(*((struct node *)ptr)));
The above should return 12 on a machine with 64-bit addresses, as mentioned above.

How does alignment work with pointers to zero-sized arrays?

I was investigating some code I saw that deals with 0-size arrays. Specifically, they are used in the case of dynamically allocated size of a struct such as in https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
Specifically, this is the code in Callgrind:
struct _EventGroup {
int size;
const char* name[0];
};
I was playing around with this, using gcc 4.1.2 on a 64-bit Red Hat, and noticed that the sizeof function returns a size of 8 bytes for the entire struct _EventGroup when the name field is a pointer. Now if I change it to:
struct _EventGroup {
int size;
const char name[0];
};
I get 4 bytes because gcc identifies the 0-size array as taking up no space, and the int as taking up 4 bytes. That makes sense. If I then change it to:
struct _EventGroup {
int size;
const char* name;
};
sizeof returns 16 bytes because the char* takes up 8 bytes in a 64 bit system, and the int has to get padded to 8 bytes. This makes sense. Now, if I do one last change:
struct _EventGroup {
const char* name[0];
};
I get 0 bytes because gcc is detecting my zero-size array. What I want clarified is what's happening in the first case I presented. How much space is gcc allocating for a pointer to a zero size array and why? I'm asking because this code seems designed to be efficient with memory allocation, however it would make sense that gcc either gives the pointer a size of 0 bytes if it detects it points to essentially nothing, or 8 bytes if it is being treated as a normal pointer. Alignment would dictate that I get either 4 bytes or 16 bytes with my original struct. Why am I getting 8 bytes?
Gcc is adding the right amount of padding such that if you actually allocate extra space for the array, the pointer &(eventGroup->name) will be properly aligned.
It seems you're on a platform that has 4-byte ints and 8-byte pointers, so this means you have:
bytes 0-3 -- the int
bytes 4-7 -- padding
bytes 8-15 -- where the first (char *) would be stored, 8-byte aligned
Since it's actually an array of zero size, you don't actually have that first char *, but you do have the padding. Hence, the struct has size 8.
In your second example, there is no alignment requirement for a one-byte char, so you have:
bytes 0-3 -- the int
byte 4 -- where the first (char) would be stored, "1-byte aligned"
Again, no actual char in the struct, so it has size 4.

How are values stored in memory?

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)

Size of type and memory allocation [duplicate]

This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Closed 9 years ago.
I've got a trouble with dynamic memory allocation.
Somehow, actual size of my struct (sum of all the parts) is less than size of the type itself. Here is the code:
#include <stdio.h>
#include <malloc.h>
struct Lol {
int a;
char b;
char s[20];
};
void main() {
Lol* lol = (Lol*)malloc(sizeof(Lol));
printf("Type size: %d bytes\n", sizeof(Lol));
printf("Actual struct size: %d bytes\n", sizeof(lol -> a) + sizeof(lol -> b) + sizeof(lol -> s));
}
in this case struct size should be 25 bytes (4 bytes for int, 1 byte for char and 20 bytes for char array), but sizeof(Lol) shows me 28 for some reason as is char type would be treated as int type. What's up with this all? Does this mean i lose 3 bytes on nothing?
actual size of my struct (sum of all the parts) is less than size of the type itself"
Because many computer operations are faster when the values they work on are aligned at certain memory boundaries, the C language standard allows implementations to do such alignment. On most systems, ints will be aligned on 4- or 8- byte boundaries, depending on the size of the int. The size of a struct must be aligned so that the address of the next struct in an array will be properly aligned, so a struct starting with an int aligned to a 4 byte boundary must have a size that is a multiple of 4.
Does this mean i lose 3 bytes on nothing?
Yes. (Well, it's not exactly nothing ... your program will generally be faster because of it.) With modern machines supporting up to 2 terabytes of RAM, this is less of a concern than it once was.

Resources