'''
void calling (char *str)
{
str = NULL;
}
int main()
{
char str2[20];
calling(str2);
if(str2 == NULL)
{
printf("null");
}
return 0;
}
'''
Just wondering why did the printf not run.Can I not change the char-array pointer to NULL once its declared.
Why does the char pointer not get updated to NULL
Incorrect conclusion. Inside calling(char *str), the pointer str did get updated to NULL.
Just wondering why did the printf not run.
Because &str2[0] is not NULL.
str2 is an array, not a pointer. With str2 == NULL, str2 is converted to the type and value of the address of the first array element. The address of the first array element (&str2[0]) is not NULL.
char str2[20];
...
if(str2 == NULL)
{
printf("null");
}
Can I not change the char-array pointer to NULL once its declared.
"char-array pointer" is unclear.
Array str2 in char str2[20]; cannot change to NULL. An array's address never changes.
Pointer str in char *str ... str = NULL; can get assigned to NULL.
calling(str2); converts array str2 to the type and value of the address of the first array element, just as if is was calling(&str2[0]); and passes that pointer to calling().
void calling(char *str) receives a copy of that pointer. As calling() changes that pointer copy str within itself, it does not affect the address of the calling code's str2.
Remember: an array is not a pointer. A pointer is not an array.
For starters you have an array
char str2[20];
that is str2 is not a pointer it is an array. Arrays are non-modifiable lvalues. You can not assign one array to another array like for example
char str1[20];
char str2[20];
str1 = str2;
In this function call
calling(str2);
the array designator str2 is implicitly converted to pointer to the first element of the array and represents an rvalue. You can imagine the function definition and its call the following way
calling(str2);
//...
void calling ( /*char *str*/)
{
char *str = str2;
str = NULL;
}
As you can see the function deals with a copy of the value of an expression that yields the value of the address of the first element of the array str2.
Within the function it is the local variable (pointer) str that is changed. The original array str2 declared in main stays unchanged.
Even if you will pass the array by reference you will be unable to change it. For example this program will not compile
#include <stdio.h>
void calling (char ( *str )[20] )
{
*str = NULL;
}
int main()
{
char str2[20];
calling( &str2 );
if(str2 == NULL)
{
printf("null");
}
return 0;
}
because in this statement
*str = NULL;
you are trying to assign a pointer to an array.
There are many issues in the code:
char* calling (char *str)
{
str = NULL;
return str;
}
You change the local copy of str which is not visible to the caller.
You could just have a plain return NULL; have the same effect.
int main()
{
char str2[20];
calling(str2);
As mentioned above, the parameter to the function is not affected outside of the function.
You also do not do anything with the return value. The NULL value is just discarded.
Also there is no pointer existing in main at all that could be updaed.
You have an array. Arrays are not pointers, pointers are not arrays.
You can never assign a value to the array variable as it represents the location in memory where the array members are stored.
As mentioned in comments you should get hands on y good book to learn C.
Especially chapters about arrays, pointers and passing data into and out of functions should be relevant for you.
Related
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 )
I am getting a pointer to a string passed as an argument to the function, and I need to change a few characters in the string. I'm copying the string to a char array and editing what I need to just fine, but I need to change the original string that is being pointed to into the new char[] I just created.
The function has to return void, and because the pointer being passed is just a copy of the one from main, setting it to point to the new char[] won't do anything as it will just be deleted when the function ends, so I need to actually change the string being pointed to.
*str = &newstr[0]
This is giving me the compiler error: assignment makes integer from pointer without a cast.
*str = newstr
And this is segfaulting when I run the program.
Here is the full function:
void replace(char* str, char toReplace, char replaceWith) {
int strLen = strlen(src);
char newstr[strLen];
int i;
for (i = 0; i < strLen; i++) {
if (str[i] == toReplace)
newstr[i] = replaceWith;
else
newstr[i] = str[i];
}
// How to change the value of the string being pointed to by *str to now be newstr?
}
After digesting all the comments on your question, I've come to the understanding that you're trying to invoke your function in the following manner:
char * str = "string literal"; /* compiler should have warned you about assigning
string literal to non-const pointer. */
replace( str, 'i', 'u' );
printf( "%s\n", str );
Now, the problem with that is any attempts to modify the memory that str points to will be undefined behaviour.
Your attempt at a solution was to try to change the actual pointer inside the function. But to do so, your replace function would need to accept a char**, and then allocate new memory. That's not a nice approach in this case. You really just need to modify the string in-place:
void replace(char* str, char toReplace, char replaceWith)
{
while( *str )
{
if( *str == toReplace ) *str = replaceWith;
str++;
}
}
And how to deal with the string literal? Well, the solution is simple. Make an array:
char str[] = "string literal";
replace( str, 'i', 'u' );
printf( "%s\n", str );
How to change the value of the string being pointed to by *str to now
be newstr?
You can't due to (1) the way you pass str to the function as char *s and (2) because you declare newstr as a local variable in replace. (and probably for a whole host of other reasons that are not ascertainable from the limited section of code you posted)
When you pass a pointer to a function, the function receives a copy of the pointer with it very own and very different memory address. In other words when you declare the parameter char *str in your function parameter list, that creates a new pointer. (it still points to whatever is passed in str, but its variable address is very different from the original pointer address in the calling function - so nothing you do to the address of str will ever be reflected in the calling function.) If you want to assign a new address to a pointer in a function, you must pass the original address from the caller. e.g.
void replace(char **str, char toReplace, char replaceWith)
and then in your calling routine call it with:
replace (&origPtr, char toReplace, char replaceWith)
(as a style aside: don't use CamelCase variables in C, camelcase is proper)
Finally, since the address for newstr will be destroyed when you exit function replace, your only option for assigning the address of newstr to *str is to (1) declare newstr as static, or (2) dynamically allocate newstr (e.g. char *newstr = malloc (sizeof *newstr * strLen + 1);. Then you can assign the value of newstr to str. e.g.:
void replace(char **str, char toReplace, char replaceWith) {
int strLen = strlen(*str);
int i;
char *newstr = malloc (sizeof *newstr * strLen + 1);
if (!newstr) {
fprintf (stderr, "error: virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
for (i = 0; i < strLen; i++) {
if ((*str)[i] == toReplace)
newstr[i] = replaceWith;
else
newstr[i] = (*str)[i];
}
newstr[strLen] = 0; /* nul-terminate (or use calloc to allocate) */
free (*str); /* MUST have been dynamically allocated in caller */
*str = newstr;
}
(note: str must not have been statically declared in the calling function, and you must free the block of memory it points to or you will create a memory leak by overwriting the starting address to the block of memory it originally pointed to -- making it impossible to free the original block.)
All of these reasons are reasons why it is better to approach this problem by either changing the toReplace and replaceWith characters in place (presuming it str was an array and not a string-literal), or passing an additional array to fill with the replacement as a parameter (or as a pointer to allocate -- or return a pointer to a newly allocated block of memory containing the new string).
Let me know if you have further questions.
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 ..
If I want to return an empty char*, I can do this
char* Fun1(void) {
return "";
}
Now imagine the same problem with char**, I want to return an empty array of char*.
Is there a shorter way to write this without using a temporary variable ?
char** Fun2(void) {
char* temp[1] = {""};
return temp;
// return {""}; // syntax error !
}
The goal is to hide the fact that the string can be a NULL pointer.
The equivalent to what you did with the string literal would be something like this:
char const* const* Fun2(void) {
static char const* const tmp[] = {""};
return tmp;
}
But as I said in a comment to the question, you might need to re-think what "empty" means.
You also need to consider what you're going to do if there are cases where the return isn't empty. If the caller is supposed to free the returned pointer, then returning pointers to string literals and/or static arrays is out.
Don't use a temporary variable, as it will be out of scope on return. If you have multiple functions that return the same empty array, they can return pointers to the same 'empty array'.
char* EmptyArray[1] = {""};
char** Fun2(void)
{
return EmptyArray;
}
Also, this makes it easy to detect if the function specifically returned emptiness, by comparing pointers:-
char **arr = Fun2();
if (arr == EmptyArray)
...
Firstly, it is not a good idea to return pointers from functions that have just been allocated. The problem is that the user then has to free that memory, and so you are forcing them to use the same memory management function as you are.
With that in mind, you want to allocate 2 bits of memory here: one for the pointer to a character and another for the character itself.
char** p = malloc(sizeof(*p));
*p = malloc(sizeof(**p));
**p = '\0';
return p;
And then remember the user then has to do:
free(*p);
free(p);
But I will say again, what you are doing is not good programming. You are better off writing functions that accept a null pointer.
the {""} only can be used to initial the variable at its definition. but not as an expression, that is, you can't use it like
char* temp[1];
temp = {""}; // invalid
The first case is fine, a string literal such as "" is safe to return from a function. For the second case, where you need an array of length 1 that contains a pointer to an empty string, you could do some trickery:
char ** array_empty_if_null(const char **array)
{
static char *empty[] = { "" };
return (array == NULL || array[0] == NULL) ? empty : array;
}
I think this matches your description of what you need.
Can't you just return null, because null is empty pointer?
this doesn't work:
void function(char* var)
{
var = (char*) malloc (100);
}
int main()
{
char* str;
function(str);
strcpy(str, "some random string");
printf("%s\n", str);
return 0;
}
this does:
void function(char* var)
{
//var = (char*) malloc (100);
}
int main()
{
char* str;
//function(str);
str = (char*) malloc (100);
strcpy(str, "some random string");
printf("%s\n", str);
return 0;
}
Why?
You have to pass the address of the pointer to assign the address you want inside the function, otherwise you are just passing a copy of it:
void function(char** var)
{
*var = malloc (100);
}
int main()
{
char* str;
function(&str);
strcpy(str, "some random string");
printf("%s\n", str);
return 0;
}
You need to use a pointer to pointer as a parameter for that, char **.
When you pass a pointer as a parameter, it gets copied, so what you get inside the function is just another pointer pointing to the same place.
You need to receive a char ** and do:
my_alloc_fun(void **ptr){
*ptr= malloc(size);
}
void *myptr;
my_alloc_fun(&myptr);
This way, you get the address of the pointer inside the function, so that you can make the original pointer to point to the newly allocated memory.
When you call function(str), you are passing the value of str to function. This value is some uninitialized garbage value because you haven't set it to anything in main, but that's not the problem.
The problem is that function has its own pointer, var, into which it puts that garbage value so that one could say var points to the same thing (garbage) that str points to. However, they are not the same variable. They are two distinct variables, and changing var has no effect on str.
When you say var = (char*) malloc (100);, you are allocating memory somewhere and then telling var to point to it. Now var points to a different location than str. Immediately you return from that function, losing var and the location of that memory. This by the way is a memory leak.
When you return back to main, str is as it ever was - pointing to garbage.
A numerical example:
char *str; // str -> 0xfeedface (garbage)
function(str);
// inside 'function', an initialization like this occurs
char *var = str; // var -> 0xfeedface (same garbage)
var = (char*) malloc (100); // var -> 0x12341234 (alloc'd memory)
return;
// back in 'main'
strcpy(str, "some random string"); // str still points to 0xfeedface!
To do this properly, you need to change strs value. This means function needs a pointer to str, or a pointer to a pointer.
void function(char **var)
{
*var = (char*)malloc(sizeof(char) * 100);
}
int main()
{
char *str;
function(&str);
strncpy(str, "some random string", 99);
...
free(str); // important in general
}
Pointers are just like any other variable; the difference is only in what their value represents. Whereas a double has a value that represents a double-precision floating point number, and an int has a value that represents a signed integer, a pointer has a value that represents the location of another variable.
Pointers themselves are still passed by-value to other functions; so your example doesn't work for exactly the same reason that this analagous function doesn't work:
void function(int var)
{
var = 100;
}
int main()
{
int num;
function(num);
printf("%d\n", num);
return 0;
}
The answer in both cases is the same: When function() changes the value of the parameter var, it is changing only its local copy of that - it isn't changing the variable within main().
See my answer to C Programming: malloc() inside another function for an explanation about how to think about this.