It may be silly question but still am not getting it.
I do have a char array say
char arr[100] having some data
char arry[100] ---- some data;
int test;
memcpy(&test,array+4,sizeof(int))
What does this memcpy will do
Thanks
SKP
This might be useful in so-called serialization of data.
Say, if someone saved an integer into a file.
Then you read the file into a buffer (arry in your case) as a stream of bytes. Now you want to convert these bytes into real data, e.g. in your case integer test which has been stored with offset 4.
There are several ways to do that. One is to use memcpy to copy bytes into area where compiler would treat them as an integer.
So to answer your question:
memcpy(&test,array+4,sizeof(int))
...will copy sizeof(int) number of bytes, starting from 4-rth byte from array into memory allocated for variable test (which has type int). Now test has the integer value which was saved into arry originally, probably using the following code:
memcpy(array+4, &original_int, sizeof(int))
Doing this requires some knowledge of hardware and the language. As there are many complications, among which:
byte order in integers.;
data alignment;
It just copy the element array[4] to variable test. On 32-bit machine sizeof(int) = 4. memcpy will copy 4 bytes to the address &test which can hold 4 bytes.
This will copy probably 4 bytes (depending on your machine and compiler--your int might be bigger or smaller) from the 4th through 7th bytes of arry into the integer test.
According to the documentation of memcpy() :
void * memcpy ( void * destination, const void * source, size_t num );
Copies the values of num bytes from the location pointed by source directly to the memory block pointed by destination.
In your case :
num=sizeof(int)
destination=&test A pointer to test
source=&array[4] A pointer to the fourth element of the array of char array
Hence, if sizeof(int)==4 it will copy array[4], array[5],array[6] and array[7] to test
There are questions that can help you understand the memory layout of integers :
int32 storage in memory
How is an integer stored in memory?
There is also an issue with endianless : on my computer, array[4] corresponds to the least significant byte.
Consequently, if array[7]=0x80 and array4]=array[5]=array[6]=0x00 then test will contain 00000080 and test will worth -2^31.
if array[7]=0x2A and array[5]=array[6]=array[4]=0x00 then test will contain 2A000000 and test will worth 42 (that is 0x0000002A).
Here is a test code to be compiled by gcc main.c -o main
#include <stdio.h>
#include <string.h>
int main(int argc,char *argv[]){
char array[100];
int test;
printf("sizeof(int) is %ld\n",sizeof(int));
array[4]=0x00;
array[5]=0;
array[6]=0;
array[7]=0x80;
memcpy(&test,&array[4],sizeof(int));
printf("test worth %d or(hexa) %x\n",test,test);
array[4]=0x2A;
array[5]=0;
array[6]=0;
array[7]=0x00;
memcpy(&test,&array[4],sizeof(int));
printf("test worth %d or(hexa) %x\n",test,test);
return 0;
}
Generally the C library function void *memcpy(void *str1,const void *str2,size_t n) copies n characters from memory area str2 to memory area str1, where:
str1 – this is pointer to the destination array where the content is to be copied, type-casted to a pointer of type void*
str2 -- this is pointer to source of data to be copied, type-casted to a pointer of type void*
n -- this is the number of bytes to be copied
memcpy returns a pointer to destination, which is str1
In your case, is copied the contents of the array, from the address pointed to by array[4] up to sizeof (int) bytes (4 bytes in this case, if you have a 32bit machine), the address pointed to by test
Related
Hello I am a beginner in C and I was working with structures when i have this problem:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char nom[20];
char prenom[20];
int note;
} Etu;
int main() {
Etu E[5];
E[0].nom = "reda";
printf("%s", E[0].nom);
return 0;
}
With this one I have this error (error: assignment to expression with array type). So I decided to do it using pointers and it actually working this is the code I used:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char *nom;
char *prenom;
int note;
} Etu;
int main() {
Etu E[5];
E[0].nom = "reda";
printf("%s", E[0].nom);
return 0;
}
So the question is what is the difference between both of them since strings are pointers.
thank you ..
Strings are not pointers, they are sequences of characters terminated with a null byte. These sequences are stored in arrays, which are not pointers either, but objects that live in memory and to which a pointer can point. A pointer is a variable that contains the address of an object in memory.
In the first example, you try and store a string into an array with =. C does not support this type of assignment and complains with an explicit error message. You can copy the string into the array with strcpy, assuming the destination array is large enough to store the bytes of the string, including the null terminator. "reda" uses 5 bytes, so it is OK to copy it into E[0].nom:
#include <stdio.h>
#include <string.h>
typedef struct {
char nom[20];
char prenom[20];
int note;
} Etu;
int main() {
Etu E[5];
strcpy(E[0].nom, "reda");
printf("%s\n", E[0].nom);
return 0;
}
The second example uses a different approach: nom is now defined as a pointer to char. Defining the array E in main leaves it uninitialized, so you can only read from the pointers after you set their value to point to actual arrays of char somewhere in memory. E[0].nom = "reda"; does just that: set the address of the string literal "reda" into the member nom of E[0]. The string literal will be placed by the compiler into an array of its own, including a null terminator, and that must not be changed by the program.
First part, you try to copy two array of character (string is not a pointer, it is array of character that is terminated by null character \0).
If you want to copy value of an array to another, you can use memcpy, but for string, you can also use strcpy.
E[0].nom = "reda";
change to:
strcpy(E[0].nom,"reda");
Second part, you make the pointer point to string literal. The pointer points to first character of the string (r in this case).
You can see How to copy a string using a pointer
And Assigning strings to pointer in C Language
It is a lower-level concept actually.
If we say char nom[20] than its memory location will be decided at compile time and it will use stack memory (see the difference between stack memory and heap memory to gain more grasp on lover level programming). so we need to use it with indexes.
such as,
nom[0] = 'a';
nom[1] = 'b'; // and so on.
On the other hand if we create a string using the double quotes method (or the second way in which you used pointers). The double quoted strings are identified as const char* by the compiler and the string is placed at the heap memory rather than the stack memory. moreover their memory location is not decided at compile time.
a very efficient way of testing the difference between these two types of strings is that when you use sizeof() with char[20] nom it will return 20 * sizeof(char) which evaluates to 20 without any doubt. it clearly states that whether you use only 5 characters or 2 characters it will always occupy space of 20 charaters (in stack memory)
but in case of const char* if you use sizeof operator on this variable than it will return the size of the pointer variable which depends on the hardware (32bit will have 4bytes pointer) and (64bit will have 8bytes pointer). So, the sizeof operator do not shows how many characters are stored in the pointer. it just shows the size of pointer. but the benefit of using const char* is that only take memory that is required if 4 characters are stored than it will consume 5 byte memory (last byte is additionally added in case of strings) and in case of 8 characters it will consume 9 bytes and so on but note that the characters will be stored in heap(memory)
pointer --------------------> "characters"
(on stack) (heap)
What you have been doing in the first problem is that you were assigning a string that is only stored on heap to a data types that is only stored on stack. it is not the matter of string. it the matter of memory model
I hope you might have understood. I not i can elaborate more in comments.
an additional information. Stack Memory is faster compared to the Heap Memory.
How can I justify the output of the below C program?
#include <stdio.h>
char *c[] = {"Mahesh", "Ganesh", "999", "333"};
char *a;
char **cp[] = {c+3, c+2, c+1, c};
char ***cpp = cp;
int main(void) {
printf("%d %d %d %d ",sizeof(a),sizeof(c),sizeof(cp),sizeof(cpp));
return 0;
}
Prints
4 16 16 4
Why?
Here is the ideone link if you want to fiddle with it.
char *c[] = {"Mahesh", "Ganesh", "999", "333"};
c is an array of char* pointers. The initializer gives it a length of 4 elements, so it's of type char *[4]. The size of that type, and therefore of c, is 4 * sizeof (char*).
char *a;
a is a pointer of type char*.
char **cp[] = {c+3, c+2, c+1, c};
cp is an array of char** pointers. The initializer has 4 elements, so it's of type char **[4]. It size is 4 * sizeof (char**).
char ***cpp = cp;
cpp is a pointer to pointer to pointer to char, or char***. Its size is sizeof (char***).
Your code uses %d to print the size values. This is incorrect -- but it happens to work on your system. Probably int and size_t are the same size. To print a size_t value correctly, use %zu -- or, if the value isn't very large, you can cast it to int and use %d. (The %zu format was introduced in C99; there might still be some implementations that don't support it.)
The particular sizes you get:
sizeof a == 4
sizeof c == 16
sizeof cp == 16
sizeof cpp == 4
are specific to your system. Apparently your system uses 4-byte pointers. Other systems may have pointers of different sizes; 8 bytes is common. Almost all systems use the same size for all pointer types, but that's not guaranteed; it's possible, for example, for char* to be larger than char***. (Some systems might require more information to specify a byte location in memory than a word location.)
(You'll note that I omitted the parentheses on the sizeof expressions. That's legal because sizeof is an operator, not a function; its operand is either an expression (which may or may not be parenthesized) or a type name in parentheses, like sizeof (char*).)
a is an usually pointer, which represents the memory address. On 32-bit operating system, 32bit (4 Byte) unsigned integer is used to represent the address. Therefore, sizeof(a) is 4.
c is an array with 4 element, each element is a pointer, its size is 4*4 = 16
cp is also an array, each element is a pointer (the first *, wich point to another pointer (the second *). The later pointer points to an string in the memory. Therefore its basic element size should represent the size of a pointer. and then sizeof(cp) = 4*4 = 16.
cpp is a pointer's pointer's pointer. It is as well represent the 32bit memory address. therefore its sizeof is also 4.
a is a pointer. cpp is also a pointer just to different type (pointer to pointer to pointer).
Now c is an array. You have 4 elements, each is a pointer so you have 4 * 4 = 16 (it would be different if you would run it on x64).
Similar goes for cp. Try changing type to int and you will see the difference.
So the reason you got 4 16 16 4, is because 'a' is simply a pointer, on its own, which only requires 4 bytes (as a pointer is holding a 32bit address depending on your architecture) and so when you have a **pointer which is == to a *pointer[], your really making an array of pointers, and since you initalized 4 things that created 4 pointers, thus the 4x4 = 16. And for the cpp you may ask "well wouldn't it then be 16 as it was initalized?" and the answer is no, because a ***pointer is its own separate variable and still just a pointer(a pointer to a pointer to a pointer, or a pointer to an array of pointers), and requires only 4bytes of memory.
Example
#include <stdio.h>
struct A {
char *b;
};
int main(int argc, char *argv[]) {
char c[4] = { 'c', 'a', 't', '\0' };
struct A a;
a.b = c;
printf("%s\n", a.b); // cat
printf("%lu\n", sizeof c); // 4
printf("%lu\n", sizeof a.b); // 8 ???
}
Why does sizeof a.b returns 8 and not 4? If I understood correctly, a.b returns the value that was assigned to it, which is c. But shouldn't it return the size of c (which is 4) then?
sizeof() operator gives the number of bytes allocated to the object and in your case the object is a pointer whose size looks like is 8 bytes on your system.
You're calling sizeof() on two different types.
sizeof(a.b) is sizeof(char *), which is 8 on your platform.
sizeof(c) is sizeof(char[4]), which is 4.
We can have pointers point to arrays via array decaying, which you can read about in this other answer: What is array decaying?
First of all sizeof(a.b) is not size of c. It doesn't give size of what it is pointing to, rather it is size of the pointer.
Take an example of char:
size of char a is 1
and char *b is 4. (on 64 bit)
So it is size of the pointer not what it points to. Please note these sizes are platform dependent.
Although don't get confused by int. An int and int * are of same size on some platforms.
If I understood correctly, a.b returns the value that was assigned to it,
Not exactly. a.b is what's called an lvalue. This means that it designates a memory location. However it does not read that memory location yet; that will only happen if we use a.b within a larger context that expects the memory location to be read.
For example:
a.b = something; // does not read a.b
something = a.b; // does read a.b
The case of sizeof is one context where it does not read the memory location. In fact it tells you how many bytes comprise that memory location; it doesn't tell you anything about what is stored there (let alone about some other memory location that might be pointed to by what is stored there, if it is a pointer).
The output is telling you that your system uses 8 bytes to store a pointer.
sizeof() returns the number of bytes of a variable.
In this case sizeof ( char * ) returns 8 bytes which is the number of bytes that compose a pointer.
Recently, I am trying to make good practice on C now I come to a command execution.
It tells me that I should us char**? But am I have some concept wrong.
Please help me.
Code is here
int excution(int cnt, char token[][BUFSIZE],int *t_token)
{
setenv ("PATH", "/bin:/bin/usr:", 1);
//printf("%s",getenv("PATH")); // check environement
const char *b_cd="cd";
const char *b_exit="exit";
const char *b_fg="fg";
const char *b_jobs="jobs";
int i,j,k;
//STEP 9:excute normal commanand
char args[cnt][BUFSIZE];
for(i=0;i<MAXARG;i++)
{
if(t_token[i]==COMMAND)
{
strcpy(args[0],token[i]); // copy 1st ARG
j=1;
while(t_token[i+1]==ARG)
{
strcpy(args[j],token[i+1]);
i++;
j++;
}
for(k=0;k<j;k++)
{
printf("%s\n", args[k]);
}
execvp (args[0], args);
}
}
It gives me warning in compilation. But it gives segmentation fault if I change 2D array to a char**....
warning: passing argument 2 of ‘execvp’ from incompatible pointer type
[enabled by default] /usr/include/unistd.h:579:12: note: expected
‘char * const*’ but argument is of type ‘char (*)[256]’
Maybe I'm just old, but when I see char var[X][Y] I think the compiler is going to allocate a chunk of memory of sizeof(char)*X*Y and then var[i] will be equal to var+(i*Y*(sizeof(char))). As long as everybody knows what X & Y are, all is cool. But execvp() doesn't know your X & Y sizes.
In contrast, char * var[X] will give me an array of X pointers each sizeof(char*), or a blob of memory of sizeof(char*)*X.
Now char's are generally 1 byte. char* is generally 4 or 8 bytes, but can vary depending on your system.
So char * var[X] might be a chunk of memory X*8 bytes in size, and anyone receiving var as an argument would know how to access each char* pointer in that array as pointer sizes are well known by the compiler and it's just a standard offset.
On the other hand, anyone receiving char var[X][Y] is going to be really confused. There's no way to tell where one argument ends and another begins in that giant chunk of memory.
Long story short: Use char * args[SIZE];, use arg[i] = "command" or arg[i] = token[j], and learn about pointers.
p.s. char** is a pointer to a pointer to char. (It's, say, 8 bytes that points to another memory address of 8 bytes of data that contains the memory address of a char (1-byte) value. This makes more sense when we talk about storing strings as null-terminated (char(0)) arrays of characters - e.g. sequentially stored characters, so if we know the address of the first character in the string we can just increment the pointer to get the next character until we hit zero, the null character '\0'.)
It's similar to, but not quite the same as an array of pointers to char. (Which is, say, 8 bytes that points to a memory address containing at least 8 bytes of data, perhaps N*8 bytes of sequential memory addresses (pointers). Again, just like with the sequential char array, we can have an array of char*, one stored after the other in memory.)
It would be more accurate to say a char** is roughly equal to a char*[N], only the char** doesn't allocate any memory for the internal char* pointers whereas char*[N] does - it allocate space for N char* pointers.
When receiving an array of pointers to char (char*[]), you can declare it as a pointer to a pointer to char (char**) and still iterate through the array. You just need to have the right underlying block of memory (data) located (passed in) where that pointer points to.
char str[] = " http://www.ibegroup.com/";
char *p = str ;
void Foo ( char str[100]){
}
void *p = malloc( 100 );
What's the sizeof str,p,str,p in the above 4 case in turn?
I've tested it under my machine(which seems to be 64bit) with these results:
25 8 8 8
But don't understand the reason yet.
sizeof(char[]) returns the number of bytes in the string, i.e. strlen()+1 for null-terminated C strings filling the entire array. Arrays don't decay to pointers in sizeof. str is an array, and the string has 25 characters plus a null byte, so sizeof(str) should be 26. Did you add a space to the value?
The size of a pointer is of course always determined just by the machine architecture, so both instances of p are 8 bytes on 64-bit architectures and 4 bytes on 32-bit architectures.
In function arguments, arrays do decay to pointers, so you're getting the same result that you get for a pointer. Therefore, the following definitions are equivalent:
void foo(char s[42]) {};
void foo(char s[100]) {};
void foo(char* s) {};
The first is the sizeof of an built-in array, which is the amount of elements (24 + null on the end of the string).
The second is the sizeof of a pointer which is the native word size of your system, in your case 64 bit or 8 bytes.
The third is the sizeof of a pointer to the first element of an array which has the same size as any other pointer, the native word size of your system. Why a pointer to the first element of an array? Because size information of an array goes lost when passed to a function and it gets implicitly converted to a pointer to the first element instead.
The fourth is the sizeof of a pointer which has the same size as any other pointer.
str is an array of 8-bit characters, including null terminator.
p is a pointer, which is typically the size of the machine's native word size (32 bit or 64 bit).
The size taken up by a pointer stays constant, regardless of the size of the memory to which it points.
EDIT
In c++, arguments that are arrays are passed by reference (which internally is a pointer type), that's why the second instance of str has sizeof 8.
in the cases the size of
char str[] = “ http://www.ibegroup.com/”
is known to be 25 (24+1), because that much memory is actually allocated.
In the case of
void Foo ( char str[100]){
no memory is allocated