Function not modyfing a character array - c

Im just starting to learn pointers and I'm trying to figure out why my code doesn't work. I get no compilation error yet the code doesn't what I want it to do. Why am I not passing the adress of an array? If I try to do so I get a compiilation error :(
#include <stdio.h>
void switch_name(char* name)
{
name= "testv2";
}
void main()
{
char *name1 = "test_name";
printf("%s\n", name1);
switch_name(name1);
printf("%s\n", name1);
}

Well because C is pass by value. You make changes to a local variable(name in function swicth_name()). To retain changes pass the address of the char* and assign the address of the string literal to the char* directly (By dereferencing the char**). For example this would work
#include <stdio.h>
void switch_name(char** name)
{
*name= "testv2";
}
int main(void)
{
char *name1 = "test_name";
printf("%s\n", name1);
switch_name(&name1);
printf("%s\n", name1);
return 0;
}
Here the function swicth_name got the address of the char* name1. Now when you dereference it using unary * in switch_name you assign the address of the string literal to the name variable of main(). That' swhy the change retains.

Function parameters are its local variables.
You can imagine the function call and its definition the following way
char *name1 = "test_name";
switch_name(name1);
//...
void switch_name( /* char* name */ )
{
char *name = name1;
name= "testv2";
}
As you can see the original variable name1 was not changed in the function. It is the variable name that is the parameter that was changed in the function.
You have to pass the original variable by reference if you are going to change it in the function.
For example
#include <stdio.h>
void switch_name( char ** name)
{
*name= "testv2";
}
int main( void )
{
char *name1 = "test_name";
printf("%s\n", name1);
switch_name( &name1 );
printf("%s\n", name1);
}
Compare the above program with the following program
#include <stdio.h>
#include <string.h>
void switch_name( char* name )
{
strcpy( name, "testv2" );
}
int main(void)
{
char s[] = "test_name";
char *name1 = s;
printf( "%s\n", name1 );
switch_name( name1 );
printf( "%s\n", name1 );
return 0;
}
In the first program you are going to reassign the original pointer itself using a function.
In the second program it is the data pointed to by the pointer that are reassigned using the standard C function strcpy.
Take into account that according to the C Standard the function main without parameters shall be declared like
int main( void )

Related

passing string to a pointer in c

I am fairly new in C. I want to assign string in a function to a pointer but I have no idea why it is not working?
This is the initial code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
void test(char* result) {
*result = "HELLO";
}
int main() {
char result[64];
test(result);
printf("%s", *result);
}
This is the error: warning: assignment makes integer from pointer without a cast. Since * result should store value and result is the address, shouldn't this work out?
Hello and welcome to C.
Your statement:
*result = "HELLO";
is the same as attempting to do the following:
result[0] = "HELLO"
which is attempting to set a single character to a string, and you can't do that.
you will need to copy the string character by character
luckily there is a function for that which you have included already with <string.h> called strcpy
strcpy(result,"HELLO")
This will work as long as your string to copy is fewer than 63 characters as you have defined in your main() function.
char result[64];
you should probably also send the length of the string to the test function and use strncpy
strncpy(result,"HELLO",length); // safe copy
and then terminate the string with '\0'
result[length-1] = 0;
your printf doesn't need to dereference the string pointer. So simply printf("%s",result); is fine.
so in summary:
void test(char* result,uint32_t len) {
strncpy(result,"HELLO",len); // safe copy (however "HELLO" will work for 64 length string fine)
result[len-1] = 0; // terminate the string
}
#define MY_STRING_LENGTH 64
int main() {
char result[MY_STRING_LENGTH ];
test(result,MY_STRING_LENGTH);
printf("%s",result); // remove *
}
You declared an array in main
char result[64];
Passed to the function it is converted to rvalue of the type char * that points to the first element of the array. The function deals with a copy of this pointer. Changing this copy of the pointer fors not influence on the original array.
Within the function the expression *result has the type char. So this assignment
*result = "HELLO";
does not make a sense.
In this call
printf("%s", *result);
there is again used an incorrect expression of the type char *result.
What you need is to use standard string function strcpy.
For example
#include <stdio.h>
#include <string.h>
void test(char* result) {
strcpy( result, "HELLO" );
}
int main( void ) {
char result[64];
test(result);
puts( result );
}
Problem:
When you store a character in a char varible,it puts the ASCII of the character in the memory.
char c='a';is the same aschar c=97;
You can verify this by using the code:
char c='a';
printf("%d",c);
So here is one way:
void test(char* result) {
*result++ = 'H';
*result++ = 'E';
*result++ = 'L';
*result++ = 'L';
*result = 'O';
}
int main() {
char result[64];
test(result);
printf("%s", result);
}
But it is redundant because there is a function called strcpy in <string.h>.
#include <stdio.h>
#include <string.h>
void test(char* result) {
strcpy( resul, "HELLO" );
}
int main() {
char result[64];
test(result);
puts( result );
}
Remove the '*' of the variable "result" after you've declared it and use the function "strcpy()" in your code.

