Whenever I want to read or write into a binary file using C, I do use the fread() and fwrite() functions. They need as a parameter the bytes of the datum that is being read or written so I use the sizeof() function. Now the question is:
The books says that I should declare a function like this:
fread(&variable,sizeof(TYPE_OF_VAR),quantity,file);
I've use the following statement which works most of the time but not always:
fread(&variable,sizeof(VARIABLE),quantity,file);
Why does it works sometimes but sometimes it doesn't?
Does it depends on the type of the variable (int, char, etc)?
Does it depends on the quantity of the datum that I use?
The thing to keep in mind is that sizeof is based on what the compiler knows about the type at compile time (ignoring VLA's for now). If you give it a variable, it will use the type of that variable.
So, the only time I can think of where it wouldn't work as you expect is with pointers.
basically what it boils down to is this:
int x[5];
int *y = &x[0];
int *p = malloc(sizeof(int) * 5);
sizeof(x); // == sizeof(int) * 5
sizeof(y); // == sizeof(int *)
sizeof(p); // == sizeof(int *)
This gets tricky when dealing with functions because arrays decay to pointers when passed to a function. Also note that all 3 of these are exactly equivalent:
int func(int *p);
int func(int p[5]);
int func(int p[]);
in all 3, p is a pointer, not an array.
See this Stack Overflow question for a discussion of heap vs. stack: What and where are the stack and heap.
sizeof() on heap elements, like pointers, will return the size of the pointer, not the number of elements that the pointer can store.
However, sizeof() on stack elements: arrays or const char * will return the length of the array or string.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LENGTH 100
int main(int argc, char *argv[])
{
char *a = NULL;
char b[10] = "abcdefghi";
printf("sizeof(b): %zu\n", sizeof(b));
a = malloc(LENGTH + 1);
if (a) {
*(a + LENGTH) = '\0';
memset(a, ' ', LENGTH);
fprintf(stdout, "a (before memcpy):\t[%s]\n", a);
printf("sizeof(a), before: %zu\n", sizeof(a));
memcpy(a, b, sizeof(b) - 1);
fprintf(stdout, "a (after memcpy):\t[%s]\n", a);
printf("sizeof(a), after: %zu\n", sizeof(a));
free(a);
}
return EXIT_SUCCESS;
}
To compile:
$ gcc -Wall sizeofTest.c -o sizeofTest
Output:
$ ./sizeofTest
sizeof(b): 10
a (before memcpy): [ ]
sizeof(a), before: 8
a (after memcpy): [abcdefghi ]
sizeof(a), after: 8
On my platform, a char * points to a memory address that takes up eight bytes.
It will always work.
int main()
{
char a[10];
int b[10];
printf("%d %d %d %d %d %d",sizeof(char),sizeof(int), sizeof(a),sizeof(b), sizeof(a[0]), sizeof(b[0]) );
}
Try the above code. You should see (depending on compiler, mine has char as 1byte and integer as 4 bytes) 1,4,10,40,1,4
It is not different for fread or fwrite or wherever you use it.
Related
why value a and x is different? I think it should be the same
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int a =5;
int *x=&a;
printf("%ld\n", sizeof(a)); // print 4
printf("%ld\n", sizeof(x)); // print 8
return(0);
}
I am not sure whether you are aware of what you are actually measuring with the sizeof operator.
First you measure integer a, which is the size of an int (4 bytes).
And second you measure not an integer but a pointer which stores the address of integer a, so the value is different and I think the value of x is 8 bytes.
int a (4 bytes INTEGER)
int *x = &a (is address of a)
But I can be wrong.
why value a and x is different? I think it should be the same
a is an int and x is a pointer.
int a = 5;
int *x = &a;
C does not specifier an int and a pointer need to be the same size. They may have the same size. Commonly a pointer is as wide as an int or wider, yet either one may be wider than the other.
It is implementation defined.
Since C99, use "%zu" to print a size_t, which is the resultant type from sizeof.
// printf("%ld\n", sizeof(a));
printf("%zu\n", sizeof(a));
// or
printf("%zu\n", sizeof a); // () not needed about objects.
#include <stdio.h>
#include <stdlib.h>
int constChars(const char* str) {
int size = sizeof(str)/sizeof(char);
printf("Size is %d.\n", size);
int i = 0;
for (i=0;i<size;i++)
printf("%c ", str[i]);
return 0;
}
int main(void) {
char a[10]={'b','c','d','e','f','f','f','f','f','f'};
constChars(a);
return 0;
}
I wrote piece of code like above, but the output result is:
Size is 8.
b c d e f f f f
I'm quite confused, why the sizeof() function gives a size of 8?
I use gcc and freebsd.
When you pass an array to a function, it gets rewritten as a pointer, where sizeof information is lost. If you did this in main instead, i.e:
char a[10]={'b','c','d','e','f','f','f','f','f','f'};
int size = sizeof(a)/sizeof(a[0]);
printf("Size is %d.\n", size);
It prints 10 as expected. But once you pass it to constChars, it prints the size of a pointer.
Str is a pointer to a char. That is typically 4 to 8 bytes. You are not getting the size of the array, but the size of the variable. The only way to know the length of the array is to pass the size in with it, or you could deliminate the array with some sort of signal value (like \0) and do some iteration.
I have a pointer A, which is passed into a function with address, say myfunc(&A).
In the function myfunc(char **A) {
I want to copy memory from A[2 to n] to C[2 to n] }
I tried memcpy(&c[2], &(*A)[2], 20);
I am getting the address copied into c rather than the actual info in A.
To copy memory from A[2 to n] to C[2 to n] (from question)
A is a char **, it points to a number of char *.
The 3rd char * is A[2]. You want to use the address of that element in memcpy.
So the line should be
memcpy(&c[2], &A[2], N);
where N is, according to your text, (n-2+1)*sizeof(char *). memcpy size argument ignores the type of what it copies, therefore the total size of what to be copied is to be provided. You want to copy from 2 to n, that makes n-2+1 elements. Each element is a char * which size is sizeof(char *).
-- following comment --
While not clear from the question, if you want to dereference A twice, you copy characters... like
memcpy(&c[2], &A[0][2], 20 /* 20 chars */);
C would be a char *.
memcpy(c+2, *A+2, 20) should be enough.
Here is a test program:
#include <stdio.h>
#include <string.h>
char c[10] = { 'a', 'b' };
void myfunc(char **A)
{
memcpy(c+2, *A+2, 8);
}
int
main(void)
{
char *A = "ABCDEFIJK";
printf("Before: %s\n", c);
myfunc(&A);
printf("After : %s\n", c);
return 0;
}
Run:
$ ./a.out
Before: ab
After : abCDEFIJK
This question already has answers here:
Stack pointer difference for char pointer and array
(1 answer)
C pointers and arrays/ 'sizeof' operator [duplicate]
(2 answers)
Closed 9 years ago.
Hi i was doing this exercise and wanted to get the size of array after i pass the pointer to the array to the function:
But the sizeof() operator doesn't work on pointer but works on the array name. Why is it so?
Is this any way i could get the size of the array on the findPut function?
#include <stdio.h>
//global vars
int i,j;
//functions prototypes
void findPut(int *, int);
int main(void){
int ins=4;
int arr[10]={1,2,3,5,6,7,8};
printf("%d\n",sizeof(arr)); //gives 40
int *ap=arr;
printf("%d\n",sizeof(*ap)); //gives 4 instead of 40 why?? if ap and arr the same thing
findPut(ap, ins);
return 0;
}
//functions
void findPut(int *p, int n){
//vars
//getting size of array
int size= sizeof(*p);
//sizeof(int);
printf("%d\n",size); //gives 4 but expected 40????
}
When you dereference *p you get an int, so it returns 4 (which is the size of int on your platform).
Because, sizeof(*ap) means sizeof(arr[0]); since array is of type int, sizeof(int), since in your system configuration, int is of size 4 you got the result as 4.
You can try it your self by printing the value of *p, you will get the value of arr[0].
Let int *p be a pointer and int arr[10]
Please note that:
Arrays and Pointers are not equivalent.
sizeof operator is a compile time operator.
sizeof(arr), evaluates to 10*sizeof(int), that is 10*4=40 in your case.
When you dereference p (getting the value that p points to), it doesn't give you whole array, but one unit of
your array that is an int so, *p means arr[0]. sizeof(arr[0]) is
4 (in your case) that's obvious.
When you use sizeof(p), it will give you the size of the pointer in your machine.
In my machine it is 8.
main function's return type should be int always. It has to retport operating system the exit status of the program. If you use void it might return random garbage.
The example demonstrate the issue:
#include<stdio.h>
#include<stdlib.h>
int main(){
int *p=NULL;
int arr[10]={10,1,2,3,5,6,7,8,9,10};
p=arr;
printf("values: arr[0]=%d *p= %d\n\n",arr[0],*p);
printf("sizes : sizeof(arr[0])=%lu, sizeof(*p)= %lu sizeof(int)=%lu\n\n",sizeof(arr[0]),sizeof(*p),sizeof(int));
printf("Sizeof pointer p: %lu \n\n",sizeof(p));
printf("Sizeof arr: %lu \n\n",sizeof(arr));
printf("Pointing p to the first byte of 100 byte sequence\n\n");
p=malloc(100);
printf("Though p is pointing 100 byte block, sizeof(p)=%lu",sizeof(p));
return 0;
}
Essentially, sizeof evaluates the sizeof type but not the sizeof type it points to.
Thank you, i do appreciate your knowledge but is there any way i could
find the size of array inside another function( not the one where i
define the array).
You can't in my IMHO! You have to pass the size along with the array.
Example:
int main(){
int arr[10]={10,1,2,3,4,5};
printf("Length of array: %lu",findLength(arr,sizeof(arr)));
return 0;
}
size_t findLength(int *p,int size){
return size/sizeof(*p);
}
You have an int array and an int pointer:
int arr[10] = {1,2,3,5,6,7,8};
int* ap;
ap = arr;
In C, the expression arr is equivalent to &arr[0]. It stands to reason, then, that *ap is equivalent to arr[0], which is an int, which for your binary has a size of 4.
You also need to understand that arrays and pointers aren't the same thing. You may have been confused by the fact that arrays and pointers are often used interchangeably in the sense that a pointer can store the address of the beginning of an array (its first element, in other words) and navigate the consecutive addresses as if it had the actual array passed to it.
I thought that if a c pointer pointing to a char array was incremented then it would point to the next element in that array. But when I tried this I found that I had to increment it twice. Trying the increment using sizeof(char) I found that adding the size of a char was too much so it had to be divided by two.
#include <stdio.h>
int main(int argc, char * argv[]){
char *pi;
int i;
pi = argv[1];
printf("%d args.\n",argc-1);
printf("input: ");
for(i=0;i<argc-1;i++){
printf("%c, ",*pi);
/*The line below increments pi by 1 char worth of bytes */
//pi+=sizeof(pi)/2;
/* An alternative to the above line is putting pi++ twice - why? */
pi++;
pi++;
}
printf("\n");
return 0;
}
Am I doing something wrong? or am I misunderstanding the method of incrementing pointers?
sizeof(char) is guaranteed to be 1, but sizeof(char*) isn't.
Nevertheless, your function only works by accident.
For example, try calling it with the following parameters:
abc defg
This will yield:
2 args.
input: a, c,
which is plain wrong. The problem is you are incrementing a pointer to the element 1 of argv instead of a pointer to argv.
Try this:
#include <stdio.h>
int main(int argc, char * argv[]){
char **pi;
int i;
pi = argv + 1;
printf("%d args.\n",argc-1);
printf("input: ");
for(i=0;i<argc-1;i++){
printf("%c, ",**pi);
pi++;
}
printf("\n");
return 0;
}
This will print the first character of every argument:
2 args.
input: a, d,
If you have a pointer ptr of type T* and you add N, then the pointer will be advanced by N * sizeof (*ptr) or equivalent N * sizeof (T) bytes. You simply forgot to dereference pi. So what you got with sizeof (pi) was the sizeof of the char*, but not the sizeof of a char. Your line was equivalent to pi+=sizeof(char*)/2; Pointers on your platform are 4 bytes big. Thus in effect you did pi+=2;. Write pi+=2 if you want to increment 2 times. Note that char has an sizeof of 1 by definition. You don't need to do sizeof (char), it is always 1.
sizeof(pi) is returning the size of (char*), which is the type of pi (a pointer, probably two, four, or eight bytes). sizeof(char) will return 1.
However, another thing to understand is that whenever you increment a pointer by a number (e.g.: pi += sizeof(char); pi++; etc.) you are incrementing the pointer by the base size anyways. So:
int *ipointer = &int_array[0];
ipointer += 2;
will actually increment ipointer by 2 times sizeof int.
Another thing you seem to be doing wrong is pointing pi at the first argument, and then looping through all the arguments. If you want to loop through the arguments, try something like this:
for (i = 1; i < argc; i++) {
pi = argv[i];
// ... do something with pi
}