Returning result via pointer to array - c

I want to return the result of a function through the pointer *address, given as parameter. My code below prints this output:
Result:
But I was expecting:
Result: 123456
Why isn't it working as expected?
#include <stdio.h>
static void get_address(char *address) {
address = "123456";
}
int main(int argc, const char * argv[]) {
char address[34];
get_address(address);
printf("Result: %s\n",address);
return 0;
}

'address' in get_address gets a copy of the address of the start of the array address in main(). get_address changes that local pointer to the address of the local string "123456" and then does nothing with it.
What you meant to do is probably the following:
#define DEST_BUFFER_SIZE 34
static void get_address(char* address) {
const char str[] = "123456";
strcpy_s(address, DEST_BUFFER_SIZE, str);
}
int main(int argc, const char * argv[]) {
char address[DEST_BUFFER_SIZE];
get_address(address);
printf("Result: %s\n", address);
return 0;
}
Here strcpy_s is the safe version of strcpy and is used to copy the contents of the local str char-array to the memory location specified by address in get_address.

#include <stdio.h>
static void get_address(char *address) {
//Attention here
// use the reference operator
// (in your code you were affecting to the address of the variable not it's content)
*address = "123456";
}

Related

Change pointer of pointer in C

I'm trying to write a void function that gets a pointer to a pointer of a string (char**) as a parameter, and changes the original char* so it pointed to another string, lets say "hello".
Below is the code I've written:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void change_ptr(char **str_ptr)
{
char hello[] = "hello";
char *hello_ptr = hello;
*str_ptr = hello_ptr;
}
int main()
{
char str[] = "yay";
char *str_ptr = str;
char **ptr_to_str_ptr = &str_ptr;
change_ptr(ptr_to_str_ptr);
printf("%s\n", str);
return 0;
}
As you can see, Im getting the pointer to the pointer of the char* "yay", delivering it to the function, and in the function I'm getting the pointer to "hello", and changes *str_ptr (which is the pointer to the original string) to the pointer to hello. But when I print str at the end, it prints "yay".
What am I doing wrong?
(when I debug with printing the addresses, everything seems fine.)
This works:
#include <stdio.h>
void change_ptr(const char ** str_ptr)
{
*str_ptr = "hello";
}
int main()
{
char str[] = "yay";
const char * str_ptr = str;
const char ** ptr_to_str_ptr = &str_ptr;
change_ptr(ptr_to_str_ptr);
printf("%s\n", str_ptr);
}
Note that the string "hello" in this example is read-only because it is a string literal. I added const in a few places so you are reminded of this and the compiler will warn you if you try to write to the string. The pointer str_ptr can be modified, but not the string itself.

In C, how to set an unsigned char array from argv

In the code below, I would like to have the value of myvar be provided by a program argument.
#include <stdio.h>
int main(int argc, const char **argv)
{
const unsigned char myvar[] = "myvalue";
return 0;
}
How would I get myvar to contain the value of the string from argv[1]?
If you are only reading, then you can simply copy the address of argv[1] like this:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char **argv) {
const unsigned char *myvar = NULL;
// Be sure to check argc first
if (argc < 2) {
fprintf(stderr, "Not enough arguments.\n");
return EXIT_FAILURE;
}
myvar = (const unsigned char *)argv[1];
printf("myvar = %s\n", myvar);
}
If you want to change myvar then you should copy the string with strncpy or alike.
An array cannot be initialized by a pointer or by another array. You can only initialize it with an initializer list or (in the char of a char array) a string constant.
What you can do it copy the contents of another string with strcpy. And since you'll be using this array as a parameter to an encryption function, it will probably need to be a fixed size.
char myvar[8] = { 0 }; // initialize all values to 0
strncpy(myvar, argv[1], 8); // copy the first 8 bytes

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;
}

Return memory address as out parameter in function

I need to store the memory address of a string in an int pointer out parameter. I've created the code below to test the implementation.
void getMemAddress (int *a) {
char str[80] = "Hello world";
a = (int*)&str; // Assign memory address of str to a
printf("%s", (char*)a);
}
int main(int argc, const char * argv[]) {
int *memaddress;
getMemAddress(memaddress);
printf("%s", (char*)memaddress);
return 0;
}
printf("%s", (char*)a);
prints "Hello World" as it should but
printf("%s", (char*)memaddress);
prints null
How could I go about retrieving the actual memory address as using it to access the original string?
Thanks!
Parameters are passed by value in C. Similar issues have been answered countless times on stackoverflow.
You need this:
void getMemAddress (int **a) {
char str[80] = "Hello world";
*a = (int*)str; // Assign memory address of str to *a
printf("%s", (char*)*a);
}
int main(int argc, const char * argv[]) {
int *memaddress;
getMemAddress(&memaddress);
printf("%s", memaddress);
return 0;
}
Casting a memory address to int won't work on a 64 bit system. On a 32 bit system it works, but it's not very clean.
Other problem. You are returning the address of a local variable that is on the stack. As soon as you leave the getMemAddress function the str buffer will be overwritten by following function calls (also a classic problem). Never return the address of a local variable.
You are assining the address of &str to your function-local copy of the pointer a. What you need is to modify getMemAddress so that it takes int **a as an argument, and assign it like this:
*a = (int *) str;
then in main:
int *memaddress;
getMemAddress(&memaddress);
And one more thing-- str only exists inside your function. Once you exit the function, you won't be able to access it. To fix this, make str a char pointer and use malloc to allocate some memory for it. Then use strcpy to insert your string.
To modify something in a function, you need to pass a pointer to the thing you want to modify.
In this case you want to modify a pointer, so you need to pass a pointer to the pointer.
void getMemAddress (int **a) { // <-------------- added a *
char str[80] = "Hello world";
*a = (int*)str; // <-------------- added a *
printf("%s", (char*)*a); // <-------------- added a *
}
int main(int argc, const char * argv[]) {
int *memaddress;
getMemAddress(&memaddress); // <-------------- added a &
printf("%s", (char*)memaddress);
return 0;
}
Also, &str should be &str[0] or just str.
Also, str is a local variable, so it will cease to exist once getMemAddress returns (and then the printf call in main will probably print garbage). You could make str static, or you could return a pointer to a string literal instead (char *str = "Hello world"; *a = (int*)str;).

