I was trying to change the value of the string t_string by passing a pointer of the string to a function and then changing the value of that pointer in the function.
The output I am receiving is the original string "Hello".
Any help would be greatly appreciated :) Thanks!
#include <stdio.h>
#include "string.h"
void editString(char *theString);
int main() {
char t_string[] = "Hello\n";
char *s = t_string;
editString(s);
printf("The string after: %s", t_string);
return 0;
}
void editString(char *theString){
theString = "Good Bye\n";
}
In C, parameters are pass by value. What you're doing is changing the value of the local variable theString to point to a string literal. That local variable change is not reflected in the calling function.
To change what theString points to, use strcpy. That will follow what theString points to (i.e. the array in main). Note however that the array isn't large enough to hold the new string, so if you do that you will write past the end of the array and invoke undefined behavior. So you need to make the array large enough to hold either string.
int main() {
char t_string[20] = "Hello\n"; // enlarge array to hold either string
char *s = t_string;
editString(s);
printf("The string after: %s", t_string);
return 0;
}
void editString(char *theString){
strcpy(theString, "Good Bye\n"); // use strcpy
}
Array designators are non-modifiable lvalues. So you can not change an array such a way.
In this statement
char *s = t_string;
there is created a new object with the name s that is initialized by the address of the first character of the array t_string.
In this call
editString(s);
there is created a copy of the value of the argument that is assigned to the function parameter.
You can imagine the function definition and its call the following way
editString(s);
//...
void editString(/*char *theString*/){
char *theString = s;
theString = "Good Bye\n";
}
So even the argument s is not changed by the function. That is at first the local variable theString initialized by the value stored in the argument s and then this local variable is reassigned by the address of the first character of the string literal "Good Bye\n".
Neither the array t_string nor the pointer s defined in main were changed in the function.
If you want to change the array you have to assign its characters individually for example by using the standard string function strcpy declared in header <string.h>. The array has to have enough size to accommodate the new string literal.
For example
#include <stdio.h>
#include "string.h"
void editString(char *theString);
int main( void )
{
char t_string[10] = "Hello\n";
char *s = t_string;
editString(s);
printf("The string after: %s", t_string);
return 0;
}
void editString(char *theString){
strcpy( theString, "Good Bye\n" );
}
Take into account that according to the C Standard the function main without parameters shall be declared like
int main( void )
Related
I am struggling to write a char* passed as an argument. I want to write some string to char* from the function write_char(). With the below code, I am getting a segmentation fault.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void write_char(char* c){
c = (char*)malloc(11*(sizeof(char)));
c = "some string";
}
int main(){
char* test_char;
write_char(test_char);
printf("%s", test_char);
return 0;
}
You have two problems (related to what you try to do, there are other problems as well):
Arguments in C are passed by value, which means that the argument variable (c in your write_char function) is a copy of the value from test_char in the main function. Modifying this copy (like assigning to it) will only change the local variables value and not the original variables value.
Assigning to a variable a second time overwrites the current value in the variable. If you do e.g.
int a;
a = 5;
a = 10;
you would (hopefully) not wonder why the value of a was changed to 10 in the second assignment. That a variable is a pointer doesn't change that semantic.
Now how to solve your problem... The first problem could be easily solved by making the function return a pointer instead. And the second problem could be solved by copying the string into the memory instead of reassigning the pointer.
So my suggestion is that you write the function something like
char *get_string(void)
{
char *ptr = malloc(strlen("some string") + 1); // Allocate memory, +1 for terminator
strcpy(ptr, "some string"); // Copy some data into the allocated memory
return ptr; // Return the pointer
}
This could then be used as
char *test_string = get_string();
printf("My string is %s\n", test_string);
free(test_string); // Remember to free the memory we have allocated
Within the function
void write_char(char* c){
c = (char*)malloc(11*(sizeof(char)));
c = "some string";
}
the parameter c is a local variable of the function. Changing it within the function does not influence on the original argument because it is passed by value. That is the function deals with a copy of the original argument.
You have to pass the argument by reference through pointer to it.
Also the function has a memory leak because at first the pointer was assigned with the address of the allocated memory and then reassigned with the address of the first character of the string literal "some string".
If you want to create a copy of a string literal then what you need is the following
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void write_char( char **s )
{
const char *literal = "some string";
*s = malloc( strlen( literal ) + 1 );
if ( *s ) strcpy( *s, literal );
}
int main( void )
{
char *test_char = NULL;
write_char( &test_char );
if ( test_char ) puts( test_char );
free( test_char );
}
The program output is
some string
Do not forget to allocate dynamically a character array that is large enough to store also the terminating zero of the string literal.
And you should free the allocated memory when the allocated array is not needed any more.
If you want just to initialize a pointer with the address of a string literal then there is no need to allocate dynamically memory.
You can write
#include <stdio.h>
void write_char( char **s )
{
*s = "some string";
}
int main( void )
{
char *test_char = NULL;
write_char( &test_char );
puts( test_char );
}
In C, you'll need to pass a pointer to a pointer. Your malloc call is trying to change the value of the variable that's being passed in, but it's actually only a copy. The real variable you pass in will not be changed.
Also, the way that you copy a string into a char* is not using assignment... Here's some revised code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void write_char(char** c){
size_t len = strlen("some string");
*c = (char*)malloc(len + 1); // + 1 for null termination
strncpy(*c, "some string", len);
}
int main(){
char* test_char;
write_char(&test_char);
printf("%s", test_char);
return 0;
}
String assignment in C is very different from most modern languages. If you declare a char * and assign a string in the same statement, e.g.,
char *c = "some string";
that works fine, as the compiler can decide how much memory to allocate for that string. After that, though, you mostly shouldn't change the value of the string with =, as this use is mostly for a constant string. If you want to make that especially clear, declare it with const. You'll need to use strcpy. Even then, you'll want to stay away from declaring most strings with a set string, like I have above, if you're planning on changing it. Here is an example of this:
char *c;
c = malloc(16 * sizeof(char));
strcpy(c, "Hello, world\n");
If you're passing a pointer to a function that will reallocate it, or even malloc in the first place, you'll need a pointer to a pointer, otherwise the string in main will not get changed.
void myfunc(char **c) {
char *tmp = realloc(*c, 32 * sizeof(char));
if(tmp != NULL) {
*c = tmp;
}
}
char *c = malloc(16 * sizeof(char));
strcpy(c, "Hello, world\n");
myfunc(&c);
char* test_char="string"; // initialize string at the time of declaration
void write_char(char* c){
c = (char*)malloc(11*(sizeof(char)));
}
int main(){
char* test_char="strin";
write_char(test_char);
printf("%s", test_char);
return 0;
}
int string1()
{
char str[]="something"
}
int string2()
{
//here I need use array str[] from string1
}
how can I use array value? Im doing string operations
Everyone has to learn how to use arrays, strings, pointers and functions -- and how to pass arrays and pointers to functions and handle function returns.
When you declare a variable (including an array type), the lifetime for the variable exists only within the scope it is declared unless memory for the variable is allocated dynamically or it is declared as static or otherwise has static storage duration.
Why? Storage for variables declared within a function is created on the function stack which is destroyed (released for reuse) on the function return. (main() is itself a function). Now a function can always return a value of its own type, but it cannot declare a an array of type with automatic storage within the function and return a pointer to the array.
char str[]="something"; /* violates that rule.... */
You have a few options, but they rely on understanding the storage duration for "something" and exactly what it is. let's look at what it appears you are attempting to do:
/* retuning pointer to string literal */
const char *string1 ()
{
const char *s = "something";
return s;
}
There are a few subtleties above. First "something" is a string literal and it has static storage duration for the life of the program. So you are assigning the address of "something" that is created in read-only memory that will survive the return of string1. Since a function can always return it's own type (in this case const char * -- chosen for that purpose), you can return the address to "something".
To use s in string2, you must pass s as an argument to string2, or assign the return of string1 to a global pointer (discouraged). Since s points to read-only memory, you should declare the parameter passed to string2 as const char * to signal it cannot be modified. Something similar to:
/* simply use string 's' in string2 */
void string2 (const char *s)
{
printf ("in string2(), s : %s\n", s);
}
Putting it altogether, you could do something like the following:
#include <stdio.h>
/* retuning pointer to string literal */
const char *string1 ()
{
const char *s = "something";
return s;
}
/* simply use string 's' in string2 */
void string2 (const char *s)
{
printf ("in string2(), s : %s\n", s);
}
int main (void) {
/* call string 2 passing string1 as the parameter */
string2 (string1 ());
return 0;
}
Example Use/Output
$ ./bin/literalreturn
in string2(), s : something
note: you can only get away with returning s in string1 because of the string literal static storage duration. Otherwise, you would need to pass s as a parameter to string1 or dynamically allocate storage for s within string1 and return a pointer to the starting address for the new block of memory.
If you were passing a character array to string1, then you would need to do something similar to the following:
#include <stdio.h>
#include <string.h>
#define MAXC 32 /* constant for array size */
/* anytime you are passing an array, pass the size. */
char *string1 (char *s, size_t max)
{
if (max < 2) {
fprintf (stderr, "error: insufficient max size.\n");
return NULL;
}
if (strlen (s) < max - 1)
strcpy (s, "something");
return s;
}
/* simply use string 's' */
void string2 (const char *s)
{
printf ("in string2(), s : %s\n", s);
}
int main (void) {
char buf[MAXC] = ""; /* declare character array of MAXC chars */
/* call string 2 passing string1 passing array and size */
string2 (string1 (buf, sizeof buf));
return 0;
}
(Since s isn't changed in string2 it is still properly passed as const char *s which allows certain compiler optimizations for your code.)
Look things over. You must understand the subtleties of each example as these concepts underlie much of C. Let me know if you have further questions.
You can use static variable in the function definition block, this has the global storage but limited access scope, when need to access it, just through the function call to get the pointer. Below is the code:
char* string1() {
static char s[64] = "hello"; //this memory has 64 chars
return s;
}
int main(int argc , char *argv[])
{
char* s = string1();
int len = strlen(s);
printf("len: %d\n", len);
for (int i = 0; i < len; ++i) {
printf("char at: %d is %c\n", i, s[i]);
}
}
Output:
len: 5
char at: 0 is h
char at: 1 is e
char at: 2 is l
char at: 3 is l
char at: 4 is o
You can't. The string from the first function is a local variable and accessing it out of scope leads to undefined behavior. What you could do is allocate the string dynamically and hand control over it to the user.
If your str is a constant as in
char str[]="something";
it is a string literal you could simply return str which being an array, will decay into base address of the array because it would be in read only memory and will remain there till end of program.
If this is the case the return type of the function should be char * like
char *string1();
See demo.
If the str is not so,
char str[30];
strcpy(str, "hello");
the str would be allocated in the stack and it cannot be accessed once control exits the function in which it is declared.
To circumvent this, you could allocate on heap memory like
char *string1()
{
char *str=malloc(sizeof(char)*30);
strcpy(str, "hello");
return str;
}
And don't forget to deallocate the memory once you are done using it.
char *p=string1();
printf("\n%s", p);
free(p);
See demo.
I'm acquainting myself with c-strings and pointers by using a very simple program.
This version, which passes in a string by reference, works:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void test(char **string) {
*string = (char *)malloc(5);
char *temp = "hell";
strcpy(*string, temp);
}
int main(int argc, char *argv[]) {
char *string = NULL;
test(&string);
printf("%s\n", string);
return 0;
}
It prints "hell".
This version, which simply passes the string by value, does not work, and results in a SEGFAULT:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void test(char *string) {
string = (char *)malloc(5);
char *temp = "hell";
strcpy(string, temp);
}
int main(int argc, char *argv[]) {
char *string = NULL;
test(string);
printf("%s\n", string);
return 0;
}
From what I know, the first version makes sense because I pass in the address of the address of the string. Thus, when I dereference this double pointer, I get the real address of the string and can reassign it with malloc.
The second version, however, I'm kind of unclear why it doesn't work. In this version I pass the address of string into the test function. I read that everything in C is passed by value but that array names are actually addresses. Doesn't this mean that I'm passing in the actual address of string into test? Shouldn't things work out the same? I'm confused, please help me out.
Remember This : In C programming to use a value,you pass "by value". To change a value you must pass "by address". So,if what you want to change is an address,then you need to pass its address to change it.otherwise you may only use it.
When you pass an argument "by value", the value of the argument is copied into the formal argument in the function. Changing a copy (in your case string inside the test function) will of course not change the original (string in the main function).
On a side-note, C doesn't actually have "pass by reference", it only have pass by value. You emulate pass by reference by using pointers.
In your second version, string itself is being passed by value, so you simply cannot change string itself. This is for the similar reason you cannot change the value of an int or float when it is passed by value. While an argument is being passed by value, there is a local copy created in the called function's stack.
You can always change the content of string, however.
In C, array type is represented as a pointer to its first element. * in type means "pointer to", but outside of type means "dereference pointer". When you pass argument to function, in the body of function, you have copy of the thing, that you passed. Lets analyse your code with that in mind:
void test(char **string) { //expect pointer to string
*string = (char *)malloc(5); //dereference pointer to string and allocate memory (*string is of type char*, it is a string)
char *temp = "hell"; //create new string
strcpy(*string, temp); //copy new string to the old one
}
int main(int argc, char *argv[]) {
char *string = NULL; //create empty pointer (string is array, which is pointer to char), but NULL is not a valid string
test(&string); //pass pointer to string
printf("%s\n", string); //print string
return 0;
}
**sting did not change, but its contents *string did.
And in the second one:
void test(char *string) { //with this type, you could modify, what is actual string content (for example first letter), but you pass here NULL, so there is nothing you can do
string = (char *)malloc(5); //here, you are changing only COPY of the pointer, that you passed in main
char *temp = "hell"; //create another string
strcpy(string, temp); //copy new string to the one created, after this operation pointer to the string is lost
}
int main(int argc, char *argv[]) {
char *string = NULL; //the same
test(string); //pass the string, you are screwed here, values in C are passed by copying, so even if you modify the string correctly, you will not see the result
printf("%s\n", string); //the string variable never changed from NULL, so you get the error
return 0;
}
this is a sample program demonstrating getting a string value from a func
can allocate memory inside called function itself and return
can allocate memory inside calling function and called function just updates it.
i am facing problem with the 2nd way.
is there any workaround?
/*
* main.c
*
* Created on: Sep 6, 2014
* Author: Murtaza
*/
#include<stdio.h>
#include<stdlib.h>
char* someFunc1();
void someFunc2(char* str);
void firstApproach();
void secondApproach();
int main()
{
firstApproach();
printf("\n");
secondApproach();
return 0;
}
char* someFunc1()
{
char *str = (char*)malloc(sizeof(char)*10);
str = "HELLO";
return str;
}
void someFunc2(char* str)
{
str = "Hello";
}
void secondApproach()
{
char *str = (char*)malloc(sizeof(char)*10);
someFunc2(str);
printf(str);
printf("heythere");
}
void firstApproach()
{
char *str;
str=someFunc1();
printf(str);
printf("wassup");
}
Please tell me why the second approach isn't working.
thanks!
my output is:
HELLOwassup
h>heythere
and my expected output should be
HELLOwassup
Helloheythere
void someFunc2(char* str)
{
str="Hello"; //-----the variable str is local to this function, thus it goes out of scope as
// soon as the function returns
}
void secondApproach()
{
char *str=(char*)malloc(sizeof(char)*10);
someFunc2(str);
printf(str); // -------------- here the value inside str is some garbage value.
printf("heythere");
}
CORRECTION :
void someFunc2(char **str )
{
*str = "hello";
}
void secondApproach()
{
char *str=(char*)malloc(sizeof(char)*10);
someFunc2(&str); // pass the address of the string
printf("%s", str);
printf("heythere");
}
Let's take a closer look at someFunc2:
void someFunc2(char* str)
{
/* str is a copy of the pointer that was passed in from secondApproach(). */
str = "Hello";
}
Here, you are passing a pointer by value. Thus, str in someFunc2 is a copy of the original pointer str that was passed in from secondApproach(). someFunc2 tells the copy pointer to point somewhere else, but it leaves the original str pointer alone. The solution is to pass in the address of the str pointer then tell someFunc2 to modify the pointer at that address to point to "hello".
void secondApproach()
{
char* str = (char*) malloc(sizeof(char) * 10);
someFunc2(&str); // Pass in the address of str.
printf("%s", str);
printf("heythere");
}
void someFunc2(char** str)
{
*str = "hello";
}
When you write a string between quotes and use it directly as:
a char* -> it gets created in a mutable place in memory, and gives its address to the pointer variable its assigned to. It is still in memory as long as that variable referencing it is not NULL.
an argument -> it gets created as char* and passed to the function (and treated there as a char*), then automatically disposed from memory (i.e. you can't access it or reference it anymore) ..
So, the only situation when a string is actually mutable is when you assign it to a char[], then it gets created in readonly memory and copied into to the stack .. ( the copy on the stack is what the char[] variable will point to )
If you think about it for some time, you realize that this is one of the benefits of dynamic memory: you can create a char* that is mutable, and since it is just a pointer, you don't need to specify the size of the string it is going to point at. So you can see how useful this would be ..
Also, it's worth to note that in functions:
if you pass a string, the variable in the function itself is treated as a char pointer and most likely would try to modify it, and if it's readonly that would raise a Segmentation Fault. So functions are assuming you know what you're doing ..
if you want a function to be able to modify a string directly (i.e string = "somestring") then pass it a pointer to the actual string, else the modification will only be local to the function. That's because the string is a "pointer to char", so the function can't modify the string as a whole. But that also means that a function can modify the string's characters individually ( obviously, because it has a pointer for characters: the string ). If you pass it, however, a string pointer (char**), the function can modify the string directly (*string = "whatever") and can also modify the characters individually (*string[1] = 'C'). Which choice you need depends entirely on the purpose of the function ..
Now, for your specific example, you can do one of two ..
Using a pointer to a pointer to a char (string pointer)
void someFunc2(char** str)
{
*str = "Hello";
}
Using a pointer to char (string)
void someFunc2(char* str)
{
char *k = "Hello";
for(int i = 0; i < 5; ++i)
str[i] = k[i];
}
This is one of the most controversial and advanced topics in C. No matter what type of C programming you're doing, you have to understand these core concepts ..
in this program i am accessing a global char array through a function pointer,changing string values with address by address in char pointer makes difference in global char array , but when changing the string as whole string it does't make any difference in the global array
#include <stdio.h>
#include <string.h>
void function(char *string);
char str[20] = "Hello"; // global char array
int main()
{
function(str);
return 0;
}
void function(char *string)
{
int i;
printf("%s\n",string);
printf("%s\n", str);
for(i = 0;i < strlen(string);i++)
string[i] = 'a';
printf("%s\n",string);
printf("%s\n", str);
string = "jhony";
printf("%s\n",string);
printf("%s\n",str); // here is the doubt
}
output
Hello
Hello
aaaaa
aaaaa
jhony
aaaaa //how this supposed to print aaaaa even after we changed string into jhony
string = "jhony";
does not copy "jhony" to the memory pointed by string. Instead, it assigns address of "jhony" to string.
So after that, string points at "jhony" while str stays unchanged.
As #BrianCain commented, to copy "jhonny" to the memory addressed by string you may use
strcpy(string, "jhonny");
string and str are both different pointers pointing to the same thing. Using the array
notation is the same as dereferencing so you were actually manipulating the underlying data and because they were pointing to the same thing the change was noted in both places.
When you set the pointer equal to the literal, there wasn't any dereferencing or array notation. This changed what the pointer pointed to but the underlying data was not touched. And so the change was not noted by the other pointer.
Setting a pointer equal to something changes its value in the sense that the value of a pointer is an address. That address is a reference to whatever the pointer points to but now the pointer points to a new address. In your case, the string literal.
This is because string is a local variable. When you set string = jhony you aren't changing str. You are simply changing what string is pointing too. After this there are two string constants defined, "aaaaa" and "jhony", the aaaaa string is not overwritten. Str is also still "aaaaa" since it was not overwritten by the assignment of johnny to string.
string = "jhony";
this statement has changed the string's value which means the variable string not points to global array any more, it now points to the new const string "johny" which stored in the function's stack