c function pointer return value - c

So I was having some fun with c when I tried this:
#include <stdio.h>
#include <string.h>
typedef void (*Function)(char *);
void helloWorld(char *);
void execute(Function, char *);
Function func;
int main(void){
char *message = "StackOverflow";
execute(helloWorld, message);
printf("%s", message);
return 0;
}
void helloWorld(char *message){
printf("HelloWorld, %s.\n", message);
message = "DONE";
printf("[%s]\n", message);
}
void execute(Function function, char * msg){
func = function;
func(msg);
}
Apparently I am not able to use pointers - which I used as parameter - as return value of pointer functions.
Well, can someone explain this behavior? How can I get return value(s) of void function?

So I found a solution while writing the question.
Apparently char pointers are not actually pointers, somehow. When I realised this it tried using pointer to pointer (**) instead and it worked.
#include <stdio.h>
#include <string.h>
typedef void (*Function)(char **);
void helloWorld(char **);
void execute(Function, char **);
Function func;
int main(void){
char *message = "StackOverflow";
execute(helloWorld, &message);
printf("%s\n", message);
return 0;
}
void helloWorld(char **message){
printf("HelloWorld, %s.\n", *message);
*message = "DONE";
printf("[%s]\n", *message);
}
void execute(Function function, char ** msg){
func = function;
func(msg);
}

In your original code:
void helloWorld(char *message){
printf("HelloWorld, %s.\n", message);
message = "DONE";
printf("[%s]\n", message);
}
the line message = "DONE"; will change the local (or "automatic") variable named message, because function parameters are, for all intents and purposes, local variables in C.
Thus, the value of the message local variable from main will not change, as those are two different variables.
Now, in your second example, you are passing pointers to pointers:
void helloWorld(char **message){
printf("HelloWorld, %s.\n", *message);
*message = "DONE";
printf("[%s]\n", *message);
}
So, your *message = "DONE"; is now changing what the message (parameter) points to, and it is pointing to the message from main(), thus it is changing message from main(). The message from helloWorld() itself is not changed here.
Of course, there is nothing special about character pointers w.r.t other pointers, they are pointers as much as any other. The only special thing is treating string literals as character pointers, but that doesn't matter here.

Related

How do I keep information in struct after returning from function?

So I am still a little confused about pointers in connection with structs.
I have a struct which represents a queue. The queue contains an array of queue elements (containers).
I now want to access these containers in order to assign values to them. This code is only for containers[0] to keep it simple.
How can I access the string at containers[0] in main after returning from writeContainer() function?
The signature of writeContainer() is given, so I can't change that.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct qElement {
char array[55];
int len;
} container;
typedef struct queue {
container containers[5];
int id;
} myq;
int writeContainer(myq anyq, void *buf, int buflen);
int main(void) {
myq *testq = malloc(sizeof(myq));
char *mainArray = "hello";
writeContainer(*testq, mainArray, 6);
printf("outside Array[0]: %s\n", testq->containers[0].array);
return EXIT_SUCCESS;
}
int writeContainer(myq anyq, void *buf, int buflen) {
container *elem = malloc(sizeof(container));
// into temp elemnt
elem->len = buflen;
memcpy(&elem->array, buf, buflen);
// into actual queue
memcpy(&anyq.containers[0], elem, buflen);
printf("qArray[0]: %s\n", &anyq.containers[0].array);
printf("exiting function\n");
free(elem);
return buflen;
}
so the output is:
qArray[0]: hello
exiting function
outside Array[0]:
but I expected:
qArray[0]: hello
exiting function
outside Array[0]: hello
Thanks in advance
With this prototype for writeContainer:
int writeContainer(myq anyq, void *buf, int buflen);
and the posted definition of myq, writeContainer cannot be written to have a side effect on the queue passed from main() because it is passed by value. The prototype is inconsistent on another aspect: if data from buf is only supposed to be read and copied to the container(s), this pointer should be declared as const void *buf and its size should be passed as a size_t buflen.
There is a * missing, either in the prototype or in the typedef for myq.

How to return a string from a function to main()?

