C struct pointers return - c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_BUFFER_SIZE 100
typedef struct config_struct config_t ;
struct config_struct{
char name[20];
char ip[20];
int port;
char log[100];
};
int main(int argc, char *argv[]) {
config_t config;
read_config_file(argv[1], &config);
return 0;
}
int read_int_from_config_line(char* config_line) {
int val = atoi(config_line);
return val;
}
void read_str_from_config_line(char* config_line, char* val) {
strncpy(val,config_line, MAX_BUFFER_SIZE);
}
void read_config_file(char* config_filename, config_t *config) {
FILE *fp;
char *value, buffer[MAX_BUFFER_SIZE];
fp = fopen("./settings.conf", "r");
while (fgets(buffer, MAX_BUFFER_SIZE, fp) != NULL) {
if(!strcmp(buffer,"NAME")) {
read_str_from_config_line(value, &(config->name));
}
if(!strcmp(buffer,"PORT")) {
&(config->port) = read_int_from_config_line(value);
}
}
}
I try to compile this code and it gives me a incompatible pointer type at read_str_from_config_line(value , &(config->name)); and lvalue required as left operand of assignment &(config->port) = read_int_from_config_line(value);
I am trying to return the stuct back to the main program but I'm having problem with the struct pointers.
Any solution for it to be solve?
PS: The code is a mess as I trying to shorten it. Any help will be good as I am still a beginner to C programming.
Thanks

The & operator means "take the address of the object to the right".
This:
&(config->port)
means "take the address of the port member of the structure pointed to by config.
You don't want to take the address, you just want to assign to the member. That's just:
config->port = ...
This is the same as (*config).port, but nobody writes it like that since the arrow operator is so convenient.

read_str_from_config_line(value, &(config->name));
confg->name is declared as a char array, which naturally decays to a pointer to the first element (of type "pointer-to-char") if you omit the &:
read_str_from_config_line(value, config->name);
Taking its address explicitly instead results in a pointer of type pointer-to-array-of-20-chars, which is not the same type as pointer-to-char - which is why you are getting an error. This is a common source of confusion in C; in general, you should not take the address of an array (although it does have legitimate use cases).
In this line:
&(config->port) = read_int_from_config_line(value);
You are taking the address of the port member of the structure pointed at by config, which is a non-lvalue pointer. It looks like you are actually trying to assign to the member, so the line should read:
config->port = read_int_from_config_line(value);

Related

How to fix function calling warnings in c?

struct reviewStruct {
char reviewer[MAX_STR];
int feedback[NUMBER_MOVIES];
};
int readMovies(FILE *file, char movieNames[NUMBER_MOVIES][MAX_STR])
int readReviews(FILE *file, struct reviewStruct reviews[NUMBER_REVIEWERS])
int main() {
FILE *file;
char movieNames[NUMBER_MOVIES][MAX_STR];
char reviews [NUMBER_REVIEWERS];
myFile("cisfile.txt");
readMovies(file, movieNames);
readReviews(file, reviews);
}
This is my main function along with the function definitions, when I compile the program I get the following errors:
"warning: passing argument 2 of ‘readReviews’ from incompatible pointer type" for the line: "readReviews(file, reviews);"
"warning: ‘file’ is used uninitialized in this function" for the line: "readMovies(file, movieNames);"
How do I fix these two errors?
I took your code and tried to make it run.
#include <stdio.h>
#include <stdlib.h>
#define MAX_STR 10
#define NUMBER_MOVIES 3
#define NUMBER_REVIEWERS 2
struct reviewStruct {
char reviewer[MAX_STR];
int feedback[NUMBER_MOVIES];
};
int readMovies(FILE *file, char movieNames[NUMBER_MOVIES][MAX_STR])
{
printf("hi\n");
}
int readReviews(FILE *file, void *reviews)
{
printf("bye\n");
}
int main(void)
{
FILE *myFile;
char movieNames[NUMBER_MOVIES][MAX_STR];
char reviews [NUMBER_REVIEWERS];
myFile = fopen("cisfile.txt","r");
readMovies(myFile, movieNames);
readReviews(myFile, reviews);
fclose(myFile);
return 0;
}
With these assumptions runs without any warnings.
I am using gcc 8.3.0 without any options.
1. First warning:
As per what #kaylum said. You are declaring char reviews[MUMBER_REVIEWERS], but when you defined the parameters for your function: int readReviews(FILE *file, struct reviewStruct reviews[NUMBER_REVIEWERS], it is clear that the parameter concerned by the array should be of type struct reviewStruct.
So in the line where you got the warning change: char reviews [NUMBER_REVIEWERS]; to struct reviewStruct reviews[NUMBER_REVIEWERS];. That should be a pointer to a structure type, not a pointer to a character type. Or if you want to go more in detail: It is a pointer to an array of structures, the type of the array is determined by the type of elements it holds.
2. Second warning:
Now let's take a look at the second warning: warning: ‘file’ is used uninitialized in this function" for the line: "readMovies(file, movieNames)
As the warning says. Your pointer file was not initialized. Take it as a rule, that you cannot use a pointer without initializing it to something to point to. I believe that you are trying to read from a stream. So just in case you need it, you perhaps may be willing to use the function fopen(), which returns a pointer to a stream.

