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
Related
I'm trying to figure out how to "transform" strings (char*) to void* and viceversa.
When I execute this my output is just the first printf and ignores the second one, it doesn't even write "after = "
PS This little program is just to understand, I know i could actually use swap(&s[0],&s[1]). I need to know how to properly cast a void pointer into an array of strings.
I'm working on a uni project where I need to create my own quick_sort algorythm and I need the swap function inside of it to work with void pointers.
#include <stdio.h>
#include <stdlib.h>
static void swap(char** x,char** y);
static void swap(char** x,char** y){
char* temp=*x;
*x=*y;
*y=temp;
}
int main()
{
char* s[2];
s[0]="weee";
s[1]="yooo";
void* array=s;
printf("before %s %s\n",s[0],s[1]);
swap((&array)[0],(&array)[1]);
printf("after = %s %s",(char*)array,(char*)array);
return 0;
}
I think I'm missing something big
Thanks in advance :D
In this declaration the array s used as an initializer is implicitly converted to a pointer to its first element of the type char **.
void* array = s;
In the call of the function swap
swap((&array)[0],(&array)[1]);
the first argument can be the pointer array itself that will be implicitly casted to the pointer type of the corresponding parameter
swap( array, (&array)[1]);
But you need to correctly pass the second argument. To do this you need to cast the pointer array explicitly like
swap( array, ( char ** )array + 1 );
In the call of printf you need also correctly to supply argument expressions.
Here is your updated program
#include <stdio.h>
static void swap(char** x,char** y);
static void swap(char** x,char** y){
char* temp=*x;
*x=*y;
*y=temp;
}
int main()
{
char* s[2];
s[0]="weee";
s[1]="yooo";
void* array=s;
printf("before %s %s\n",s[0],s[1]);
swap( array, ( char ** )array + 1 );
printf("after = %s %s", *(char**)array, ( (char**)array )[1]);
return 0;
}
The program output is
before weee yooo
after = yooo weee
void *array = s; declares array to be a void *. Then &array is the address of that void *, so &array[1] would access a void * after it. But there is no void * after it, since void *array defines a single void *.
array could be properly defined to alias s with char **array = s;, after which swap(&array[0], &array[1]); would work as desired.
If you define array as void **array = (void **) s;, then swap(&array[0], &array[1]); will produce diagnostic messages because the types are wrong. You could use swap((char **) &array[0], (char **) &array[1]);.
Then, if you print the strings with printf("after = %s %s", array[0], array[1]);, this will work, although it is not entirely proper code. Using array[0] as an argument passes a void * where printf is expecting a char * for the %s. However, the C standard guarantees that void * and char * have the same representation (encode their values using bytes in memory in the same way), and it further says (in a non-normative note) that this is intended to imply interchangeability as arguments to functions.
The void* doesn't seem to fulfil any particular purpose here, just swap the pointers: swap(&s[0],&s[1]);.
You could also do this:
char** ptr = &s[0];
printf("before %s %s\n",ptr[0],ptr[1]);
swap(&ptr[0],&ptr[1]);
printf("after = %s %s",ptr[0],ptr[1]);
If you for reasons unknown insist on using void* then note that as your code stands, it points at the first char* in your array of char*. However, it isn't possible to perform pointer arithmetic on void* since that would entail knowing how large a "void" is. The void* doesn't know that it points at an array of pointers. Therefore array[i] is nonsense.
Also, the void* are set to point at char* so you simply cannot pass it to a function expecting a char**. You'd have to rewrite the whole program in a needlessly obfuscated way, so just abandon that idea.
I am a newbie to C and it took me 2 hours to figure out the problem.
void helper(char* a, char* b){
a = malloc(strlen(b));
memcpy(a, b, strlen(b));
printf("%s %s\n", a, b);
}
int main(){
char* b = "hello";
char* a;
helper(a, b);
printf("%s", a);
}
While a is always null. Is there anything I missed?
In main(), a and b are pointers.
helper(a, b); gives a copy of pointer a and a copy of pointer b to helper() as part of the call to helper().
The function completes.
The a in main() is not updated/changed by the call helper(a, b). Neither is b changed.
Code needs a new approach of which there are several good ones. Example: Use the return value of helper2().
char *helper2(const char *source);
int main(void) {
const char* b = "hello";
char* a = helper2(b);
printf("<%s>", a);
free(a);
}
Now create helper2(). Code template follows:
#include <...> // whats includes are needed.
#include <...>
char *helper2(const char *source) {
size_t size_needed = ....; // length + 1 for the null character
char *destination = ...' // allocate
if (destination ...) { // Successful allocation?
memcpy(destination, ...., ...); // copy - include null character
}
return ... // What should be returned here?
}
You've missed the fact that main() passes a copy of a to helper() by value. So the a in helper() is a completely different variable (even though you've given it the same name) - it has a different address.
The change of a in helper() therefore does not affect the a in main() at all.
Regardless of what helper() does, main() exhibits undefined behaviour. a is uninitialised, so passing its value to helper() gives undefined behaviour. Passing it to printf() gives undefined behaviour for the same reason.
The printf() call in helper() also has undefined behaviour, since %s causes printf() to expect a string terminated by a '\0', but the memcpy() call has not copied such a thing to a. Practically, printf() will probably keep stepping from a through random memory until it happens to find a byte with zero value. This may result in garbage output or (if there is no such byte in memory) an obscure program crash.
A partial fix of your code would be to make the change of a in helper() visible to main(). For example;
/* Danger: This code still has undefined behaviour */
void helper(char **a, char* b)
/* note usage of extra * on every usage of a in this function */
{
*a = malloc(strlen(b));
memcpy(*a, b, strlen(b));
printf("%s %s\n", *a, b);
}
int main()
{
char* b = "hello";
char* a;
helper(&a, b); /* note use of ampersand here */
printf("%s", a);
free(a); /* a has been malloc()ed, so free() it */
/* using a here will give undefined behaviour, since it is free()d */
}
This code makes the changes to a in helper() visible to main(), by use of pointers.
The problem with this partially fixed code code is that %s still causes printf to expect that a to be terminated with a trailing '\0', but the memcpy() does not copy such a trailing '\0'. So both printf() calls (in both helper() and main()) still have undefined behaviour.
To fix this, we need to change helper() to
void helper(char **a, char* b)
{
*a = malloc(strlen(b) + 1);
memcpy(*a, b, strlen(b) + 1);
printf("%s %s\n", *a, b);
}
which allocates a larger buffer, and copies the content of b - with its contained '\0' into that additional length.
An alternative is to use strcpy() instead of memcpy().
void helper(char **a, char* b)
{
*a = malloc(strlen(b) + 1);
strcpy(*a, b);
printf("%s %s\n", *a, b);
}
The only difference is that strcpy() copies characters until it finds the trailing '\0' in b.
You didnt change a inside the function. when you did malloc a received new address.
void helper(char **a, char *b){
*a = malloc(strlen(b)+1); //+1 for the \0 in the end of b
strcpy(*a, b);
printf("%s %s\n", *a, b);
}
int main(void){
char *b = "hello";
char *a;
helper(&a, b);
printf("%s\n", a);
}
And in you code you didnt use free.. You have to free all the pointers that you did malloc...
so add free(a) in the end of the main.
I renamed variables, to be clear. What #chux said, is value of variable 'a' changed, but value of variable 'x' - not.
void helper(char* a, char* b){
a = malloc(strlen(b));
memcpy(a, b, strlen(b));
printf("%s %s\n", a, b);
}
int main(){
char* y = "hello";
char* x;
helper(x, y);
printf("%s", x);
}
UPD: This is an original code. I just renamed variables in order to disambiguate variables naming, and to do explanations more clear. The problem, as it was pointed by #chux, variable x sent by value, and so cannot be changed in function main.
First mistake I saw is that you have ever to allocate strlen(foo)+1. the correct size for copy a string is this. Than call strcpy() or memset +1 . But with strings I ever use strcpy() on my mind is more performant:
char *strcpy(char *a , const char*b)
{
while(*a++=*b++)
;
return a;
}
then (this is a very trivial version, the real one has more checks)
char * memcpy(a,b,n)
{
while(n--)
*a++=*b++;
return a;
}
there is a counter more to decrease; With memset you have also to call strlen() for get the length, and add one. With strcpy() is not required. So yes, the differences are not appreciable, but there are, but what is appreciable is the redeability, the clearness of the code all this with (teorethical, unless some compiler optimization) better performance
#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.
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.
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
}