simply accessing char array in a function by char pointer - c

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

Related

In this solution, if *inputString is a memory address (and the input is a char type) then does *inputString qualify as an array?

I was solving a challenge on CodeSignal in C. Even though the correct libraries where included, I couldn't use the strrev function in the IDE, so I looked up a similar solution and modified it to work. This is good. However, I don't understand the distinction between a literal string and an array. Reading all this online has left me a bit confused. If C stores all strings as an array with each character terminated by \0 (null terminated), how can there be any such thing as a literal string? Also if it is the case that strings are stored as an array, *would inputString store the address of the array or is it an array itself of all the individual characters stored.
Thanks in advance for any clarification provided!
Here is the original challenge, C:
Given the string, check if it is a palindrome.
bool solution(char * inputString) {
// The input will be character array type, storing a single character each terminated by \0 at each index
// * inputString is a pointer that stores the memory address of inputString. The memory address points to the user inputted string
// bonus: inputString is an array object starting at index 0
// The solution function is set up as a Boolean type ("1" is TRUE and the default "0" is FALSE)
int begin;
// The first element of the inputString array is at position 0, so is the 'counter'
int end = strlen(inputString) - 1;
// The last element is the length of the string minus 1 since the counter starts at 0 (not 1) by convention
while (end > begin) {
if (inputString[begin++] != inputString[end--]) {
return 0;
}
} return 1;
}
A string is also an array of symbols. I think that what you don't understand is the difference between a char pointer and a string. Let me explain in an example:
Imagine I have the following:
char str[20]="helloword";
str is the address of the first symbol of the array. In this case str is the address of h. Now try to printf the following:
printf("%c",str[0]);
You can see that it has printed the element of the addres that is 'h'.
If now I declare a char pointer, it will be poining to whatever char adress I want:
char *c_pointer = str+1;
Now print the element of c_pointer:
printf("%c",c_pointer[0]);
You can see that it will print 'e' as it is the element of the second adress of the original string str.
In addition, what printf("%s", string) does is to printf every elemet/symbol/char from the starting adress(string) to the end adress where its element is '\0'.
The linked question/answers in the comments pretty much cover this, but saying the same thing a slightly different way helps sometimes.
A string literal is a quoted string assigned to a char pointer. It is considered read only. That is, any attempts to modify it result in undefined behavior. I believe that most implementations put string literals in read-only memory. IMO, it's a shortcoming of C (fixed in C++) that a const char* type isn't required for assigning a string literal. Consider:
int main(void)
{
char* str = "hello";
}
str is a string literal. If you try to modify this like:
#include <string.h>
...
str[2] = 'f'; // BAD, undefined behavior
strcpy(str, "foo"); // BAD, undefined behavior
you're broken the rules. String literals are read only. In fact, you should get in the habit of assigning them to const char* types so the compiler can warn you if you try to do something stupid:
const char* str = "hello"; // now you should get some compiler help if you
// ever try to write to str
In memory, the string "hello" resides somewhere in memory, and str points to it:
str
|
|
+-------------------> "hello"
If you assign a string to an array, things are different:
int main(void)
{
char str2[] = "hello";
}
str2 is not read only, you are free to modify it as you want. Just take care not to exceed the buffer size:
#include <string.h>
...
str2[2] = 'f'; // this is OK
strcpy(str2, "foo"); // this is OK
strcpy(str2, "longer than hello"); // this is _not_ OK, we've overflowed the buffer
In memory, str2 is an array
str2 = { 'h', 'e', 'l', 'l', '0', '\0' }
and is present right there in automatic storage. It doesn't point to some string elsewhere in memory.
In most cases, str2 can be used as a char* because in C, in most contexts, an array will decay to a pointer to it's first element. So, you can pass str2 to a function with a char* argument. One instance where this is not true is with sizeof:
sizeof(str) // this is the size of pointer (either 4 or 8 depending on your
// architecture). If _does not matter_ how long the string that
// str points to is
sizeof(str2) // this is 6, string length plus the NUL terminator.

Is it applicable to pass pointer to character (after assigning string to it) to method and modify this string after without using array and why not?

I want to pass string to a c function using pointer to char and modify it and it gave me segmentation fault. I don't know why ?
Note*: I know I can pass the string to array of character will solve the problem
I tried to pass it to array of character and pass to function the name of array and it works , but I need to know what the problem of passing the pointer to character.
void convertToLowerCase(char* str){
int i=0;
while(str[i] != '\0')
{
if(str[i]>='A'&& str[i]<='Z'){
str[i]+=32;
}
i++;
}
}
int main(void){
char *str = "AHMEDROSHDY";
convertToLowerCase(str);
}
I expect the output str to be "ahmedroshdy", but the actual output segmentation fault
This (you had char str* which is a syntax error, fixed that):
char *str = "AHMEDROSHDY";
is a pointer to a string literal, thus it cannot be modified, since it is stored in read-only memory.
You modify it here str[i]+=32;, which is not allowed.
Use an array instead, as #xing suggested, i.e. char str[] = "AHMEDROSHDY";.
To be more precise:
char *str = "AHMEDROSHDY";
'str` is a pointer to the string literal. String literals in C are not modifacable
in the C standard:
The behavior is undefined in the following circumstances: ...
The program attempts to modify a string literal