Pointer Functions in C: initialization of foo from incompatible pointer type

I'm working with C, and not allowed to use C++. Currently, I'm trying to implement some level of OOP in C. I'm currently working on trying to implement polymorphism and inheritance.
I've spent the majority of the day reading up on how my goals are possible through the use of function pointers. I am attempting to print the members variables of both structs as seen here:
RecordObject.h
typedef struct SuperRecordObject
{
char *Id;
char *date;
char *cases;
char *deaths;
void (*ptrPrintRecord)(char *id, char *date, char *cases, char *deaths, char *names_fr, char *names_en);
} SuperRecord;
typedef struct ChildRecordObject
{
SuperRecord super;
char *names_fr;
char *names_en;
} ChildRecord;
I have defined the function ptrPrintRecord in this file:
RecordObject.c
#include <stdio.h>
#include "RecordObject.h"
void ptrPrintRecord(char *id, char *date, char *cases, char *deaths, char *names_fr, char *names_en)
{
//char *record;
printf(" %s | %s | %s | %s | %s | %s\n", id, date, cases, deaths, names_fr, names_en);
//return record;
}
And I try to use the function in this file, as such:
DataLayer.c
#include <stdio.h>
#include <string.h>
#include "RecordObject.h"
/* more code here */
void(*fun_ptr)(char*,char*,char*,char*,char*,char*) = &record.super.ptrPrintRecord; //
(*fun_ptr)(record.super.Id, record.super.date, record.super.cases, record.super.deaths, record.names_fr, record.names_en);
/* more code here */
However, when I compile (using GCC), I get this warning which causes a crash.
warning: initialization of 'void (*)(char *, char *, char *, char *, char *, char *)' from incompatible pointer type 'void (**)(char *, char *, char *, char *, char *, char *)' [-Wincompatible-pointer-types]
62 | void(*fun_ptr)(char*,char*,char*,char*,char*,char*) = &record.super.ptrPrintRecord;
I've ran some other pointer functions in other files to mess around and test it, and the only thing I can think of as to what's going on here is it's maybe got something to do with how strings work in C?
You have an extraneous & in your attempted function pointer assignment. The ptrPrintRecord member of your structure is already a function pointer of the correct type, so you don't need the & - which would give the address of that pointer.
Just use:
void(*fun_ptr)(char*, char*, char*, char*, char*, char*) = record.super.ptrPrintRecord; // No &
As a side note, your use of ptrPrintRecord as that member (function pointer) and also as the name of an actual function (with the same 'signature') is likely to cause some issues, further down the road.
Furthermore, you need to actually initialize that member (pointer) to a valid function address before copying it to something you then call (as also with the other members of the structure). Here's a small main (using your other code) that works:
int main()
{
ChildRecord record;
record.super.ptrPrintRecord = ptrPrintRecord; // See my note about the name clash!
record.super.Id = "ID";
record.super.date = "today";
record.super.cases = "cases";
record.super.deaths = "deaths";
void(*fun_ptr)(char*, char*, char*, char*, char*, char*) = record.super.ptrPrintRecord; //
// To call the pointed-to function, we can just use the pointer name:
fun_ptr(record.super.Id, record.super.date, record.super.cases, record.super.deaths, record.names_fr, record.names_en);
return 0;
}

function address cast to char array

