Using calloc() to create dynamic struct utmp array [duplicate] - c

char c[] = {'a','b','c'};
int* p = &c[0];
printf("%i\n", sizeof(*p)); //Prints out 4
printf("%i\n", sizeof(*c)); //Prints out 1
I am extremely confused about this section of code. Both p and c represent the address of the array c at the 0th index. But why does sizeof(*p) print out 4? Shouldn't it be 1?

Because p is of type int *, so *p is of type int, which is apparently 4 bytes wide on your implementation.
And use %zu for printing size_t (what sizeof yields) if you don't want your program to invoke undefined behavior.

sizeof(*p) is the size of the int object to which p points.

sizeof(*p) will print size of p which is 4 because of int but c is of char that's why it is 1

In C (not C99) the sizeof operator is strictly a compile time calculation. so when sizeof (*p) [a dereferenced ptr to an integer] is evaluated then the size of int is four.
Note. the (*p) portion of that statement is a "cast" operator. So, sizeof is NOT a function call as in sizeof(xyz), rather it is like sizeof var_name or sizeof (int *).
When your program runs it changes the object pointed to by p, but the value of sizeof (*p) was already computed and hard-coded into your executable load module.
I think your confusion is that you were thinking that C would figure out what data type p was pointing to when your program runs.

Related

is sizeof a pointer equal to sizeof a pointer to pointers?