I have tried the following code but am getting an error:conflicting types for fun.Is there any solution that doesn't require the use of malloc.
#include <stdio.h>
int main()
{
printf("%s",fun());
return 0;
}
char* fun()
{
static char str[]="Hello";
return str;
}
It is because you have not declared prototype for fun.
#include <stdio.h>
char* fun(void);
int main()
{
printf("%s",fun());
return 0;
}
char* fun(void)
{
static char str[]="Hello";
return str;
}
C does not allow an array to be returned from a function, but it does allow a struct to be returned from a function. You can define a struct type to hold strings in an array, and return such a struct from your function to be copied into a receiving struct:
#include <stdio.h>
struct String
{
char body[1024];
};
struct String fun(void);
int main(void)
{
struct String my_string = fun();
printf("%s\n", my_string.body);
return 0;
}
struct String fun(void)
{
return (struct String){ .body = "Hello" };
}
char* fun()
{
static char str[]="Hello";
return str;
}
str hold base address of your string. (Assume 1000). Now when you return str, it'll return only base address.
printf("%s",fun());
Here you want to print string so you gave %s but this fun return base address of your character array(string) but not string (as you assume).
First, you need to dereference your fun() in printf so that it'll give first character of string array as str gave base address which points to first character of your string.
Also, you need to give formatter as %c so that it'll give H.
Now to print whole string, you need to increment what's inside your char pointer.
See below Code:
#include <stdio.h>
char* fun();
int main()
{
int i;
for(i=0;i<6;i++){
printf("%c",*(fun()+i));
}
return 0;
}
char* fun()
{
static char str[]="Hello";
return str;
}
Here you can see that I dereference fun() first to print the first character and then I made a for loop so that I can use loop variable i to increment what's inside in pointer returned by fun().
Try and let me know if you face any problem here.

strcpy() and char

