I need recive the char* from a function but I don't understand what is wrong.
int main(int argc,char** argv)
{
char *respuesta;
respuesta = comunicacion(comando);
printf("respuesta uno %s",respuesta);
return EXIT_SUCCESS;
}
char *comunicacion(char data[])
{
unsigned char c ='d';
char *respuesta;
append(respuesta,c);
return respuesta;
}
void append(char* s, char c)
{
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
}
this is the error:
main.c:24:15: warning: assignment makes pointer from integer without a cast [enabled by default]
The reason you see the "assignment makes pointer from integer without a cast" warning is that your comunicacion function lacks a prototype. When this happens, C assumes that your function returns an int, and all its parameters are int as well. Since neither of these is true about your comunicacion function, your code has undefined behavior.
Another problem is that comando is undefined. Finally, when you call append, respuesta is uninitialized. Using it in any way inside the append function would be undefined behavior, so the call strlen on the vale that's uninitialized is illegal.
Finally, note that the data parameter is unused in the comunicacion function. This needs to be changed - either use the parameter, or remove it from the function's signature.
in respuesta = comunicacion(comando); .... the compiler is assuming that comunicacion returns an int, since it has not seen a prototyp[e or definition. This is likely what generates the warning.
in main(), comando apparently has not been declared. Had it already been defined as a global variable?
in comunicacion(), respuesta is never set to anything. The call to append can have no effect on the value of respuesta.
Related
Inside a thread, I run this function:
char *r = NetString("ch","aaaaa");
printf("%s",r); printf("%s","\n");
Which calls
char *NetString(char *id, char *data) {
char *result;
result = (char *)malloc(strlen(id)+strlen(data)+2);
strcpy(result, id);
strcat(result, "/");
strcat(result, data);
printf("%s",result); printf("%s","\n");
return (char *)result;
}
In the console, when I compile this warning shows up:
warning: initialization makes pointer from integer without a cast
[enabled by default]: char *r = NetString("ch","aaaaa");
^
If you need the full code (which may be a bit unorganized), here it is:
pastebin
Apparently, this code runs as expected (returns "ch/aaaaa" twice) when not run in a thread, but when I run it in a thread, the string only prints once (that is, in the NetString function). Any help? Thanks a lot.
This code
char *r = NetString("ch","aaaaa");
and this error
warning: initialization makes pointer from integer without a cast
[enabled by default]: char *r = NetString("ch","aaaaa");
^
almost certainly mean:
You are calling NetString() without providing a function prototype, thus it is treated as returning int.
You are running on a 64-bit platform where pointers are 64 bit and int values are 32 bit.
Thus, your char * pointer value from NetString() gets truncated to an int, then assigned to a pointer, where it no longer points to anything useful.
You need to provide a proper prototype with a function declaration:
char *NetString( char *, char * );
in all code that calls NetString(), and the prototype needs to be before any such calls.
#include <stdio.h>
#include <string.h>
int myprint(char_array){
char mystring[80];
strcat(mystring, "\n");
printf("%s", mystring);
return 0;
}
int main(int argc, char** argv){
int count = 5;
char letter = 'c';
printf("decimal: %d, char: %c\n", count, letter);
myprint("sup");
return 0;
}
I get warnings on compile:
cchilders:~/projects/buildyourownlisp_in_C/ch3 [master]$ compile basics.c basics
basics.c: In function ‘myprint’:
basics.c:4:5: warning: type of ‘char_array’ defaults to ‘int’
int myprint(char_array){
^
It compiles, but my myprint function doesn't work:
cchilders:~/projects/buildyourownlisp_in_C/ch3 [master]$ ./basics
decimal: 5, char: c
I see this answer warning: return type defaults to ‘int’ [-Wreturn-type] but doesn't apply to me since I did declare int main(...)
I also see this declaration of functions:
return_type function_name( parameter list ) {
body of the function
}
And for myprint I declare as taking int and return 0. What does this warning mean and why doesn't my function work? Thank you
ANSWER:
void myprint(char mystring[]){
strcat(mystring, "\n");
printf("%s", mystring);
}
quiets the warnings, but causes Segmentation fault (core dumped)
Changing to
void myprint(char[] mystring){
strcat(mystring, "\n");
printf("%s", mystring);
}
makes it worse:
cchilders:~/projects/buildyourownlisp_in_C/ch3 [master]$ cc -std=c99 -Wall basics.c -o basics
basics.c:4:21: error: expected ‘;’, ‘,’ or ‘)’ before ‘mystring’
void myprint(char[] mystring;){
^
basics.c: In function ‘main’:
basics.c:15:5: warning: implicit declaration of function ‘myprint’ [-Wimplicit-function-declaration]
myprint("sup");
^
I also tried
void myprint(char[] mystring;){...
and
void myprint(char[] mystring,){...
As others have pointed out, you didn't specify a type for char_array, so it is assumed to be int. Changing it to char char_array[] fixes this.
Your other problem is that you're passing a string constant ("sup") to this function and are then attempting to modify it. String constants are stored in a read-only section of memory, so you can't modify it.
Given that you're only printing the string with a newline, you can do this instead:
void myprint(char mystring[]){
printf("%s\n", mystring);
}
You are not providing a data type for char_array in
int myprint(char_array)
You need char * or whatever you want it to be.
Firstly, function definitions should be like
return-type function-name ( parameter-type parameter-name, parameter-type parameter-name)
{ ... }
You did not specify either a parameter type or a parameter name. If you mean char_array to mean a type, you need to define it first, using a typedef or a struct or something else. If you mean char_array to be a parameter name, you need to specify its type, as
char[] char_array
say. Also, in this case, you do not actually use the variable char array anywhere in the function myprint. So the argument "sup" is not being used at all.
After edit to the question:
Try
char str[] = "sup";
myprint(str);
instead. As far as I know, you can't pass a string (a character array) by value.
int myprint(char_array)
What type has the parameter with name char_array? Because you didn't specify it, the compiler assumed it to be an int. Luckily it's warning you about that.
Don't rely on such behaviour, though. (I don't know whether this is still legal in C11 for example) Just write correct function declarations, including parameter types.
You need to specify the type of the parameters you expect to be passed to the function. There are mistakes in the function too. char_array is of char* type. You need to copy every part of the passed array to your local array, THEN only can you call printf for this function to work
I'm learning about the pointers in C. I don't understand why this code fails during the compilation process.
#include <stdio.h>
void set_error(int *err);
int main(int argc, const char * argv[])
{
const char *err;
set_error(&err);
return 0;
}
void set_error(int *err) {
*err = "Error message";
}
You declare the function to expect a pointer-to-int (int *). But you give it a pointer-to-pointer-to-char and set_error treats it as such. Change the declaration thusly:
void set_error(const char ** err)
If you had compiled with warnings enabled (-Wall for GCC) it would give the following warnings:
In function 'main':
warning: passing argument 1 of 'set_error' from incompatible pointer type [enabled by default]
set_error(&err);
^
note: expected 'int *' but argument is of type 'const char **'
void set_error(int *err);
^
In function 'set_error':
warning: assignment makes integer from pointer without a cast [enabled by default]
*err = "Error message";
^
Your function expects int * type argument but you are passing to it const char ** type argument.
Change your function declaration to
void set_error(const char **err);
The issue you have unearths an important facts about strings in C.
It also raises an interesting fact about scoping.
1. There is no such thing as a string in C; only a pointer to an array of characters.
Therefore, your statement *err = "Error message"; is wrong because by derefencing err you're not getting to the value of the string, but it's first character. (You can't quantify the 'value of a string' in C because there's no such thing as a string in C)
*err is actually undefined because nothing is yet assigned.
Note that the usual definition of a string is const char * or char * so I've changed this from what you had for the note below:
#include <stdio.h>
int main(void){
char * a = "hello";
if (*a == 'h'){
printf("it's an 'H'\n");
}
else{
printf("no it isn't\n");
}
}
You'll see that *err actually returns the value of the first character because a[0] == *a
2. You cannot return pointers to locally scoped data in C
set_error() has the correct intentions, but is doomed to fail. Although "Error message"looks like a value, it is actually already a pointer (because strings in C are pointers to character arrays, as mentioned above).
Therefore, taking (1) into account you might expect to be able to do this:
void set_int(int *myint) {
*myint = 1; //works just fine because 1 is a value, not a reference
}
void set_error(char *err) {
// doesn't work because you're trying to assign a pointer to a char
*err = "Error message";
void set_error_new(char *err) {
//doesn't work because when the function returns, "Error Message" is no longer available on the stack" (assignment works, but when you later try to get at that data, you'll segfault
err = "Error message";
}
You need to take a different approach to how you play with so-called 'strings' in C. Think of them as a pointer to a character array and you'll get better at understanding these issues. Also see C: differences between char pointer and array
One problem is that set_error expects an int * parameter, but you're passing the address of a char *, which makes it a char **. In addition, as noted by #Kninnug there's a buffer overwrite problem here which needs to be dealt with. Try rewriting your code as:
#include <stdio.h>
#include <string.h>
void set_error(char *err, size_t errbuf_size);
int main(int argc, const char * argv[])
{
char err_buf[1000];
set_error(err_buf, sizeof(err_buf));
printf("err_buf = '%s'\n", err_buf);
return 0;
}
void set_error(char *err, size_t errbuf_size) {
strncpy(err, "Error message", errbuf_size-1);
}
As you'll notice in the rewritten version of set_error, another problem is that you can't just assign a value to a pointer and have the target buffer changed - you need to use the string functions from the standard library (here I'm use strncpy to copy the constant "Error message" to the buffer pointed to by the char * variable err). You may want to get familiar with these.
Share and enjoy.
Firstly you have to change your function's declaration to
void set_error(char **err);
The body of the function is the same. Also you declared err variable as const char *err and tried change it. It generates a warning.
Let's start by talking about types. In your main function, you declare err as
const char *err;
and when you call the set_error function, you pass the expression &err, which will have type "pointer to const char *", or const char **.
However, in your function declaration and definition, you declare the parameter err as
int *err;
The types const char ** and int * aren't compatible, which is why the compiler is yakking. C doesn't allow you to assign pointer values of one type to pointer variables of a different type (unless one is a void *, which is a "generic" pointer type). Different pointer types are not guaranteed to have the same size or representation on a particular platform.
So that's where the compiler issue is coming from; what's the solution?
In C, string literals like "Error message" have type char *1 (const char * in C++), so whatever I assign it to needs to have a type of either char * or const char *. Since we're dealing with a string literal, the latter is preferable (attempting to modify the contents of a string literal invokes undefined behavior; some platforms put string literals in read-only memory, some don't). So you need to make the following changes to your code2:
void set_error( const char **err )
{
*err = "Error message";
}
int main( void ) // you're not dealing with command line arguments, so for this
{ // exercise you can use `void` for your parameter list
const char *err;
set_error( &err );
return 0;
}
Remember that C passes all function arguments by value; this means that the formal parameter err in set_error is a different object in memory than the actual parameter err in main; if the code had been
void set_error( const char *err )
{
err = "Error message";
}
int main( void )
{
const char *err;
set_error( err );
return 0;
}
then the change to err in set_error would not be reflected in the variable err in main. If we want set_error to modify the value of err in main, we need to pass set_error a pointer to err and dereference it in the function. Since the parameter err has type const char **, the expression *err has type const char *, which is the type we need for this assignment to succeed.
1. Actually, that's not true; string literals have type "N-element array of char", where N is the number of characters in the string plus the 0 terminator. However, for reasons that aren't really worth going into here, the compiler will convert expressions of array type to expressions of pointer type in most circumstances. In this case, the string literal "Error message" is converted from an expression of type "14-element array of char" to "pointer to char".
2. A function definition also serves as a declaration; I typically put the called function before the caller so I don't have to mess with separate declarations. It means my code reads "backwards" or from the bottom up, but it saves some maintenance headaches.
1st error--> You are noticing is due to the fact that your function expects a pointer to int and you are passing a pointer to const char
2nd error--> You dereferenced the pointer and inserted the value "Error Message" which is a string and you pointer was pointer to char.
3rd error--> set_error(&err); --> This statement is wrong as err itself stores an address so there is no need to put & putting & means you are passing the address of the pointer *err and not the address which it is holding. So try this.
include <stdio.h>
void set_error(const char* err[]); //Function Declaration
int main()
{
const char* err[1000];
set_error(err);
printf("%s",*err);
return 0;
}
void set_error(const char* err[])
{
*err = "Error Message";
}
I always thought that when you want to return an array from a function, the only way to do that was using pointers like so:
char * func();
But yesterday, while I was going through K & R, I noticed wrongly assumed that char x()[] is also a valid construct. So I went ahead to test this out and wrote up the following code:
#include <stdio.h>
#include <stdlib.h>
char string1[10] = "123456789";
char x(void)[10];
int main(void) {
printf("string returned by x() is %s",x());
return EXIT_SUCCESS;
}
char x(void)[10] {
return x;
}
Compiling using GCC on Windows, this threw the following errors:
..\src\07arrreturn.c:7:6: error: 'x' declared as function returning an array
..\src\07arrreturn.c: In function 'main':
..\src\07arrreturn.c:10:2: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'int' [-Wformat]
..\src\07arrreturn.c: At top level:
..\src\07arrreturn.c:14:6: error: 'x' declared as function returning an array
..\src\07arrreturn.c: In function 'x':
..\src\07arrreturn.c:15:2: warning: return makes integer from pointer without a cast [enabled by default]
What is happening? am I mis-understanding what the book says? How can you return more than one value (or address) from a function? Isn't that restricted by the fact that you only have a single limited size CPU register that can hold the return value? If you have to return a big chunk of data, you can do so only by returning the address to it right?
Whats the deal with char x()[]? Is such a thing even used?
EDIT: I DID in fact misread the stuff from K&R. See comment below.
char x()[] is also a valid construct
Not as-is, and not quite in this context.
You can use similar syntax to:
declare a pointer to array: char (*arrPtr)[20];
declare an array of function pointers: void (*foo[20])(void);
dereference the return value (pointer) of a function call: char *foo(); char c = foo()[0];
declare a function that returns a pointer to array: char (*foo())[20]
or the same thing with a function pointer: char (*(*foo)())[20]
Which one of these are you looking for?
The C standard (ISO/IEC 9899:2011) says unequivocally:
6.7.6.3 Function declarators (including prototypes)
Constraints
1 A function declarator shall not specify a return type that is a function type or an array
type.
Thus your code is invalid.
K&R C is quite old. In ANSI C (C89), functions returning arrays aren't allowed and what you see is the result of this. First, you get errors for the declaration of x() as a function returning an array and due to this error, x() is never correctly declared and thereby treated like a function returning an int (because this used to be the default return type). This returned int is then supposed to be interpreted as char * generating the final warning.
If you need to return an array, you can wrap it in a struct. Otherwise return a pointer (make sure that the memory it points to is valid after returning).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char string1[10] = "123456789";
struct ret_s {
char string1[10];
};
struct ret_s x(void);
int main(void) {
struct ret_s r = x();
printf("string returned by x() is %s\n", r.string1);
return EXIT_SUCCESS;
}
struct ret_s x(void) {
struct ret_s r;
strcpy(r.string1, string1);
return r;
}
I want to the know the problems with the code presented below. I seem to be getting a segmentation fault.
void mallocfn(void *mem, int size)
{
mem = malloc(size);
}
int main()
{
int *ptr = NULL;
mallocfn(ptr, sizeof(ptr));
*ptr = 3;
return;
}
Assuming that your wrapper around malloc is misnamed in your example (you use AllocateMemory in the main(...) function) - so I'm taking it that the function you've called malloc is actually AllocateMemory, you're passing in a pointer by value, setting this parameter value to be the result of malloc, but when the function returns the pointer that was passed in will not have changed.
int *ptr = NULL;
AllocateMemory(ptr, sizeof(ptr));
*ptr = 3; // ptr is still NULL here. AllocateMemory can't have changed it.
should be something like:
void mallocfn(void **mem, int size)
void mallocfn(int **mem, int size)
{
*mem = malloc(size);
}
int main()
{
int *ptr = NULL;
mallocfn(&ptr, sizeof(ptr));
*ptr = 3;
return;
}
Because you need to edit the contents of p and not something pointed b p, so you need to send the pointer variable p's address to the allocating function.
Also check #Will A 's answer
Keeping your example, a proper use of malloc would look more like this:
#include <stdlib.h>
int main()
{
int *ptr = NULL;
ptr = malloc(sizeof(int));
if (ptr != NULL)
{
*ptr = 3;
free(ptr);
}
return 0;
}
If you're learning C I suggest you get more self-motivated to read error messages and come to this conclusion yourself. Let's parse them:
prog.c:1: warning: conflicting types for built-in function ‘malloc’
malloc is a standard function, and I guess gcc already knows how it's declared, treating it as a "built-in". Typically when using standard library functions you want to #include the right header. You can figure out which header based on documentation (man malloc).
In C++ you can declare functions that have the same name as already existing functions, with different parameters. C will not let you do this, and so the compiler complains.
prog.c:3: warning: passing argument 1 of ‘malloc’ makes pointer from integer without a cast
prog.c:3: error: too few arguments to function ‘malloc’
Your malloc is calling itself. You said that the first parameter was void* and that it had two parameters. Now you are calling it with an integer.
prog.c:8: error: ‘NULL’ undeclared (first use in this function)
NULL is declared in standard headers, and you did not #include them.
prog.c:9: warning: implicit declaration of function ‘AllocateMemory’
You just called a function AllocateMemory, without telling the compiler what it's supposed to look like. (Or providing an implementation, which will create a linker error.)
prog.c:12: warning: ‘return’ with no value, in function returning non-void
You said that main would return int (as it should), however you just said return; without a value.
Abandon this whole idiom. There is no way to do it in C without making a separate allocation function for each type of object you might want to allocate. Instead use malloc the way it was intended to be used - with the pointer being returned to you in the return value. This way it automatically gets converted from void * to the right pointer type on assignment.