I need help figuring out why I am getting a segmentation fault here. I have gone over it and I think I am doing something wrong with the pointers, but I can figure out what.
My Program:
#include <stdlib.h>
#include <stdio.h>
void encrypt(char* c);
//characters are shifted by 175
int main(){
char* a;
*a = 'a';
/*SEGMENTATION FAULT HERE!*/
encrypt(a);
printf("test:%c/n",*a);
return 0;
};
void encrypt(char* c){
char* result;
int i=(int)(*c);
i+=175;
if(i>255)
{
i-=256;
}
*c=(char)i;
};
The problem is here:
char *a;
*a = 'a'
Since the variable "a" is not initialized, *a = 'a' is assigning to a random memory location.
You could do something like this:
char a[1];
a[0] = 'a';
encrypt(&a[0]);
Or even just use a single character in your case:
int main(){
char a = 'a';
encrypt(&a);
printf("test:%c/n",a);
return 0;
};
char* a;
*a = 'a';
/*SEGMENTATION FAULT HERE!*/
There isn't any "there" there. You've declared a and left it uninitialized. Then you tried to use it as an address. You need to make a point to something.
One example:
char buffer[512];
char *a = buffer;
(Note buffer has a maximum size and when it falls out of scope you cannot reference any pointers to it.)
Or dynamic memory:
char *a = malloc(/* Some size... */);
if (!a) { /* TODO: handle memory allocation failure */ }
// todo - do something with a.
free(a);
That pointer a does not get the actual space where to store the data. You just declare the pointer, but pointing to where? You can assign memory this way:
char *a = malloc(1);
Then it won't segfault. You have to free the variable afterwards:
free(a);
But in this case, even better,
char a = 'a';
encript(&a);
Related
#include <stdio.h>
#include <string.h>
void replace (char a[]){
char *y;
*y = 'm';
char *p = a;
p = strchr(p, 'g');
while (p){
*p = *y;
p++;
p = strchr(p, 'g');
}
}
int main (){
char x[10];
gets(x);
replace(x);
puts(x);
return 0;
}
What's wrong with this replace function?
It doesn't output a string instead it says segmentation fault.
You're trying to write to a wild pointer here:
char *y;
*y = 'm';
y doesn't point anywhere in particular, so you get Undefined Behaviour (a seg fault in your particular case).
You are assigning value using an uninitialized pointer, y.
Why do you use pointer y anyway, instead of
*p = *y;
you can just say
*p = 'm';
y is not allocated. It is just a pointer and a pointer must point to a space in the memory. But you didn't allocate any space in the memory. So when you defferentiate it, is going to deferentiate the garbage address that a non itialized pointer has. Crash...
So rather than
char *y;
*y='p';
just write:
char y='p'; ///no pointer
Then a first improvment at the function. The function is too specific, just for a character, I would write like:
void replace (char a[],char from, char to)
{
char *p = a;
while(*p)
{
if(*p==from) *p=to;
p++;
}
}
If you compile your program with warnings enabled you should get a warning like this (with the GCC compiler):
warning: ‘y’ is used uninitialized in this function [-Wuninitialized]
*y = 'm';
^
Before you dereference the pointer y you need to know that it points to a valid object, but in your case y has not been assigned a value so it can point anywhere. Also you don't need any extra pointer; here is a more concise (and more general) version of the function:
static void replace(char old, char new, char s[])
{
s = strchr(s, old);
while (s != NULL) {
*s = new;
s = strchr(s, old);
}
}
Or without using strchr:
static void replace(char old, char new, char s[])
{
int i = 0;
while (s[i] != '\0') {
if (s[i] == old) {
s[i] = new;
}
i++;
}
}
I have a structure with a member that I need to pass to a function by reference. In that function, I'd like to allocate memory & assign a value. I'm having issues somewhere along the line - it seems that after the code returns from allocateMemory, the memory that I had allocated & the values that I assigned go out of scope (this may not be exactly what is happening, but it appears to be the case).
#include <stdio.h>
#include <stdlib.h>
typedef struct myStruct_t
{
char *myString;
} myStruct;
void allocateMemory(void *str);
int main(void) {
myStruct tmp = {
.myString = NULL
};
myStruct *p = &tmp;
allocateMemory(p->myString);
//allocateMemory(&(p->myString)); //also tried this
printf("%s", p->myString);
return 0;
}
void allocateMemory(void *str)
{
str = malloc(8);
((char *)str)[0] = 'a';
((char *)str)[1] = 0;
}
If I print the value of str inside of allocateMemory, the 'a' is successfully printed, but if I attempt to print p->myString in main, my string is empty.
Can anyone tell me what I'm doing wrong?
You need to pass address of the structure member and then you can change (aka allocate memory) to it. In your version of the function, you are not taking a pointer not reference of a pointer, so you can change the content of memory referenced by the pointer but not the pointer itself.
So change your function to
void allocateMemory(char **ret_str)
{
char *str = malloc(8);
str[0] = 'a';
str[1] = 0;
*ret_str = str;
}
And then call it as
allocateMemory(&p->myString)
An alternative way of writing the same function Rohan did, eliminating the need to define any new variables:
void allocateMemory(char **str, size_t size) {
*str = malloc(size);
(*str)[0] = 'a';
(*str)[1] = '\0';
}
Note that I pass a size parameter to justify using malloc() in the first place.
This relates to C. I am having some trouble understanding how I can assign strings to char pointers within arrays from a function.
#include <stdio.h>
#include <string.h>
void function(char* array[]);
int main(void)
{
char* array[50];
function(array);
printf("array string 0: %s\n",array[0]);
printf("array string 1: %s\n",array[1]);
}
void function(char* array[])
{
char temp[] = "hello";
array[0] = temp;
array[1] = temp;
return;
}
Ideally, I would like the main printf function to return
array string 0: hello
array string 1: hello
But I'm having trouble understanding arrays of pointers, how these pass to functions and how to manipulate them in the function. If I declare a string like char temp[] = "string" then how do I assign this to one of the main function array[i] pointers? (assuming I have my jargon right)
char temp[] = "hello"; only creates a local, temporary array inside the function. So when the function exists, the array will be destroyed.
But with array[0] = temp; you're making array[0] point to the local array temp.
After the function returns, temp doesn't exist anymore. So accessing array[0] which pointed to temp will cause undefined behavior.
You could simply make temp static, so it also exists outside the function:
static char temp[] = "hello";
Or, you could copy the "hello" string to array[0] and array[1]. For copying C-strings, you normally use strcpy.
char temp[] = "hello";
strcpy(array[0], temp);
strcpy(array[1], temp);
However, before copying you need to make sure array[0] and array[1] point to memory that has enough space to hold all characters of "hello", including the terminating null character. So you have to do something like this before calling strcpy:
array[0] = malloc(6);
array[1] = malloc(6);
(6 is the minimum numbers of characters that can hold "hello".)
how do I assign this to one of the main function array[i] pointers
Arrays cannot be assigned.
A pointer cannot hold an array, it can only refer to an array. For the latter the pointer needs to get an array's address assigned.
Referring 1.
This
char temp[] = "hello";
isn't an assigment, but an initialisation.
This
char temp[];
temp[] = "hello";
would not compile (the 2nd line errors), as an array cannot be assigned.
Referring 2.
This
char* array[50];
defines an array of 50 pointers to char, it could reference 50 char-arrays, that is 50 C-"strings". It cannot hold the C-"strings" themselfs.
Example
Applying what is mentioned above to your code whould lead to for example the following:
#include <stdio.h>
#include <string.h>
void function(char* array[]);
int main(void)
{
char* array[50];
/* Make the 1st two elements point to valid memory. */
array[0] = malloc(42); /* Real code shall test the outcome of malloc()
as it might fail and very well return NULL! */
array[1] = malloc(42);
function(array);
printf("array string 0: %s\n",array[0]);
printf("array string 1: %s\n",array[1]);
return 0;
}
void function(char* array[])
{
char temp[] = "hello";
/* Copy the content of temp into the memory that was allocated to
the array's 1st memebrs in main(). */
strcpy(array[0], temp);
strcpy(array[1], temp);
return;
}
first, you need to allocate the destination.
second, char temp[] = "hello"; in function() is local variable. you cannot use their outside of the function. use strcpy to copy the content.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void function(char* dest)
{
char temp[] = "hello";
strcpy(dest, temp);
return;
}
int main(void)
{
// or just char dest[10] = {0};
char *dest = malloc(10);
function(dest);
printf("dest: %s\n", dest);
}
In you program, you defined char* array[50];, so you need to create memory space for each item:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void function(char* a[])
{
char temp[] = "hello";
strcpy(a[0], temp);
strcpy(a[1], temp);
return;
}
int main(void)
{
char *a[50];
int i = 0;
for (i = 0; i < 50; ++i)
a[i] = malloc(10);
function(a);
printf("a[0]: %s\n", a[0]);
printf("a[1]: %s\n", a[1]);
}
I'm writing a function that reverses a cstring not in place but returns the reversed cstring. What exactly should the return type be?
#include <stdio.h>
#include <string.h>
const char* reverStr(const char *str)
{
char revStr[strlen(str)];
int i;
for(i = strlen(str)-1; i >= 0; i--)
revStr[strlen(str)-1-i] = str[i];
printf("returned value should be %s\n", revStr);
return revStr;
}
int main()
{
char aStr[] = "hello";
char aStr2[] = "goodbye";
printf("%s %s", aStr, aStr2);
char* tmp = reverStr(aStr);//tmp now has garbage
printf("\n%s", tmp);
printf(" %s", aStr);
return 0;
}
Gives
warning: function returns address of local variable [enabled by default]|
warning: initialization discards 'const' qualifier from pointer target type [enabled by default]|
I tried changing char* tmp to char tmp[] but it wouldn't compile. It confuses me when I should use an array and when I should use a pointer.
revStr is an array and ceases to exist after reverStr function exits. For more please read:
Where is the memory allocated when I create this array? (C)
const char* reverStr(const char *str)
{
char revStr[strlen(str)];
return revStr; /* Problem - revStr is a local variable trying to access this address from another function will be erroneous*/
}
const char* reverStr(const char *str)
{
const char * revStr = str;
return revStr; //ok
}
A modifiable l-value cannot have an array type. An l-value is an expression which can come on the left side of an assignment. You use an array when you want to declare lots of variables of the same type and you can index it easily since its layout will be in a sense contiguous.
You use pointers when you want to keep changing the values of the address where you variable points to.
You can do this:
char * p = "test";
p = "new";
But you cannot do this:
char p[] = "test";
char *p1 ="test1";
p = p1; //error
Because their (arrays and pointers) types are not the same and the array p is a non-modifiable l-value.
Here is your fixed code. I tried to make less modifications.
char revStr[strlen(str)]; allocates a local variable(an array) and when you are out of the scope of the reverStr function, its memory is released, which will lead any further usage of its pointer to be UB(segfault in most cases).
A correct way is to allocate the string on the heap and return its pointer like this
char* x = (char*)malloc(strlen(str));
...
return x;
This requires user to be responsible to free the memory. Or you could pass another parameter to your function for the result string.
I think you should use malloc to allocate a new string.
const char* reverStr(const char *str)
{
char *revStr;//using pointer
int i;
revStr = (char*)malloc(strlen(str));//dynamic allocation
for(i = strlen(str)-1; i >= 0; i--)
revStr[strlen(str)-1-i] = str[i];
printf("returned value should be %s\n", revStr);
return revStr;
}
An array is a pointer point to the head of continuous memory.
for example:
int a[] = {1,2,3};
The address in memory maybe:
--1000
|1|
--1004
|2|
--1008
|3|
--1012
1000, 1004, and 1012 are the value of address in memory.
Thus, the value of array a should be 1000.
printf("%d",a);// Yes, you can do it and you may get the value of 1000.
Also, you can use the following code.
int a[] = {1,2,3};
int *b;
b= a;
printf("%d",b[1]);// you will get "2".
You can consider that pointer is a set and array is in the set.
Therefore, you can NOT do this;
int a[] = {1,2,3};
int c = 0;
int *b = &c;
a = b;//error
int main() {
int i;
char a[]={"Hello"};
while(a!='\0') {
printf("%c",*a);
a++;
}
getch();
return 0;
}
Strings are stored in contiguous memory locations & while passing the address to printf() it should print the character. I have jst started learning C. I am not able to find an answer to this. Pls help.
Well a is the name of the array which you cannot increment. It is illegal to change the address of the array.
So define a pointer to a and then increment
#include <stdio.h>
#include <conio.h>
int main()
{
int i;
char a[]="Hello";
char *ptr = a;
while(*ptr!='\0')
{
printf("%c",*ptr);
// a++ here would be illegal
ptr++;
}
getch();
return 0;
}
NOTE:
In fact, arrays in C are non-modifiable lvalues. There are no
operations in C that can modify the array itself (only individual
elements can be modifiable).
In your code, a is a name of an array, you can't modify it like a++. Use a pointer like this:
char *p = "Hello";
while(*p++)
{
printf("%c",*p);
}
Three problems:
char a[]={"Hello"}; is illegal. {"Hello"} can only initialize char* a[]. You probably want char a[]="Hello";
while(a!='\0') - you probably meant *a != '\0'. a is the array itself.
a++; - an array cannot be incremented. you should increment a pointer pointing to it.
You can also try it using a for loop:
#include <stdio.h>
int main(void) {
char a[] = "Hello";
char *p;
for(p = a; *p != '\0'; p++) {
printf("%c", *p);
}
return 0;
}