I want to store a string to a char array inside a structure and when I access the char array I want the result to be displayed along with the value from the global variable errCode. When I access the errDesc member of the structure then I want the result to be "Error detected with error code 0xA0B0C0D0", but since using strcpy copies the string as it is I am getting a result "Error detected with error code %08lx" . Here is a sample code which replicates my issue:
int errCode = 0xA0B0C0D0;
void function(errpacket* ptr, int a, char* errString, ...);
typedef struct{
int err;
char errDesc;
}errpacket;
int main(){
errpacket* a;
void function(a, 10, "Error detected with error code %08lx", errCode);
return 0;
}
void function(errpacket* ptr, int a, char* errString, ...){
ptr->err = a;
strcpy(&ptr->errDesc, errString);
}
If my implementation is incorrect, please suggest me a way to do what I intend to. Also please point out the mistakes in the above code.
you have to typedef the struct errpacket before declaration of function(...)
Variable a in function main() is only a pointer. You'll get a segmentation fault inside function if you try to write to an uninitialized pointer.
The member errDesc will only hold ONE char, not a string or char array.
Try this...
int errCode = 0xA0B0C0D0;
typedef struct {
int err;
char* errDesc;
} errpacket;
void function (errpacket* ptr, int a, char* errString, ...);
int main () {
errpacket a;
function(&a, 10, "Error detected with error code %08lx", errCode);
return 0;
}
void function (errpacket* ptr, int a, char* errString, ...) {
ptr->err = a;
ptr->errDesc = strdup( errString);
}
try this fix:
#include <stdarg.h> //to be added for vsprintf use
int errCode = 0xA0B0C0D0;
void function(errpacket* ptr, int a, char* errString, ...);
typedef struct{
int err;
char *errDesc;
}errpacket;
int main(){
errpacket a; //you need allocate memory if you use a pointer here
void function(&a, 10, "Error detected with error code %08lx", errCode);
return 0;
}
void function(errpacket* ptr, int a, char* errString, ...){
ptr->err = a;
ptr->errDesc = malloc(strlen(errString)+1);
memset(ptr->errDesc, 0, strlen(errString)+1);
/*if(ptr->errDesc != NULL)
{
strcpy(ptr->errDesc, errString);
}*/
// use like following if you want use a formatted string
if(ptr->errDesc != NULL)
{
va_list args;
va_start (args, errString);
vsprintf (ptr->errDesc, errString, args);
va_end (args);
}
}
You can't use a single char variable to hold an entire string.
What you can do is declare errDesc to be either an array of fixed length (if you know the maximum number of characters that an error description can contain), or a pointer that is allocated dynamically with malloc and later freed with free.
Array case:
#define MAX_ERR_STRING_SIZE 500
typedef struct
{
int err;
char errDesc[MAX_ERR_STRING_SIZE];
} errpacket;
// You can now use strcpy() to copy to errpacket::errDesc assuming none of the error strings exceed MAX_ERR_STRING_SIZE
Dynamic memory:
typedef struct
{
int err;
char *errDesc;
} errpacket;
// Take note of the new parameter: int errStringLength,
void function(errpacket* ptr, int a, char* errString, int errStringLength, ...){
ptr->err = a;
ptr->errDesc = malloc((errStringLength + 1) * sizeof(char));
if(ptr->errDesc == NULL)
{
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(&ptr->errDesc, errString);
}
After you are done using ptr you will need to call free(ptr->errDesc); to de-allocate the string.
I don't think you really want a function with variable arguments, like printf. The solution below just expects the arguments you use in the end. Note that I do not use a user-supplied format string; that is considered a security risk. I also used snprintf (instead of the simple sprintf) in order to protect against error messages which are longer than the array size in the struct. The array size is a define so that it can be changed easily.
Specific fixes:
Proper declaration order (define the struct type before it's used)
Define an actual error packet object (and not just an uninitialized pointer to one)
Provide actual memory in the error packet for the message
Provide a print function for error packets
Do not let the user code specify printf formats; print user supplied strings with a length protected %s format specifier.
Do not use a variable argument function (whose excess arguments were not evaluated anyway); just declare the needed arguments explicitly.
.
#include<stdio.h>
int errCode = 0xA0B0C0D0;
#define MAX_ERRDESC_LEN 80 // avoid literals
typedef struct{
int err;
char errDesc[MAX_ERRDESC_LEN]; // provide actual space for the message
}errpacket;
void printErrPack(FILE *f, errpacket *ep){
fprintf(f, "Error packet:\n");
fprintf(f, " err = 0x%x:\n", ep->err);
fprintf(f, " desc = ->%s<-\n", ep->errDesc);
}
// Standard function with fixed argument count and types
void function(errpacket* ptr, int errNo, char* errString, int errCodeArg){
ptr->err = errNo;
// snprintf "prints" into a string
snprintf( ptr->errDesc, // print destination
MAX_ERRDESC_LEN, // max length, no buffer overflow
"%s with error code %x", // do not use user string as format
errString, // user supplied string, printed via %s
errCodeArg );
}
int main(){
errpacket a; // define an actual object, not a pointer
// pass the address of the object a
function(&a, 0xdead, "Error detected ", errCode);
printErrPack(stdout, &a);
return 0;
}

C program. Call a function that prints a string

Is there a way to make a function that stores a string, and then call that function in int main() that displays it on the screen? I have been searching a lot and haven't found a clear example. Here is my code. I would like to be able to call it without using the if statement
#include <stdio.h>
/* function declaration */
int StrPrint(char *str);
/* main() function */
int main()
{
char str[] = "The string i am returning n";
int (*ptr)(char *str);
ptr = StrPrint;
if (!(*ptr)(str))
printf("Done!\n");
return 0;
}
/* function definition */
int StrPrint(char *str)
{
printf("%s\n", str);
return 0;
}
The code you've posted is far more complicated than the simple task you're trying to accomplish.
Why not something like this:
#include <stdio.h>
void StrPrint(char* str);
int main(void)
{
char str[] = "The string i am returning n";
StrPrint(str);
return 0;
}
void StrPrint(char* str)
{
printf("%s\n", str);
}
This conflicts slightly with your requirement, in that the function doesn't store a string it just prints out the string passed to it as an argument. But according to the code you posted, this looks like what you're trying to accomplish.
As mentioned by you if you don't like to use pointers it can be done as shown below:
#include <stdio.h>
int StrPrint(char s[])
{
printf("%s\n", s);
return 0;
}
int main()
{
char str[] = "The string i am returning n";
if (!StrPrint(str))
printf("Done!\n");
return 0;
}

Receiving a string as a void pointer parameter and using strcpy to change it

Here's the code:
#include <stdio.h>
#include <string.h>
void print (void*);
int main (void)
{
char *a = "Mcwhat";
print(&a);
printf("\n%s", a);
return 0;
}
void print (void *text)
{
char* pchar[5];
*pchar = (char*)text;
strcpy( *pchar, "Mcthat" );
}
I am trying to make Mcwhat into Mcthat using a void parameter, but the printf gives me a segmentation fault afterwards. Where is my mistake? I managed to do it char by char but now I want to change the whole string. Didn't found enough material on this in the books on C I have.
Keep it simple and pay attention to the type of your variables :
#include <stdio.h>
#include <string.h>
void print (void*);
int main()
{
char a[] = "Mcwhat"; // a is now a read-write array
print(a); // a decays to a pointer, don't take its adress or you'll get a pointer-to-pointer
printf("\n%s", a);
return 0;
}
void print (void *text)
{
strcpy( text, "Mcthat" ); // Don't dereference text here
}
Note that this "print" function is unsafe in all imaginable ways, but that wasn't the question.
There are lot of issues in your code:
1. Char array should be big enough to store the string. char[5] cannot hold Mswhat.
2. char* pchar [5] declares 5 char pointers, whereas you need one char pointer pointing to a char array.
I have corrected it.
#include <stdio.h>
#include <string.h>
void print (char*);
int main (void)
{
char *a = malloc(10);
strcpy(a,"Mcwhat");
print(a);
printf("\n%s", a);
free(a);
return 0;
}
void print (char *text)
{
char *pchar = text;
strcpy( pchar, "Mcthat" );
}
Just write it like that
void print (char *text)
{
strcpy( text, "Mcthat" );
}
But make sure, the that size of text is large enough to put "Mcthat" inside it.
Also in main:
print(a);
instead of
print(&a); // would requite void print (char** text)
tho whole shebang:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void print (void*);
int main (void)
{
char *a = malloc(strlen("Mcwhat")+1);
print(a);
printf("\n%s\n", a);
free(a);
return 0;
}
void print (void *text)
{
strcpy(text, "Mcthat" );
}

Resources