For my educational purposes I was wondering if there is an alternative way with memcpy() to the following code for the function address casting to an array of chars?
#include <stdio.h>
#include <string.h>
typedef void (*_vfp)(void);
#define FPSZ sizeof(_vfp)
union rcast {
_vfp fp;
char fp_c[FPSZ];
} rc;
void a(void){
printf("a()\n");
}
int main(int argc, char **argv)
{
int i=0;
memset(&rc,0,FPSZ);
rc.fp=a;
for (i=0;i<FPSZ;++i)
printf("%hhx ",rc.fp_c[FPSZ-i-1]);
puts("");
printf("%p\n",a);
return 0;
}
Thanks.
Minimally modifying your code:
#include <stdio.h>
#include <string.h>
typedef void (*_vfp)(void);
#define FPSZ sizeof(_vfp)
void a(void){
printf("a()\n");
}
int main(int argc, char **argv)
{
int i=0;
_vfp fp = a;
char fp_c[FPSZ];
memcpy(fp_c, &fp, FPSZ);
for (i=0;i<FPSZ;++i)
printf("%hhx ",fp_c[FPSZ-i-1]);
puts("");
printf("%p\n",a);
return 0;
}
EDIT: In response to comment, here's a version without a proxy and without memcpy
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
#include <string.h>
typedef void (*_vfp)(void);
#define FPSZ sizeof(_vfp)
void a(void){
printf("a()\n");
}
int main(int argc, char **argv)
{
int i=0;
char fp_c[FPSZ];
for (i=0;i<FPSZ;++i)
fp_c[i] = (char) (((uintptr_t) &a) >> CHAR_BIT * i);
for (i=0;i<FPSZ;++i)
printf("%hhx ",fp_c[FPSZ-i-1]);
puts("");
printf("%p\n",a);
return 0;
}
For my educational purposes I was wondering if there is an alternative way with memcpy() to the following code for the function address casting to an array of chars?
Note well: though arrays and pointers are closely associated, they are very different things. Among many other differences, you can use pointer types in cast operators, and pointers as cast operands, but you cannot use array types or arrays in those contexts.
You seem to say that what you want is a char array containing the bytes of the function pointer's value (as opposed to the bytes of whatever the pointer points to). You can get that, or something like it, several ways. The simplest way is to create a char * to the pointer's value. Again, that's not an array, but it can be used in many of the same ways that an array could be used:
typedef void (*_vfp)(void);
int main(int argc, char **argv)
{
int i;
_vfp fp = a;
char *cp = &fp;
for (i = 0; i < sizeof(fp); ++i) {
printf("%hhx ", cp[i]);
}
printf("\n%p\n", (void *) a);
return 0;
}
Do note, however, that the above code exhibits undefined behavior. The %p field descriptor tells printf() that the corresponding argument is an object pointer. C draws a distinction between object pointers and function pointers, and does not define any behavior for converting between values of those two type families. I include a cast explicitly expressing such a conversion (which may enable the compiler to notice and complain); your code results in such a conversion being performed implicitly.
If you want a separate array object containing the bytes of the pointer's value (as opposed to the pointed-to function's), then you can get it in a similar way:
int main(int argc, char **argv)
{
_vfp fp = a;
char array[sizeof(fp)];
memcpy(array, &fp, sizeof(array));
/* ... */
}
That one uses memcpy(), exactly as you asked.
In any event, there is no need for a union. In fact, although your union-based approach might happen to work with your C implementation, reading from a different union member than was most recently written to formally exhibits undefined behavior.
What you are doing is formally Undefined Behaviour. C language says that an union can contain any of different variables, but you shall only access the variable that was set in the union : The size of a union is sufficient to contain the largest of its members. The value of at
most one of the members can be stored in a union object at any time. (ref : C Language Specification Draft - 6.7.2.1 Structure and union specifiers - 16)
So it is neither best nor worse than doing pointer casting via void :
intptr_t ip = (intptr_t) &a;
char *fp_c = (void *) &intptr_t;
or with memcpy :
char fp_c[FPSZ];
intptr_t ip = (intptr_t) &a;
memcpy(fp_c, &ip, sizeof(intptr_t));
All will give you same result in :
for (i=0; i<FPSZ; i++) {
printf("%hhx ",fp_c[FPSZ-i-1]);
}
fputs("\n");

C: Function that recieves a pointer to pointer so it can allocate an external one

