I am trying to use memcpy C library function to swap rows of 2D array(array of strings). Source files for this task is below:
main.c
#include <stdlib.h>
#include "main.h"
char *table[NBLOCK] = {
"abcdefghi",
"defghiabc",
"ghiabcdef",
"bcaefdhig",
"efdhigbca",
"higbcaefd",
"cabfdeigh",
"fdeighcab",
"ighcabfde",
};
int main() {
swap_rows(table, 0, 2);
return 0;
}
main.h
#define NBLOCK 9
#define BLOCK_CELLS 9
void swap_rows(char**, int, int);
shuffle.c
#include <string.h>
#include "main.h"
void swap_rows(char **table, int r1, int r2) {
char tmp[BLOCK_CELLS];
size_t size = sizeof(char) * BLOCK_CELLS;
memcpy(tmp, table[r1], size);
memcpy(table[r1], table[r2], size); /* SIGSEGV here */
memcpy(table[r2], tmp, size);
}
Segmentation fault occurs inside swap_rows function. Out of three memcpy calls shown above, the first one works as expected. I commented out the last two memcpy calls and added below line:
table[0][0] = 'z';
But, segmentation fault occurred again. Why I am not allowed to override values of table in swap_rows function?
You are not allowed to modify string literals.
For more information, see c - Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?.
You can modify values of pointers to swap rows.
void swap_rows(char **table, int r1, int r2) {
char* tmp;
tmp = table[r1];
table[r1] = table[r2];
table[r2] = tmp;
}
If you prefer to use memcpy():
void swap_rows(char **table, int r1, int r2) {
char* tmp;
size_t size = sizeof(tmp);
memcpy(&tmp, &table[r1], size);
memcpy(&table[r1], &table[r2], size);
memcpy(&table[r2], &tmp, size);
}
In your code table is not defined as a 2D array of char, it is an array of pointers to char initialized with pointers to string literals, which must not be modified.
You get a segmentation fault because the string literals are stored in read-only memory protected by the operating system.
You should either swap the pointers in swap_rows or define table as a real 2D array and swap the rows with an appropriate prototype:
#include <stdlib.h>
//#include "main.h"
#define NBLOCK 9
#define BLOCK_CELLS 9
void swap_rows(char table[][BLOCK_CELLS], int, int);
char table[NBLOCK][BLOCK_CELLS] = {
"abcdefghi",
"defghiabc",
"ghiabcdef",
"bcaefdhig",
"efdhigbca",
"higbcaefd",
"cabfdeigh",
"fdeighcab",
"ighcabfde",
};
int main() {
swap_rows(table, 0, 2);
return 0;
}
void swap_rows(char table[][BLOCK_CELLS], int r1, int r2) {
char tmp[BLOCK_CELLS];
size_t size = sizeof(tmp);
memcpy(tmp, table[r1], size);
memcpy(table[r1], table[r2], size);
memcpy(table[r2], tmp, size);
}
Related
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct individual {
char name[32];
int stats[7];
char role;
};
void create_array(struct individual **array){
*array = malloc(sizeof(struct individual)); //allocate initial memory space
}
void resize_array(struct individual **array, unsigned char num) {
printf("%d\n", *array);
*array = realloc(*array, num * sizeof(struct individual));
printf("%d\n", *array);
printf("resize success\n");
}
void problem(struct individual **f_array, unsigned char *f_num) {
*f_num = 2;
printf("%d\n", *f_array);
resize_array(f_array, *f_num);
printf("%d\n", *f_array);
strcpy(f_array[*f_num - 1]->name, "test value"); //CRASH LINE
}
int main() {
unsigned char f_num = 0;
struct individual *f_array;
create_array(&f_array);
problem(&f_array, &f_num);
}
This code crashes on the line marked "CRASH LINE". While it is not shown here, doing this same code setting (*f_num = 1) does not result in an error. While passing *f_array as itself (with appropriate alterations to the code in problem) does not result in an error, the values given after problem is exited result in nonsense being given, as the pointer reverts to it's pre-resize state. Any help appreciated.
The problem is the line accessing that value.
The line should read like this:
strcpy((*f_array)[*f_num - 1].name, "test value"); // doesn't crash any more :)
To break it down a little bit:
f_array is a pointer to the array of structs, need to dereference it before indexing
[*f_num - 1] accesses element 1 of the array.
This question already has answers here:
Changing address contained by pointer using function
(5 answers)
Closed 2 years ago.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *alloc_init(void *ptr, size_t size, void *val)
{
ptr = malloc(size);
memcpy(ptr, val, size);
return ptr;
}
int main()
{
int *a;
int val = 5;
int b = 5;
alloc_init(a, 4, &val);
printf("%d\n", *a);
return 0;
}
It's a very simple program - I wanted to test the alloc_init function. I expect 5 to be printed, but it's always 1. The function should be allocating memory for a variable(in this case) and assigning it a value passed to the function by copying it's bytes. What am I doing wrong?
Two ways to do this (both untested):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void alloc_init(void **ptr, size_t size, void *val)
{
*ptr = malloc(size);
memcpy(*ptr, val, size);
}
int main()
{
int *a;
int val = 5;
int b = 5;
alloc_init(&a, sizeof *a, &val);
printf("%d\n", *a);
return 0;
}
or
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *alloc_init(size_t size, void *val)
{
void *ptr = malloc(size);
memcpy(ptr, val, size);
return ptr;
}
int main()
{
int *a;
int val = 5;
int b = 5;
a = alloc_init(sizeof *a, &val);
printf("%d\n", *a);
return 0;
}
You should probably prefer the 2nd approach. Passing an int** where a void** is expected is probably UB.
I'm fully prepared to be told that I'm doing something stupid/wrong; this is what I expect.
I'm getting a feel for structures and coming a cropper when it comes to accessing the fields from the pointers. Code to follow.
matrix.h:
#ifndef MATRIX_H_INCLUDED
#define MATRIX_H_INCLUDED
#include <stdlib.h>
typedef struct
{
size_t size;
int* vector;
} vector_t;
#endif // MATRIX_H_INCLUDED
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "matrix.h"
vector_t* vector_new(size_t size)
{
int vector[size];
vector_t v;
v.size = size;
v.vector = vector;
return &v;
}
int main(int argc, char* argv[])
{
vector_t* vec = vector_new(3);
printf("v has size %d.\n", vec->size);
printf("v has size %d.\n", vec->size);
return EXIT_SUCCESS;
}
So this is a very simple program where I create a vector structure of size 3, return the pointer to the structure and then print its size. This, on the first print instance is 3 which then changes to 2686668 on the next print. What is going on?
Thanks in advance.
You are returning a pointer to a local variable v from vector_new. This does not have a slightest chance to work. By the time vector_new returns to main, all local variables are destroyed and your pointer points to nowhere. Moreover, the memory v.vector points to is also a local array vector. It is also destroyed when vector_new returns.
This is why you see garbage printed by your printf.
Your code has to be completely redesigned with regard to memory management. The actual array has to be allocated dynamically, using malloc. The vector_t object itself might be allocated dynamically or might be declared as a local variable in main and passed to vector_new for initialization. (Which approach you want to follow is up to you).
For example, if we decide to do everything using dynamic allocation, then it might look as follows
vector_t* vector_new(size_t size)
{
vector_t* v = malloc(sizeof *v);
v->size = size;
v->vector = malloc(v->size * sizeof *v->vector);
return v;
}
(and don't forget to check that malloc succeeded).
However, everything that we allocated dynamically we have to deallocate later using free. So, you will have to write a vector_free function for that purpose.
Complete re-write of answer to address your question, and to provide alternate approach:
The code as written in OP will not compile: &v is an illegal return value.
If I modify your code as such:
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
size_t size;
int* vector;
} vector_t;
vector_t* vector_new(size_t size)
{
int vector[size];
vector_t v, *pV;
pV = &v;
pV->size = size;
pV->vector = vector;
return pV;
}
int main(int argc, char* argv[])
{
vector_t* vec = vector_new(3);
printf("v has size %d.\n", vec->size);
printf("v has size %d.\n", vec->size);
getchar();
return EXIT_SUCCESS;
}
It builds and runs, but returns unintended values for vec->size in main() due to the local scope of that variable in the function vector_new.
Recommend creating globally visible instance of your struct, and redefine vector_new() to int initVector(void):
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
typedef struct
{
size_t size;
int* vector;
} vector_t;
vector_t v, *pV;//globally visible instance of struct
int initVector(void)
{
int i;
pV->size = SIZE;
pV->vector = calloc(SIZE, sizeof(int));
if(!pV->vector) return -1;
for(i=0;i<SIZE;i++)
{
pV->vector[i] = i;
}
return 0;
}
int main(int argc, char* argv[])
{
int i;
pV = &v; //initialize instance of struct
if(initVector() == 0)
{
printf("pV->size has size %d.\n", pV->size);
for(i=0;i<SIZE;i++) printf("pV->vector[%d] == %d.\n", i, pV->vector[i]);
}
getchar(); //to pause execution
return EXIT_SUCCESS;
}
Yields these results:
You still need to write a freeVector function to undo all the allocated memory.
I am starting to learn about pointers in C.
How can I fix the error that I have in function x()?
This is the error:
Error: a value of type "char" cannot be assigned to an entity of type "char *".
This is the full source:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
void x(char **d, char s[]) {
d = s[0]; // here i have the problem
}
void main() {
char *p = NULL;
x(&p, "abc");
}
In function x() you pass d which is a char ** (a pointer to a string pointer), and char s[] (an array of char, passed as similarly to a pointer to char).
So in the line:
d = s[0];
s[0] is a char, whereas char **d is a pointer to a pointer to char. These are different, and the compiler is saying you cannot assign from one to the other.
However, did your compiler really warn you as follows?
Error: a value of type "char" cannot be assigned to an entity of type "char *"
Given the code sample, it should have said char ** at the end.
I think what you are trying to make x do is copy the address of the string passed as the second argument into the first pointer. That would be:
void x(char **d, char *s)
{
*d = s;
}
That makes p in the caller point to the constant xyz string but does not copy the contents.
If the idea was to copy the string's contents:
void x(char **d, char *s)
{
*d = strdup(s);
}
and ensure you remember to free() the return value in main(), as well as adding #include <string.h> at the top.
A more proper way would be to use strcpy:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
void x(char **d) {
*d = malloc(4 * sizeof(char));
strcpy(*d, "abc");
}
int main() {
char *p;
x(&p);
printf("%s", p);
free(p);
return 0;
}
Outputs: abc
This question already has answers here:
Passing address of array as a function parameter
(6 answers)
Closed 9 years ago.
I'm writing a function that gets a string, allocates memory on the heap that's enough to create a copy, creates a copy and returns the address of the beginning of the new copy.
In main I would like to be able to print the new copy and afterwards use free() to free the memory. I think the actual function works although I am not the char pointer has to be static, or does it?
The code in main does not work fine...
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int make_copy(char arr[]);
int main()
{
char arrr[]={'a','b','c','d','e','f','\0'};
char *ptr;
ptr=make_copy(arrr);
printf("%s",ptr);
getchar();
return 0;
}
int make_copy(char arr[])
{
static char *str_ptr;
str_ptr=(char*)malloc(sizeof(arr));
int i=0;
for(;i<sizeof str_ptr/sizeof(char);i++)
str_ptr[i]=arr[i];
return (int)str_ptr;
}
OK, so based on the comments. A revised version:
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
char* make_copy(char arr[]);
int main()
{
char arrr[]={"abcdef\0"};
char *ptr=make_copy(arrr);
printf("%s",ptr);
getchar();
return 0;
}
char* make_copy(char arr[])
{
static char *str_ptr;
str_ptr=(char*)malloc(strlen(arr)+1);
int i=0;
for(;i<strlen(arr)+1;i++)
str_ptr[i]=arr[i];
return str_ptr;
}
Or even better:
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* make_copy(char arr[]);
int main()
{
char arrr[]={"abcdef\0"};
printf("%s",make_copy(arrr));
getchar();
return 0;
}
char* make_copy(char arr[])
{
char *str_ptr;
str_ptr=(char*)malloc(strlen(arr)+1);
return strcpy(str_ptr,arr);
}
You're on the right track, but there are some issues with your code:
Don't use int when you mean char *. That's just wrong.
Don't list characters when defining a string, write char arrr[] = "abcdef";
Don't scale string alloations by sizeof (char); that's always 1 so it's pointless.
Don't re-implement strcpy() to copy a string.
Don't cast the return value of malloc() in C.
Don't make local variables static for no reason.
Don't use sizeof on an array passed to a function; it doesn't work. You must use strlen().
Don't omit including space for the string terminator, you must add 1 to the length of the string.
UPDATE Your third attempt is getting closer. :) Here's how I would write it:
char * make_copy(const char *s)
{
if(s != NULL)
{
const size_t size = strlen(s) + 1;
char *d = malloc(size);
if(d != NULL)
strcpy(d, s);
return d;
}
return NULL;
}
This gracefully handles a NULL argument, and checks that the memory allocation succeeded before using the memory.
First, don't use sizeof to determine the size of your string in make_copy, use strlen.
Second, why are you converting a pointer (char*) to an integer? A char* is already a pointer (a memory address), as you can see if you do printf("address: %x\n", ptr);.
sizeof(arr) will not give the exact size. pass the length of array to the function if you want to compute array size.
When pass the array to function it will decay to pointer, we cannot find the array size using pointer.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *strdup(const char *str)
{
char *s = (char*)malloc(strlen(str)+1);
if (s == NULL) return NULL;
return strcpy(s, str);
}
int main()
{
char *s = strdup("hello world");
puts(s);
free(s);
}
Points
~ return char* inside of int.
~ you can free the memory using below line
if(make_copy!=NULL)
free(make_copy)
Below is the modified code.
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
char* make_copy(char arr[]);
int main()
{
char arrr[]={'a','b','c','d','e','f','\0'};
char *ptr;
ptr=make_copy(arrr,sizeof(arrr)/sizeof(char));
printf("%s",ptr);
printf("%p\n %p",ptr,arrr);
getchar();
return 0;
}
char* make_copy(char arr[],int size)
{
char *str_ptr=NULL;
str_ptr=(char*)malloc(size+1);
int i=0;
for(;i<size;i++)
str_ptr[i]=arr[i];
str_ptr[i]=0;
return str_ptr;
}