Why isn't this function(char*) pass by ref?

Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void set(char* str){
str = malloc(10);
strcpy(str, "dog");
printf("\nstr = %s", str);
}
int main(){
char* s;
set(s);
printf("\n%s", s);
return 0;
}
Here's what I want to print out:
str = dog
dog
Here's what actuall gets printed out:
str = dog
(null)
Why is this? What I think I'm doing is passing an uninitalized pointer that then gets assigned a block of memory in set(), which then gets "dog" written into. What's actually going on?
There is no pass-by-reference in C. But pointers and indirection gives a facility to mimic that indirectly.
In your case, what is sent from main() to set() is the address in variable 's'. It
will have that value till malloc() statement executes. After that, str will have whatever address is returned by malloc().
When the same thing is expected in main, what should have been passed is the address
of 's' rather than what address it holds (like some of the examples above).
C is a pass-by-value language. There is no way to pass something by reference except explicitly. For your case that means expecting a pointer-to-a-pointer:
void set(char **str)
{
*str = malloc(10);
strcpy(*str, "dog");
printf("str = %s\n", *str);
}
And calling with the address of the pointer you want to 'fill in':
int main(void)
{
char *s;
set(&s);
printf("%s\n", s);
return 0;
}
Why isn't this function(char*) pass by ref?
C doesn’t have pass-by-reference. Everything is pass-by-value – it’s just that some values are also pointers to other values. Your uninitialized variable s is read when you call set(s) (which is undefined behaviour) in order to provide a value for its parameter str, then str = malloc(10) throws that value away to assign a new value to the local str.
You can pass a pointer to the pointer:
void set(char** str){
*str = malloc(10);
strcpy(*str, "dog");
printf("\nstr = %s", *str);
}
int main(){
char* s;
set(&s);
printf("\n%s", s);
return 0;
}
or return a pointer:
char* set(void) {
char* str = malloc(10);
strcpy(str, "dog");
printf("\nstr = %s", str);
return str;
}
int main(){
char* s = set();
printf("\n%s", s);
return 0;
}
You are passing an unasigned pointer to your set function, here a copy of the pointer is made and you use malloc on that copy. The original pointer in main is never updated with the new memory address.
To achieve what you want could be done this way:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void set(char** str){
*str = malloc(10);
strcpy(*str, "dog");
printf("\nstr = %s", *str);
}
int main(){
char* s;
set(&s);
printf("\n%s", s);
return 0;
}
I used a pointer to a pointer in set, and pass the memory address of the pointer s to it.

Make a function that reads (string) input