How can I make the following work? The idea is for the function to allocate an external pointer so I can use this concept in another program, but I can't do that because gcc keeps telling me that the argument is from an incompatible pointer type... It should be simple, but I'm not seeing it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int allocMyPtr(char *textToCopy, char **returnPtr) {
char *ptr=NULL;
int size=strlen(textToCopy)+1;
int count;
ptr=malloc(sizeof(char)*(size));
if(NULL!=ptr) {
for(count=0;count<size;count++) {
ptr[count]=textToCopy[count];
}
*returnPtr = ptr;
return 1;
} else {
return 0;
}
}
int main(void) {
char text[]="Hello World\n";
char *string;
if(allocMyPtr(text,string)) {
strcpy(string,text);
printf(string);
} else {
printf("out of memory\n");
return EXIT_FAILURE;
}
free(string);
return EXIT_SUCCESS;
}
It's almost correct, but as your function wants a pointer to a pointer, you have to pass the address of the pointer to the function, using the address-of operator:
allocMyPtr(text, &string)
You are passing string using pass by value in allocMyPtr() you should use pass by adress so that pointer should match otherwise compiler keep tellin you about ,
incompatible type char * to char **
do this :
if(allocMyPtr(text,&string)) { }
use &string instead to fix your problem the type related to this input parameter is char ** and not char *
if(allocMyPtr(text,&string)) {
Just a remark concerning your source code:
The allocMyPtr() function already do a copy from text to string.
so why you make copy agian with strcpy. it's useless
strcpy(string,text); // this useless

How to pass an array of struct using pointer in c/c++?

in C code I'm stuck to pass an array of struct to a function, here's the code that resembles my problem:
typedef struct
{
int x;
int y;
char *str1;
char *str2;
}Struct1;
void processFromStruct1(Struct1 *content[]);
int main()
{
Struct1 mydata[]=
{ {1,1,"black","cat"},
{4,5,"red","bird"},
{6,7,"brown","fox"},
};
processFromStruct1(mydata);//how?!?? can't find correct syntax
return 0;
}
void processFromStruct1(Struct1 *content[])
{
printf("%s", content[1]->str1);// if I want to print 'red', is this right?
...
}
Compile error in msvc is something like this:
error C2664: 'processFromStruct1' : cannot convert parameter 1 from 'Struct1 [3]' to 'Struct1 *[]'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
How to solve this? tnx.
You almost had it, either this
void processFromStruct1(Struct1 *content);
or this
void processFromStruct1(Struct1 content[]);
and, as Alok points out in comments, change this
content[1]->str1
to this
content[1].str1
Your array is an array of structures, not an array of pointers, so once you select a particular structure with [1] there is no need to further dereference it.
Try
processFromStruct1( & mydata[ i ] ); // pass the address of i-th element of mydata array
and the method to
void processFromStruct1(Struct1 *content )
{
printf("%s", content->str1);
...
}
(2nd part already noted by John Knoeller and Alok).
John Knoeller gave the perfect syntax , I am trying to explain some basic things,
I hope that it willsolve your confusions in future.
This is very similar to passing pointer to a function in C.
Of course struct is also a pointer,
so we can pass the value in 2 ways
0. Via pointer
0. Via array ( since we are using array of struct )
so the problem is simple now ,
You have to give the data type of a variable as we do in normal pointers ,
here the data type is user-defined ( that means struct ) Struct1 then variable name,
that variable name can be pointer or array name ( choose a compatible way ).
This works for me. Changed structs to C++ style.
struct Struct1
{
int x;
int y;
char *str1;
char *str2;
};
Struct1 mydata[]=
{ {1,1,"black","cat"},
{4,5,"red","bird"},
{6,7,"brown","fox"},
};
void processFromStruct1(Struct1 content[]);
int main()
{
processFromStruct1(&mydata[1]);
return 0;
}
void processFromStruct1(Struct1 content[])
{
printf("%s",content->str1);
}
output: red
Perhaps a proper re-factoring from the future:
#include <stdio.h>
typedef struct
{
int x;
int y;
char *str1;
char *str2;
} struct_1;
static void proc_the_struct_1_arr (
const int count_ ,
// array arg declared with min number of arguments
// also can not be null
struct_1 content[ static count_ ]
)
{
for (unsigned j = 0; j < count_; ++j)
printf("x:%-4dy:%-4d%-12s%-12s\n", content[j].x,content[j].y,content[j].str1,content[j].str2);
}
int main( void )
{
struct_1 mydata[3]= {
{.str1 = "black", .str2 = "cat" },
{.str1 = "red", .str2 = "bird"},
{.str1 = "brown", .str2 = "fox" },
};
proc_the_struct_1_arr (3,mydata);
return 0;
}
Godbolt
Obviously proc_the_struct_1_arr declaration is interesting. That actually uses Variably Modified Types (VMT). That is a legal syntax only for array arguments.
That is not slower vs the pointer to array solution:
static void proc_the_struct_1_arr_pointer (
const int count_ ,
// array arg not declared with min
// required number of arguments
struct_1 (*arr_ptr)[ /* static no allowed here */ count_ ]
);
I assume the compiler "rewrites" the above to the array pointer, anyway. On the second option arr_ptr can be a null argument.
You can try the prototype as void processFromStruct1(Struct1 content[]); and then the declaration should be like void processFromStruct1(Struct1 content[]).

Resources