when I got an array of pointers and a pointer why sizeof the array of poninters is equal to the sizeof pointer?
for example:
char *matrixp;
char **m;
printf("%llu", sizeof matrixp);
printf("%llu", sizeof m);
gives back the same output.
is there a way I can get the total size in bytes for example of
char *vet[10]
? (that should be 80).
To answer the question in the title - pointers to different types (including pointer types) do not all have to be the same size. The only requirements are:
char * and void * have the same size and alignment;
Pointers to qualified types have the same size and alignment as pointers to their unqualified equivalents (e.g., sizeof (int *) == sizeof (const int *);
All struct pointer types have the same size and alignment;
All union pointer types have the same size and alignment;
So it's not guaranteed that an int * is the same size as an int ** or
an int (*)[N], but for commodity hardware like x86_64 it tends to be true.
Now, for your specific questions:
First of all, a sizeof expression has type size_t, for which we need to use the %zu conversion specifier in printf. Using %llu on a size_t argument is technically undefined behavior. Rewrite those statements as
printf("%zu", sizeof matrixp);
printf("%zu", sizeof m);
and see if you still get the same output. You shouldn't because you've defined matrixp as a plain char (at least in the code you've posted here), and sizeof (char) is 1 by definition, and I will guarantee no pointer type is only one byte wide (unless you're working on a system that only has 256 addressable memory locations).
Edit
And now someone has changed the types from char and char * to char * and char **, so that paragraph is now wrong. Awesome.
For x86 and x86_64 platforms, all pointer types do have the same size and representation, so if you're running this on Windows or Linux you should get the same output. Just be aware that's not universally true.
End edit
Secondly, sizeof evaluates to the number of bytes in the operand (whether the operand is a type name or expression). sizeof vet will yield the total number of bytes used by the vet array (10 * sizeof (char *)). To get the number of elements (10), you'll have to divide the result of sizeof vet by the size of an individual element, sizeof vet[0] (or sizeof *vet, which evaluates to the same thing).
All pointer have the same size (8 bytes). If you want to get the total size of an array (like char *vet[10]), you have to declare it as an array (with []) and not as a pointer (char **vert). *vert[10] is an array of 10 pointers while **vert is a pointer to the start of an area of memory containing pointers.
For example
#include <stdio.h>
int main(void){
char *chars[] = {"hello", "world", "pointers"}; // declared as an array of strings/pointers
printf("%zu\n", sizeof(chars[0])); // pointer to the start of 'hello' (size is 8)
printf("%zu\n", sizeof(chars[1])); //pointer to start of 'world' (still 8 bytes)
printf("%zu\n", sizeof(chars)); // refers to the whole array (24 bytes)
char **m; // a pointer pointing to the first pointer in m (not an array)
char *n; // another pointer pointing to the first letter in n
n = "pointer";
printf("%zu\n", sizeof(n)); // 8
printf("%zu\n", sizeof(m)); // 8
return 0;
}

Right syntax with malloc : sizeof(*int) or sizeof(int*)

I usually see the syntax for malloc allocation :
int **p = malloc(N*sizeof(int*))
with p being a pointer. I have also seen the following syntax (maybe my sources are not right) :
int **p = malloc(N*sizeof(*int))
The difference between 2 syntax above is that "star" * appears after the type int for the first and before for the second one.
Could you tell me the right syntax between the two above?
The second one can be used only with an expression as the operand of the sizeof operator (and *int is not an expression, it's a syntax error).
You probably have seen it in code that uses the canonical way to allocate a dynamic array of N members of an arbitrary type:
p = malloc (N * sizeof *p);
I deliberately do not show the declaration of the pointer type p, since it is not needed. Even if the type of p changes, you never need to touch this allocation line. It always does the right thing.
C grammar sizeof quirk: with an expression operand, the parentheses are optional. They are required when the operand is a type.
None of the above is right for enough amount of memory. Below is correct:
int *p = malloc(N * sizeof(int));
or
int **p = malloc(N * sizeof(int *));
In the first one, you allocate memory for integers and you return it as pointer. The second is allocating array of pointers so you need * character in sizeof keyword.
But for messing in future of sizes, if you change int *p to let's say char *p, it is better to use this syntax:
int *p = malloc(N * sizeof(*p));
TL;DR The first one, partially (considering you have the terminating ; in your actual code).
Probably a better Correct way to write it will be
int *p = malloc(N*sizeof(*p)); // need memory for "int" type, not pointer to int
which removes the hard-coded dependency on the data type.
FWIW, the second one,
int *p = malloc(N*sizeof(*int))
is an erroneous statement, syntactical error.
And, to nitpick, it's not a "star", it's called a dereference operator.

What exactly int/char when we declare double pointer(**q)

Lets take 64 bit machine
where pointer is of 8 bytes in 64 bit machine
int *p ; // it is a pointer to integer variable so when i increment p
// i.e., p++ it will increment by 4
char *r; // It is pointer to character .
// So if i increment 'r' it will increment by 1
int **q ; // if i increment q ie.,q++ it will increment 8 bytes
i tried this peace of code if any thing wrong please correct me
int a=10;
int *p;
char *r;
int **q;
p=&a;
q=&p;
printf("p= %p\t r= %p\t q=%p\n",p,r,q);
printf("p(increment)= %p\t r (increment)= %p\tq (increment)= %p ",++p,++r,++q);
output
p= 0x7fff669bb1bc r= 0x7fff669bb2a0 q=0x7fff669bb1a0
p(increment)= 0x7fff669bb1c0 r (increment)= 0x7fff669bb2a1 q (increment)= 0x7fff669bb1a8
what is role of int/char/float in double pointer?
To quote the property of the postfix ++ operator, from C11, chapter ยง6.5.2.4, Postfix increment and decrement operators, (emphasis mine)
The result of the postfix ++ operator is the value of the operand. As a side effect, the
value of the operand object is incremented (that is, the value 1 of the appropriate type is
added to it). [...]
In case of int *p ;, p is a pointer to type int, hence the increment will be based on sizeof(int)
In case of int **p ;, p is a pointer to type int *, hence the increment will be based on sizeof(int *)
Well, this depend not only on your machine, but also on your implementation. You can figure them out by outputting sizeof p, sizeof r, and sizeof q. Printing sizeof (int *), sizeof (char *), and sizeof (int **) works too.
C programmers traditionally like to know a lot (perhaps more than they
need to) about the underlying machine implementation.
From my perspective, you don't need to know these stuffs, because the compiler will handle this for us (according to the C standard) quite well. Also, most practices making use of these stuffs are essentially undefined behaviors.
In int **p you increment the pointer by the size it points to (i.e. pointer). As the size of pointer is 8, it will increment by 8.
The final type has no role here. It will behave the same like the pointer to pointer to void.

Why can't I memcpy an int to a char[] without getting the address of the int?

This might be a duplicate, but I haven't found any other question dealing with my exact situation (yet).
Here's what I'm trying to do:
int n = 12;
char s[sizeof(n)];
memcpy(s, (char *)n, sizeof(n));
printf("%d", s);
Basically, I want to copy n into s without having to get the address of n. When I run this, it gives me a segmentation fault. This, however, works:
printf("%d", (char *)n);
So I know that the problem is in the memcpy call. Why can't I memcpy an int into a char[] like this?
You get a segmentation fault because what you're trying to do is not what your code states.
int n = 12;
char s[sizeof(n)];
memcpy(s, (char *)n, sizeof(n));
You wanted to say:
"copy the sizeof(int) bytes representing the value of n into s".
But memcpy() is about copying memory objects, not values. An object resides at a given address, and contains a given value. Taking n gives the value, taking &n gives the address.
And the construct (char *)n tells the compiler to interpret the value of n as the address of a char, so what you are saying is:
"copy the sizeof(int) bytes at the address contained in n into s."
Since n = 12, you are reading from address 0x00000012... which is most likely not a legal address to read from (hence the segfault).
By taking the address of n before casting that (instead of the value) into char *, your statement matches your intent:
int n = 12;
char s[sizeof(n)];
memcpy(s, (char *)&n, sizeof(n));
"copy the sizeof(int) bytes at the address of n into s".
You don't need to take the address of s since the name of an array in this context evaluates to the address of the first element. Since the integer n is not an array, that doesn't apply, which is why you must take the address.
Of course you can use an int array too, to get around this, but it's extremely silly and a very bad idea in general:
int n[1];
char s[sizeof n];
memcpy(s, n, sizeof n);
This works because n now evaluates to &n[0], i.e. the address of the first (and only!) element in the array.
Note that sizeof is not a function, it does not need parentheses for this usage.

Why does my homespun sizeof operator need a char* cast?

Below is the program to find the size of a structure without using sizeof operator:
struct MyStruct
{
int i;
int j;
};
int main()
{
struct MyStruct *p=0;
int size = ((char*)(p+1))-((char*)p);
printf("\nSIZE : [%d]\nSIZE : [%d]\n", size);
return 0;
}
Why is typecasting to char * required?
If I don't use the char* pointer, the output is 1 - why?
Because pointer arithmetic works in units of the type pointed to. For example:
int* p_num = malloc(10 * sizeof(int));
int* p_num2 = p_num + 5;
Here, p_num2 does not point five bytes beyond p_num, it points five integers beyond p_num. If on your machine an integer is four bytes wide, the address stored in p_num2 will be twenty bytes beyond that stored in p_num. The reason for this is mainly so that pointers can be indexed like arrays. p_num[5] is exactly equivalent to *(p_num + 5), so it wouldn't make sense for pointer arithmetic to always work in bytes, otherwise p_num[5] would give you some data that started in the middle of the second integer, rather than giving you the sixth integer as you would expect.
In order to move a specific number of bytes beyond a pointer, you need to cast the pointer to point to a type that is guaranteed to be exactly 1 byte wide (a char).
Also, you have an error here:
printf("\nSIZE : [%d]\nSIZE : [%d]\n", size);
You have two format specifiers but only one argument after the format string.
If I don't use the char* pointer, the output is 1 - WHY?
Because operator- obeys the same pointer arithmetic rules that operator+ does. You incremented the sizeof(MyStruct) when you added one to the pointer, but without the cast you are dividing the byte difference by sizeof(MyStruct) in the operator- for pointers.
Why not use the built in sizeof() operator?
Because you want the size of your struct in bytes. And pointer arithmetics implicitly uses type sizes.
int* p;
p + 5; // this is implicitly p + 5 * sizeof(int)
By casting to char* you circumvent this behavior.
Pointer arithmetic is defined in terms of the size of the type of the pointer. This is what allows (for example) the equivalence between pointer arithmetic and array subscripting -- *(ptr+n) is equivalent to ptr[n]. When you subtract two pointers, you get the difference as the number of items they're pointing at. The cast to pointer to char means that it tells you the number of chars between those addresses. Since C makes char and byte essentially equivalent (i.e. a byte is the storage necessary for one char) that's also the number of bytes occupied by the first item.

Resources