recv() C error invalid conversion from char to int - c

I have some C code below:
char update[MAX_UPDATE_LEN];
int remoteLen;
char pholder;
pholder = recv(update,connectDescriptor,MAX_UPDATE_LEN,MSG_DONTWAIT); //error
remoteLen = atoi("pholder");
I keep getting the following errors:
client.cpp:849: error: invalid conversion from `char*' to `int'
client.cpp:849: error: initializing argument 1 of `ssize_t recv(int, void*,
size_t, int)'
client.cpp:849: error: invalid conversion from `int' to `void*'
client.cpp:849: error: initializing argument 2 of `ssize_t recv(int, void*,
size_t, int)'
What is causing these errors?

There are several issues with this code:
char update[MAX_UPDATE_LEN];
int remoteLen;
char pholder;
pholder = recv(update,connectDescriptor,MAX_UPDATE_LEN,MSG_DONTWAIT); <-- error here
remoteLen = atoi("pholder");
recv returns an ssize_t which is usually much bigger than a char. So you can't safely store the return code in pholder.
The arguments to recv() are in the wrong order. Here's the declaration: ssize_t recv(int sockfd, void *buf, size_t len, int flags);
atoi is being passed a string which is not a number "pholder". It expects a string like "12345". If ASCII-encoded numerals is what you expect, you can give update to atoi.
Bonus: use sizeof(update) instead of MAX_UPDATE_LEN for len -- that way if the type declaration or size of update changes, you should still get the expected value.
Here's how you might fix it:
char update[MAX_UPDATE_LEN];
const int flags = MSG_DONTWAIT;
const ssize_t ret = recv(connectDescriptor, update , sizeof(update), flags);
if (-1 == ret)
{
perror("recv");
exit(1);
}
const int remoteLen = strtol(update, update + sizeof(update), 0);

Related

Convert to Pointer Argument in Function (C)

There is a function that takes the following argument :
int send_message(const char *topic)
I have a struct :
typedef struct mqtt_topic {
char topic[200];
} mqtt_topic_t;
and a value that is of the type : mqtt_topic_t *mqtt_topic
I am trying to pass mqtt_topic->topic as an argument to the function but it throws an error. How do I convert this data to useful format that I can then use as an argument in my function?
Here is the code snippet :
int mqtt_publish(char message[])
{
int msg_id = 0;
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
mqtt_topic_t *mqtt_topic = get_mqtt_topic();
msg_id = esp_mqtt_client_publish(client,&mqtt_topic->topic, message, 0, 1, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
return msg_id;
}
Function Prototype :
int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic, const char *data, int len, int qos, int retain);
The argument &mqtt_topic->topic has type "pointer to char[200]". What you want is pointer to just char:
msg_id = esp_mqtt_client_publish(client, mqtt_topic->topic, message, 0, 1, 0);
When passed as argument, or used in almost any other way except with & and sizeof operators, array decays to pointer to its first element. This is why mqtt_topic->topic gives char*, which is ok as const char* parameter needed here.
you do not need & in front of mqtt_topic->topic.
If your code does not compile (it is giving errors - not warnings) it means that you use a C++ compiler instead of C compiler or you set warning to be treated as errors.

Add numbers to filename

I want to store data in different files. Therefore I want to create files as follows: data_1.log, data_2.log, ..., data_N.log. The appendix .log is not necessary but would be nice. All my approaches failed so far. Here is one sample that is probably close to what I need:
#include <stdio.h>
#include <string.h>
char get_file_name(int k){
int i, j;
char s1[100] = "logs/data_";
char s2[100];
snprintf(s2, 100, "%d", k);
for(i = 0; s1[i] != '\0'; ++i);
for(j = 0; s2[j] != '\0'; ++j, ++i){
s1[i] = s2[j];
}
s1[i] = '\0';
return s1;
}
int main(){
char file_name[100];
for(int k=0; k<10; k++){
// Get data
// ...
// Create filename
strcpy(file_name, get_file_name(k));
printf("%s", file_name);
// fp = fopen(file_name, "w+");
// Write data to file
// print_results_to_file();
// fclose(fp);
}
return 0;
}
At the moment I get the following errors which I don't understand:
string.c: In function ‘get_file_name’:
string.c:14:12: warning: returning ‘char *’ from a function with return type ‘char’ makes integer from pointer without a cast [-Wint-conversion]
return s1;
^~
string.c:14:12: warning: function returns address of local variable [-Wreturn-local-addr]
string.c: In function ‘main’:
string.c:24:27: warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
strcpy(file_name, get_file_name(k));
^~~~~~~~~~~~~~~~
In file included from string.c:2:
/usr/include/string.h:121:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
^~~~~~
Is there a more simpler way to create such filenames? I can't believe that there isn't one.
There are various issues with this code and rather than correcting them one by one here’s an alternative approach. It’s not the only one but it’s simple and should be easy to understand and adapt:
#include <stdio.h>
void get_file_name(int k, char* buffer, size_t buflen) {
snprintf(buffer, buflen, "logs/data_%d.log", k);
}
int main() {
const size_t BUFLEN = 50;
char file_name[BUFLEN];
for (int i = 0; i < 10; i++) {
get_file_name(i, file_name, BUFLEN);
printf("%s\n", file_name);
// Code for writing to file.
}
}
A few details:
Rather than attempting to return (pointers to) memory, this function passes a buffer that is written to. It’s up to the caller to ensure that the buffer is big enough (this is always the case here, but if the actual filenames are longer, you should add logic that inspects the return value of snprintf and performs appropriate error handling).
The actual logic of the function requires only a single call to snprintf, which already performs everything you require, so it’s unclear whether having a separate function is even necessary or helpful.
The above uses variable-length arrays. If you want to ensure constant buffers, you can use a #define instead of a const size_t variable for the buffer length. However, using a variable-length array here is fine, and some compilers even convert it into a constant array.
As mentioned in comments, it’s important that you (a) read and understand the documentation of the functions you’re using, and (b) read and understand the compiler error messages.
The function get_file_name has return type char
char get_file_name(int k){
but it returns an object of type char *
char s1[100] = "logs/data_";
//...
return s1;
Moreover the returned pointer points to a local array s1 that will not alive after exiting the function.
In this call
strcpy(file_name, get_file_name(k));
the type of the second argument (that is char according to the function get_file_name declaration) shall be char *.
There is neither the function print_results_to_file declaration nor its definition.
According to the C Standard the function main without parameters shall be declared like
int main( void )
I would write the function get_file_name the following way
#include <stdio.h>
#include <string.h>
char * get_file_name( char *file_name, size_t n, size_t padding )
{
const char *common_part = "logs/data_";
snprintf( file_name, n, "%s%zu", common_part, padding );
return file_name;
}
int main( void )
{
enum { N = 100 };
char file_name[N];
for ( size_t i = 0; i < 10; i++ ) puts( get_file_name( file_name, N, i ) );
}
The program output is
logs/data_0
logs/data_1
logs/data_2
logs/data_3
logs/data_4
logs/data_5
logs/data_6
logs/data_7
logs/data_8
logs/data_9
There are several problems with your code, but the biggest one is that you are trying to return a pointer to a local variable from get_file_name.
This is a big no no since the memory allocated for char s1[100] in get_file_name is freed immediately after return.
The rest of the errors are because you forgot the * in char get_file_name(int k).
There are several possible solutions:
Pass in a char array for the function to fill.
Use a global variable (This is considered a bad practice).
Dynamically allocate the memory.
Make the local variable static (this is a bit hacky, but legal)
Your errors are easily explained:
get_file_name should return a char but you create a char[] and return this(it isthe same as char*)
get_file_name returns the adress of an array that is created in the function itself. After the function ends, the array may be overwritten. Add the array as parameter or use malloc
strcpy does not work because it expects a char* (char[]) and not a char. get_file_name returns a char.
print_results_to_file is not defined. You may need to include other files you use in the program (e.g. if the function is implemented in a file func.c the prototype should be in a file called func.h that is included via #include "func.h".

v8 node buffer of unsigned chars

My knowledge / experience of C is quite limited but I'm trying to create a node addon that uses a node buffer with a C call which expects the buffer to be of type 'unsigned char*' but from what I can see the node buffer Data method provides a 'char*' so the types are incompatible. E.g.
This is how it would be called using c:
int length = 100;
unsigned char buf[length];
int ret = ftdi_read_data(&ftdic, buf, length);
And from what I have read, to use a node buffer you do the following instead:
int length = 100;
node::Buffer *slowBuffer = node::Buffer::New(length);
int ret = ftdi_read_data(&ftdic, node::Buffer::Data(slowBuffer), length);
However this returns the following error when building:
error: invalid conversion from ‘char*’ to ‘unsigned char*’ [-fpermissive]
int ret = ftdi_read_data(&ftdic, node::Buffer::Data(slowBuffer), length);
Is it possible to create a node buffer of type unsigned chars, or achieve this in some other way?
Thanks
In your addon C code use a cast like this: (unsigned char*)node::Buffer::Data(slowBuffer). This is the usual fix for the specific error shown.

Conversion between function pointers with void and non-void pointer parameters

I have a question related to void pointer conversions. Instead of casting between void* and non-void pointers, my question is about casting between function pointer types, one of which has void* as parameter type and another has a pointer to some particular data type.
Here's the code which allows to reproduce the warning messages:
#include <stdio.h>
typedef void (*module_outputMessage)(void *param, const char *msg);
void module_function(module_outputMessage outputFunc, void *output_param, int msgid, const char *msg1, const char *msg2)
{
if (msgid == 0)
outputFunc(output_param, msg1);
else
outputFunc(output_param, msg2);
}
struct main_state
{
int msgid;
};
void main_outputMessage(struct main_state *state, const char *str)
{
printf("Message %d: %s\n", state->msgid, str);
state->msgid++;
}
int main(int argc, char *argv[])
{
struct main_state state;
const char *msg1 = "abc", *msg2 = "def";
state.msgid = 0;
module_function(&main_outputMessage, &state, 0, msg1, msg2);
module_function(&main_outputMessage, &state, 0, msg1, msg2);
module_function(&main_outputMessage, &state, 1, msg1, msg2);
module_function(&main_outputMessage, &state, 0, msg1, msg2);
module_function(&main_outputMessage, &state, 1, msg1, msg2);
return 0;
}
This is it, the program is made of two parts, main and module. module outputs the text, but it shouldn't deal with all output specifics - instead, main is the one to handle the output. Since main is dependent on module and not vice versa, module does not know what's going on in main, and to output the messages, it needs an output function to be passed as a parameter. In order for output to know which state object it's dealing with, that object needs to be passed along with the output function. And that's where conversion comes into play: module doesn't know and shouldn't care about the implementation of main, so instead of using struct main_state* as function parameter, it accepts void* which it merely passes to output function.
So it all boils down to conversion between these types:
void (*)(void* , const char*)
void (*)(struct main_state *, const char*)
The program gives the expected results:
Message 0: abc
Message 1: abc
Message 2: def
Message 3: abc
Message 4: def
However, GCC complains about incompatible pointer types (I get five messages like this, one for each function call):
funcpointvoid.c: In function ‘main’:
funcpointvoid.c:33:2: warning: passing argument 1 of ‘module_function’ from incompatible pointer type
module_function(&main_outputMessage, &state, 0, msg1, msg2);
^
funcpointvoid.c:5:6: note: expected ‘module_outputMessage’ but argument is of type ‘void (*)(struct main_state *, const char *)’
void module_function(module_outputMessage outputFunc, void *output_param, int msgid, const char *msg1, const char *msg2)
^
So even though it works fine for me, with these warnings I'm not sure if this 'architecture' can be relied upon. But as I see it myself, the only difference is pointers to void and non-void, and it's just one way to use generic pointers for whatever purpose they exist. Is this a bug of GCC or have I missed something?
void (*)(void* , const char*)
void (*)(struct main_state *, const char*)
are two different types and as there are no implicit conversion between function pointer types you need to make the conversion explicit by using a cast:
Change:
module_function(&main_outputMessage, &state, 0, msg1, msg2);
to
module_function((module_outputMessage) main_outputMessage,
&state, 0, msg1, msg2);
but be aware that the function call outputFunc technically invoke undefined behavior as void (*)(void* , const char*) and void (*)(struct main_state *, const char*) are not compatible types.

How to handle data types?

I'm really facing a problem with data types conversions.
I'm making a GUI version of a program with GTK. To get entry_text string I need a const char* which obliges me to use this data type in the function below.
I want to convert it to string(char[]) and compiler keep giving me errors below :
Source code where errors come:
//....
char ret (const char *bd){
char c[100];
strcpy(c,bd);
return *c;
}
char encode(const char ebuf[],const char epass[]) {
char *buf=ret(ebuf);
char *pass=ret(epass);
//...
When I compile the code I get following errors (with g++):
codgui.cpp: In function ‘char encode(const char*, const char*)’:
codgui.cpp:36: error: invalid conversion from ‘char’ to ‘char*’
codgui.cpp:37: error: invalid conversion from ‘char’ to ‘char*’
Anyone have any clue on how to fix this?
Your ret function is only returning the first character in the local variable c. You want to return a char*, and you should never return the address of a local variable, so you will need to create it on the heap.
char* ret (const char *bd){
char *c = new char[100];
strcpy(c,bd);
return c;
}
char encode(const char ebuf[],const char epass[]) {
char *buf=ret(ebuf);
char *pass=ret(epass);

Resources