Passing char * vs char ** as parameters to a function in C

I've read several discussions of passing char * in C.
stackoverflow: passing-an-array-of-strings-as-parameter-to-a-function-in-c
stackoverflow: how-does-an-array-of-pointers-to-pointers-work
stackoverflow: whats-your-favorite-programmer-ignorance-pet-peeve
drexel.edu: Character arrays
Many of them include discussions of arrays, but I want to stay away from that.
I'm writing a sample program to teach myself about the passing of char * and char ** in C. This is an exercise in passing char *, without using (pointers to) arrays. Also no concerns for execution efficiency. :-)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void get_args_works(int, char **, char **);
void get_args_broken(int, char **, char *);
char *get_string(int, char **);
int main(int argc, char **argv)
{
char *string_works;
char *string_broken;
get_args_works(argc, argv, &string_works);
get_args_broken(argc, argv, string_broken);
printf("in main string_works (%p) = %s\n",string_works,string_works);
free(string_works);
printf("in main string_broken (%p) = %s\n",string_broken,string_broken);
free(string_broken);
}
void get_args_works(int argc, char **argv, char **string)
{
*string = get_string(argc, argv);
printf("in get_args_works %p string %s\n",*string,*string);
}
void get_args_broken(int argc, char **argv, char *string)
{
string = get_string(argc, argv);
printf("in get_args_broken %p string %s\n",string,string);
}
char * get_string(int argc, char **argv)
{
int i;
char *string;
string = malloc(40);
// placeholder in case -s switch not found below
strcpy(string,"-s switch not found below");
for(i = 0; i < argc; i++)
{
if(argv[i][0] == '-')
{
switch(argv[i][1])
{
case 's':
// release above malloc(40) for "-s switch not found below"
free(string);
// make room for storing variable
string = malloc(strlen(argv[++i]) + 1);
// the argv just after -s
strcpy (string,argv[i]);
break;
}
}
}
return string;
}
You can also view the same code on github
The above code is somewhat self documenting. main() declares two char * variables, and passes them as parameters to their respective get_args() functions.
Each get_args() function calls char * get_string(int, char **), using the exact same call (but different way to collect the return value).
get_string() works fine; it does a malloc() and returns the pointer back to the calling function. That code works, and each get_args() function receives the return value as I expect.
But then, when the get_args() functions return to main(), why does the dereferenced pointer value get back to main (from get_args_works(), but not the pointer's value (from get_args_broken())?
(i.e. I can see that if I dereference the pointer (&string_works) when sending as a parameter, it works. But why? Isn't char * string_broken already a pointer? Why does it need the "extra" dereference when sending as a parameter?)
I'm hoping for a winning answer that explains how you (yes, you) conceptualize sending char * as a parameter vs receiving it as the function's return value.
int get_args_broken(int argc, char **argv, char *string)
{
string = get_string(argc, argv);
printf("in get_args_broken %p string %s\n",string,string);
}
You're only modifying the string local (automatic) variable. That's not visible to the caller in any way. Note that this means you're freeing a wild pointer in main.
It's wrong for the same reason:
int get_sum(int sum, int a, int b)
{
sum = a + b;
}
is; the parameter is copied by value. Also, you're not returning an int (as you declared you would).
int get_args_works(int argc, char **argv, char **string)
{
*string = get_string(argc, argv);
printf("in get_args_works %p string %s\n",*string,*string);
}
is correct (except the missing return). You're not modifying string, which would be pointless. You're modifying the object at the location in string, which in this case is a char *.
EDIT: You would need to triple * the argv if there was a function calling main, and you wanted to set that function's variable to a different char **. E.G.
void trip_main(int *argc, char ***argv)
{
*argc = 10;
*argv = malloc(*argc * sizeof(char *));
}
void caller()
{
char **argv;
int argc;
trip_main(&argc, &argv);
}
One of the needs to use Pointer to a pointer (here get_args_works()) is to modify (or return) more than on variable from a function, as in C it's not possible to return more than one variable.
get_args_works() works 'coz, you are passing pointer to a pointer & a reference to it is there in your main().
But in get_args_broken() you are passing just a pointer. Nothing wrong here, now you do malloc() & return back the memory allocated string to get_args_broken(), still nothing wrong here. But now, this mem allocated string is local & main() does not have a reference to this var. So when you dereference char *string_broken; in main() it might cause undefined behavior.
Hope this's clear.

Resources