Changing the value of a string with a pointer in C

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 )

Passing array of string pointers to function and reading value of the strings

I have an assignment where I am required to pass an array of string pointers to a function, assign strings and then read back these strings. Here is what I am doing:
void getStr(char *str[])
{
char temp[256];
strcpy (temp,"Apple");
*str = temp;
printf("\ngetStr Str= %s",*str);
str++;
strcpy (temp,"Mango");
*str = temp;
printf("\ngetStr Str= %s",*str);
str++;
}
int main()
{
char *str[2] ;
int i=0;
getStr (str);
for(i =0 ;i<2;i++)
printf("\nstr addr =%x, str= %s\n",&str[i],str[i]);
return 1 ;
}
Here is my output:
getStr Str= Apple
getStr Str= Mango
str addr =28d623b0, str=
str addr =28d623b8, str=
So str gets the strings assigned correctly in getStr(), but when I print them in main() it is blank. What am I doing wrong here?
You stored into str the address of the first element of the local variable temp (the array decayed into a pointer), but that array's lifetime ends once getStr() returns. Hence you are accessing a local variable after its lifetime ended, and undefined behavior results.
This sort question seems to be coming up constantly.
void getStr(char *str[])
{
char temp[256];
...
}
That temp array is a block of memory whose lifetime is tied to the duration of the getStr function.
Also, when you overwrite it from "Apple" to "Mango", then the pointer you had stored that used to point to temp in str[0] will point to "Mango". str[0] and str[1] hold the same pointer! And that pointer is no longer pointing to valid memory as soon as you return from the function. :-/
For these kinds of problems, C programmers use things like strdup. That does a memory allocation for each string and is a little bit more ergonomic than having to do strlen/malloc/strcpy. Either way, remember to free() each string when you're done with them.
This is very old post, but I must update it because I have similar problem, and I found out, that in side of function, I need use pointer only once, and array is restored like I am using this original from outside.
void getStr(char *str)
{
str[1] = (temp,"Apple");
str[2] = (temp,"Mango");
}
int main()
{
char str[2] ;
int i=0;
getStr (str);
for(i =0 ;i<2;i++)
printf(str[i]);
return 1 ;
}
That's why I hate use pointers, is to much mist-confusion and pointers it self are used in wrong way. They should be used only in special cases, like passing some arrays to function, to prevent making copy of this same twice. And Function it self don't need output set of values.
But that's is only in special case. Using pointers on each line in program don't have sense if compiler is doing it anyway, From what I learned, pointers was design only because there was to much problems with functions and passing big sort of data.

How does strcpy() copy a string to an array when you can't change the address of an array?

So basically strcpy assigns the address of the 2nd argument to the 1st, but how does it do it with an array as the first argument? like in my program, i tried changing the address of the array but unfortunately it wont compile. So I had to resort to making a character pointer variable to assign the return value of capitalize. Is there something I'm misunderstanding?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char string[20];
char *Capitalize(char *str)
{
int i;
char *temp;
temp = malloc(sizeof(char)*(int)(strlen(str)+1));
for(i = 0;i < strlen(str);i++)
{
if(*(str+i) >= 'a' && *(str+i)<= 'z')
*(temp+i) = *(str+i) - 32;
else
*(temp+i) = *(str+i);
}
*(temp+i) = '\0';
return temp;
}
int main(void)
{
string word;
printf("Enter word to capitalize: ");
scanf("%19s",word);
word = Capitalize(word);
printf("%s",word);
return 0;
}
strcpy() makes a copy, just like the name implies. it's perfectly legal to copy a string in to an array.
When you make an initialization of an array such as:
char myarr[] = "hello";
You're actually copying the characters into the array.
You seem to be confusing arrays with pointers (see here for some reason you can't treat them the same)
In C, qualifying an array by name without an indexer, is equivalent to specifying a pointer to the memory address of the first element in the array, that is why you can pass as a parameter an array to functions like strcpy.
char * strcpy ( char * destination, const char * source );
strcpy will copy whatever series of characters are found, starting at memory address specified by source, to the memory address specified by destination, until a null character (0) is found (this null character is also copied to the destination buffer).
The address values specified in the parameters are not modified, they just specify from where in memory to copy and where to. It is important that destination is pointing to a memory buffer (can be a char array or a block of memory requested via malloc) with enough capacity for the copied string to fit, otherwise a buffer underrun will occur (you will write characters past the end of your buffer) and your program might crash or behave in a weird way.
Hope I have been clear and not confused you more with my explanation ;)
The thing you seem to be missing is that in c/c++ strings ARE arrays, in most practical respects declaring
char c[] = "hello";
and
char* c = "hello";
is the same thing, all strcpy does is copy the characters into the destination memory, whether that memory is allocated as an array (presumably on the stack) or pointer (presumably on the heap);it does not make a difference.

Resources