I'm new to programming and I have an assignment to make a function that reads a name. For some reason the following 'solution' does not work and the output is always something with weird chinese? characters. What went wrong?
#include <stdio.h>
#include <stdlib.h>
void input(char* a);
int main()
{
char name[8];
input(&name);
printf("%s", name);
return 0;
}
void input(char* a)
{
char buff[8];
scanf("%s", buff);
*a = buff;
}
I think the problem is in your
*a = buff;
statement because buff does not have a life outside of your function. so its memory will be lost.. so it is not safe to try and use buff in this way...
[ But as pointed out by #pablo what *a = buff; will do is copy the address of buff and put it into the memory allocated to a, which is really not what you want to do. ]
below should work and do include return from your function
#include <stdio.h>
#include <stdlib.h>
void input(char* a);
int main()
{
char name[8];
input(&name);
printf("%s", name);
return 0;
}
void input(char* a)
{
// char buff[8];
scanf("%s", a);
// *a = buff;
return;
}
one other point is to check if you are sure the name will only be 8 characters long... why not have it as 50 characters?
First off, you should pass the array to the function input() not its address. Secondly, replace scanf("%s", buff) with scanf("%s", a). This will store the string directly in the array you pass to the function.
So, the fixed code should look like:
#include <stdio.h>
#include <stdlib.h>
void input(char* a);
int main(void)
{
char name[8];
input(name);
printf("%s\n", name);
return 0;
}
void input(char* a)
{
scanf("%s", a);
}
The reason why your code doesn't work is that, you try to assign address of the local array buff to the first element of the array that you pass to the function. This shouldn't even compile or the compiler must issue a warning! If your compiler allows it to pass without any of these, that's a disaster.
Finally, the main function should be declared as int main(void) or int main(int argc, char **argv).
*a = buff; doesn't copy buff to a. Use strcpy() as
strcpy(a,buff);
complete code :
void input(char* a);
int main()
{
char name[8];
//input(&name);/** no need to pass & bcz name itself represents address */
input(name);
printf("[%s]", name);
return 0;
}
void input(char* a) {
char buff[8];
scanf("%s", buff);
//*a = buff; /* not valid **/
strcpy(a,buff);
}
This function is a problem:
void input(char* a)
{
char buff[8];
scanf("%s", buff);
*a = buff;
}
buff is local variable that is only valid while input() is running, so
returning this variable is wrong.
*a = buff; is also wrong. *a is the same as a[0], that means it is a
char. buff is an array of char, so you are assigning a pointer to an array
of char to a char variable. That doesn't sound right, it's putting apples in
the oranges box. In fact what is happening is that you are assigning the address
pointed to by buff in the memory pointed to by a.
Your compiler should have warned you about that, don't ignore the
compiler warnings, they are there to help you, not annoy you,
void input(char *a)
{
scanf("%s", a);
}
would be the correct function.
Doing
char name[8];
input(&name);
is wrong, even though the address of name and &name will be the same, but
they will have different types. name decays into a pointer, so it is a
char*. However &name is a pointer to an array of char, a different type.
The compiler should give you a warning like this:
warning: passing argument 1 of bar from incompatible pointer type
note: expected char * but argument is of type char (*)[8]
The correct call is:
input(name);
In general there is one big problem, though: You only declare 8 spaces for the
buffer. If the name is longer than 7 characters, you will have a buffer
overflow. Instead of using scanf I recommend using fgets instead, because
here you have much more control of the input and the memory boundaries.
char name[30];
fgets(name, sizeof(name), stdin);
name[strcspn(name, "\n")] = 0; // removing possible newline
scanf is not always easy to use. A name can be long and have spaces in it.
Specially for a beginner, this can be tricky. fgets is easier to use.
You don't need to pass the address of name since it's a char array. And when you do the copy in input(), you should use strcpy. The following code works:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void input(char* a);
int main()
{
char name[8];
input(name);
printf("%s", name);
return 0;
}
void input(char* a)
{
char buff[8];
scanf("%s", buff);
strcpy(a, buff);
}

Return the address of a global string variable

How do I return the address of a global char* variable? I have to do this for a project. I have to write the function based on pseudo code which looks like this:
string* get_variable_address();
C doesn't have string so I assume string* will become char**. I've tried many things but I can't get it to work. What I have looks something like this:
#include <stdio.h>
char test[100] = "Get my address";
int main(void) {
char** address = return_variable_address();
printf("The address is: %s\n", *address);
return 0;
}
char** return_variable_address() {
return &test;
}
C doesn't have string so I assume string* will become char**
Probably not. A string in a C is a character array, which you can access through a char*. Therefore you can simplify your program quite a bit to get the desired result:
#include <stdio.h>
char* return_variable_address (void);
char test[100] = "Get my address";
int main(void) {
char* address = return_variable_address();
printf("The content stored at the address: %s\n", address);
return 0;
}
char* return_variable_address (void) {
return test;
}
Please note that all of this is bad practice - avoid global variables.
Keeping your following requirements in mind -
You want to return a char** where one deferencing once gives you the string "Get my address"
You want the string to be mutable.
So you can do
char test[100] = "Get my address";
char *pointer = test;
char** return_variable_address(void) {
return &pointer;
}
int main(void) {
char** address = return_variable_address();
printf("The address is: %s\n", *address);
(*address)[0] = 'F'; //Test for mutability
printf("The address is: %s\n", *address);
return 0;
}
I understand that these requirements are for some security testing and hence are so peculiar.
Demo here: Ideone
It might help you to typedef a definition of string. Then it is easy to see that the address of a string variable s is just &s as for any other address. I expect that string is used a lot through the project and the typedef will also save you from trying to change every string to char*.
To print an address use the format flag %p.
#include <stdio.h>
typedef char string[10]; // string defined as an arrary of 10 chars
string s = "Hello world"; // I've deliberately put a common error in here
string* return_variable_address( void )
{
return &s;
}
int main( void )
{
printf("Address of global var s = %p \n", return_variable_address() );
return 0;
}

change string to point to next character in function

#include <stdio.h>
void change(char *str)
{
(*str++);
return;
}
int main()
{
char *str = "ABC";
printf("before change %s \n",str);
change(str);
printf("after change %s \n",str);
return 0;
}
Output of the program is
ABC
ABC
I want output to be
ABC
BC
I don't want to return string, str needs to be modified in change function; return type of change function should remain void. I don't know how to do this.
I did try to google it but i didn't find the solution.
In C if you want to change the value of an argument to a function, you need to take that argument by pointer. And since here you are trying to change a pointer, it needs to be a pointer to a pointer:
void change(char **str)
{
(*str)++;
}
Then:
change(&str);
The expression (*str++); increments a local copy of str, not str from main. This is because C uses pass-by-value technique for function parameters.
You need to change your function to take a pointer to pointer, and pass a pointer to str in order to achieve the desired effect.
As we are in C would you need a pointer to a pointer.
I.e
void change(char **str)
{
*str = *str + 1;
}
Then
int main()
{
char *str = "ABC";
printf("before change %s \n",str);
change(&str);
printf("after change %s \n",str);
return 0;
}
See https://ideone.com/Ouo19v

Resources