open_memstream warning "pointer from integer without a cast" - c

I'm writing some C code for an embedded linux system using an open_memstream and I don't understand why I am getting a compile warning: assignment makes pointer from integer without a cast
To make things simple, rather than pasting all my code I reproduced the problem with the small example from here:
#include <stdio.h>
#include <stdlib.h>
int
main (void)
{
FILE *stream;
char *buf;
size_t len;
off_t eob;
stream = open_memstream (&buf, &len);
if (stream == NULL)
/* handle error */ ;
fprintf (stream, "hello my world");
fflush (stream);
printf ("buf=%s, len=%zu\n", buf, len);
eob = ftello(stream);
fseeko (stream, 0, SEEK_SET);
fprintf (stream, "good-bye");
fseeko (stream, eob, SEEK_SET);
fclose (stream);
printf ("buf=%s, len=%zu\n", buf, len);
free (buf);
return 0;
}
The code works, but the compiler complains about the line stream = open_memstream (&buf, &len);
What integer is it talking about? We're passing in a pointer to a size_t as required by the function prototype.
FILE *open_memstream(char **bufp, size_t *sizep);
Is there a problem with this code, or do I need to take a look at my compiler? I want to get rid of this warning the right way.
UPDATE:
Using gcc 4.3.2, glibc 2.9
UPDATE 2:
Tried the following:
powerpc-860-linux-gnu-gcc -std=c99 -Wall -D_XOPEN_SOURCE=700 -c source.c
Result:
source.c: In function 'main':
source.c:12: warning: implicit declaration of function 'open_memstream'
source.c:12: warning: assignment makes pointer from integer without a cast
According to this, it seems that _XOPEN_SOURCE=700 is available since glibc 2.10.
Since I'm using glibc 2.9, what other alternatives do I have (other than upgrading glibc)?
UPDATE 3:
Adding the following got rid of the warning:
extern FILE *open_memstream(char **bufp, size_t *sizep);
Is there anything wrong with this solution?
UPDATE 4:
This worked instead of the extern:
powerpc-860-linux-gnu-gcc -std=c99 -Wall -D_GNU_SOURCE -c ops_cmds.c
So according to the manpage, need to use _GNU_SOURCE if glibc pre-2.10 (in my case) and _XOPEN_SOURCE=700 if 2.10+

Define:
#define _POSIX_C_SOURCE 200809L
or
#define _XOPEN_SOURCE 700
in your source code before including stdio.h. Or with gcc you can define and pass the macro value to the source file with -D option:
gcc -std=c99 -Wall -D_XOPEN_SOURCE=700 -c source.c
open_memstream is a POSIX function and its declaration is not visible in your program without this define.

The compiler is complaining about the return value of open_memstream, not about the arguments you pass in.
Your open_memstream is not declared, i.e. the compiler does not see the prototype. So the compiler (apparently pre-C99) assumes that it returns an int. You are forcing that int into stream pointer, which is what triggers the warning about "making pointer form integer".
Make sure open_memstream is declared before you attempt to use it. The prototype is supposed to reside in stdio.h, but it is only available in POSIX.1-2008. You have to enable it explicitly (see other answers).

Related

No output from split up source, but no warnings either, when omitting an included file

I ran into an issue invoking gcc where if I omit a library .c file, I got no output from the binary (unexpected behavior change) but since this is a missing dependency, I kind of expected the compile to fail (or at least warn)...
Example for this issue is from Head First C page 185 (but is not errata, see my compile mis-step below):
encrypt.h:
void encrypt(char *message);
encrypt.c:
#include "encrypt.h"
void encrypt(char *message)
{
// char c; errata
while (*message) {
*message = *message ^ 31;
message++;
}
}
message_hider.c:
#include <stdio.h>
#include "encrypt.h"
int main() {
char msg[80];
while (fgets(msg, 80, stdin)) {
encrypt(msg);
printf("%s", msg);
}
}
NOW, everything works fine IF I faithfully compile as per exercise instruction:
gcc message_hider.c encrypt.c -o message_hider
... but bad fortune led me to compile only the main .c file, like so:
$ gcc message_hider.c -o message_hider
This surprisingly successfully builds, even if I added -Wall -Wextra -Wshadow -g.
Also surprisingly, it silently fails, with no output from encrypt() function:
$ ./message_hider < ./encrypt.h
$
my gcc is:
$ /usr/bin/gcc --version
Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: x86_64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Mindful that even with a Makefile, I could "still" end up with a missing .c file due to a mistake in the recipe.
Q: Is it possible to force a hard error if I forget to tell gcc about a .c file?
As I noted in a (misspelled) comment:
There is probably a function encrypt() in the system library.
On a Mac, man -s 3 encrypt shows:
CRYPT(3) BSD Library Functions Manual CRYPT(3)
NAME
crypt, encrypt, setkey -- DES encryption
SYNOPSIS
#include <unistd.h>
char *
crypt(const char *key, const char *salt);
void
encrypt(char *block, int edflag);
#include <stdlib.h>
void
setkey(const char *key);
…
The encrypt() and setkey() functions are part of POSIX, so they'll be available on most POSIX-like systems. Curiously, as shown in the manual page extract, the functions are declared in separate headers — <unistd.h> for encrypt() and
<stdlib.h> for setkey(). There's probably a good (enough) historical reason for the disconnect.
You should have received a compiler warning about the function being undeclared — if you didn't, you are presumably compiling using the C90 standard. That is very old and should not still be being taught; you need to be learning C11 or C18 (almost the same).
Since C99, the C standard requires functions to be declared before use — you can define a static function without pre-declaring it, but all other functions (except main()) should be declared before they are used or defined. You can use GCC compiler warning options such as -Wmissing-prototypes -Wstrict-prototypes (along with -Wold-style-declaration and -Wold-style-definition) to trigger warnings. Of these, -Wold-style-declaration is enabled by -Wextra (and none by -Wall). Be aware: as noted in the comments, clang does not support -Wold-style-declaration though true GCC (not Apple's clang masquerading as gcc) does support it.

using c11 standard with clang for use of strcpy_s

I'm running OS X Sierra and trying to compile a c program that uses strcpy_s, but my installed clang compiler is using the c99 standard, but from what I've read strcpy_s requires c11.
Here's the code I'm trying to compile
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char source[] = "Test string";
char destination[50];
if(strcpy_s(destination, sizeof(destination), source))
printf("string copied - %s",destination);
return 0;
}
And here's the command I'm using to compile
$ clang copytest.c -o copytest
copytest.c:11:5: warning: implicit declaration of function 'strcpy_s' is invalid in C99 [-Wimplicit-function-declaration]
if(strcpy_s(copied_string, sizeof(copied_string), source))
^
1 warning generated.
Undefined symbols for architecture x86_64:
"_strcpy_s", referenced from:
_main in copytest-e1e05a.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I've tried compiling with the standard flag...
clang -std=c11 copytest.c -o copytest
but I get the same exact "invalid in c99" warning. I've also tried compiling with gcc instead, and I still get the same c99 warning.
I tried upgrading via homebrew which shows the following
Warning: gcc 9.2.0 is already installed and up-to-date
I have clang version 9.0.0
$ clang -v
Apple LLVM version 9.0.0 (clang-900.0.39.2)
My xcode version is Xcode 9.2, which from everything I've read should come with c11 support.
Am I doing something wrong with the compiling, is my code itself incorrect? This is the only similar question I found on here, but it didn't even have an answer. Thanks
The _s functions are an optional component of the 2011 C standard (Annex K), and, to the best of my knowledge, they have never been implemented as an integrated part of any C library. Portable code cannot rely on their availability. (Microsoft's C compilers for Windows implement an overlapping set of functions with the same names but different semantics (and sometimes even a different argument list), and at least one bolt-on implementation does exist. See this old answer, and the much longer question and answer it links to, for more detail.)
Also, the _s functions do not solve the problem that they were intended to solve (unsafe string handling); it is necessary to put actual thought into a proper fix for each use of strcpy, instead of globally search-and-replacing strcpy with strcpy_s, etc., as was the hope of the authors of Annex K. If you do put appropriate amounts of thought into a proper fix, you won't need any of the _s functions to implement it. For instance, here's a fixed version of your example program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char source[] = "Test string";
char destination[50];
size_t srclen = strlen(source);
if (srclen + 1 > sizeof destination) {
fprintf(stderr, "string too long to copy - %zu bytes, need %zu\n",
sizeof destination, srclen + 1);
return 1;
} else {
memcpy(destination, source, srclen + 1);
printf("string copied - %s\n", destination);
return 0;
}
}
And here's an even better version:
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "usage: ./test 'message of arbitrary length'\n");
return 1;
}
char *destination = strdup(argv[1]);
if (!destination) {
perror("strdup");
return 1;
}
printf("string copied - '%s'\n", destination);
free(destination);
return 0;
}
Therefore: Never use any of the _s functions. If you need to write a program that compiles on Windows with no warnings, put #define _CRT_SECURE_NO_WARNINGS 1 at the top of each file to make MSVC stop giving you bad advice.
If all, or even most, programmers wrote the suggested solutions above all the time, then these functions wouldn't be needed. We have a lot of evidence that many programmers do not write such careful code, going back to Spaf's notes on the Robert T Morris finger worm in the late 1980's.
You also would prefer not to have to duplicate 10 lines of code for every call site of strcpy. That leads to unreadable code. More so, what zwol suggests is really just an implementation of the function he claims we don't need. A good programmer would take that, stick it in a header, and name it something helpful, maybe checked_strcpy? Or even strcpy_s?
The second suggested implementation, which is purportedly better is not - it would cause an allocation when we might already have a buffer. Allocations are expensive, using this approach everywhere would be bad for perf. It also introduces new complexity because now we'd have to free every duplicated string - imagine doing that with repeated calls to strcat.
There is a fairly nicely done cross-platform implementation here:
https://github.com/intel/safestringlib
I'm also not sure whether this is actually any different, but worth taking a look - https://github.com/coruus/safeclib

putw() function in C

Following program with putw is not writing the required data in the file.
#include <stdio.h>
int main(void)
{
FILE *fp;
fp = fopen("a.txt", "w");
putw(25,fp);
putw(325,fp);
putw(425,fp);
fclose(fp);
return 0;
}
Program is compiled and executed like the following
gcc filename.c
./a.out
It is writing something in the file. Also if we read the integer using getw(), it is reading the value which is not available in the file. Even it is not the ASCII value.
When it is compiled with gcc filename.c -std=c99, it is showing implicit declaration warning error.
Is it required to link any library files to use putw/getw in c.
There is no function called putw in standard C, which is why you get compiler warnings. You probably meant to use putwc in wchar.h.
putw is an ancient function that exists on some platforms. Use fwrite and fread instead. You should also check the return value from putw. It may be telling you why it is failing.

How are library functions are linked in this case?

I just come across this code and the blog says this works fine on 32 bit architecture. I didn't test it; however, I have a doubt about the linkage of libraries in this case. How will the compiler link the string library to main since its not aware which library to link?
So basically if I include <string.h> then it should work fine; however, if I don't include <string.h> then, as per the blog, it runs in 32 bit architecture and fails to run on 64 bit architecture.
#include <errno.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "%s\n", strerror(errno));
return errno;
}
printf("file exist\n");
fclose(fp);
return 0;
}
The code shown will only compile if you allow the compiler to infer that functions that are not declared always return an int. This was valid in C89/C90 but marked obsolescent; C99 and C11 require functions to be declared before they are used. GCC prior to version 5.1.0 assumes C90 mode by default; you had to turn the 'reject this code' warnings on. GCC 5.1.0 and onwards assumes C11 by default. You will at least get warnings from the code even without any compilation options to turn them on.
The code will link fine because the function name is strerror() regardless of whether it was declared or not, and the linker can find the function in the standard C library. In general, all the functions that are in the Standard C library are automatically made available for linking — and, indeed, there are usually a lot of not so standard functions also available. C does not have type-safe linkage as C++ does (but C++ also insists on having every function declared before it is used, so the code would not compile as C++ without the header.)
For historical reasons, the maths library was separate and you needed to specify -lm in order to link it. This was in large part because hardware floating point was not universal, so some machines needed a library using the hardware, and other machines needed software emulation of the floating point arithmetic. Some platforms (Linux, for example) still require a separate -lm option if you use functions declared in <math.h> (and probably <tgmath.h>); other platforms (Mac OS X, for example) do not — there is a -lm to satisfy build systems that link it, but the maths functions are in the main C library.
If the code is compiled on a fairly standard 32-bit platform with ILP32 (int, long, pointer all 32-bit), then for many architectures, assuming that strerror() returns an int assumes that it returns the same amount of data as if it returns a char * (which is what strerror() actually returns). So, when the code pushes the return value from strerror() onto the stack for fprintf(), the correct amount of data is pushed.
Note that some architectures (notably the Motorola M680x0 series) would return addresses in an address register (A0) and numbers in a general register (D0), so there would be problems even on those machines with a 32-bit compilation: the compiler would try to get the returned value from the data register instead of the address register, and that was not set by strerror() — leading to chaos.
With a 64-bit architecture (LP64), assuming strerror() returns a 32-bit int means that the compiler will only collect 32-bits of the 64-bit address returned by strerror() and push that on the stack for fprintf() to work with. When it tried to treat the truncated address as valid, things would go awry, often leading to a crash.
When the missing <string.h> header is added, the compiler knows that the strerror() function returns a char * and all is happiness and delight once more, even when the file the program is told to look for doesn't exist.
If you are wise, you will ensure your compiler is always compiling in fussy mode, rejecting anything which is plausibly erroneous. When I use my default compilation on your code, I get:
$ gcc -std=c11 -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes \
> -Wstrict-prototypes -Wold-style-definition bogus.c -o bogus
bogus.c: In function ‘main’:
bogus.c:10:33: error: implicit declaration of function ‘strerror’ [-Werror=implicit-function-declaration]
fprintf(stderr, "%s\n", strerror(errno));
^
bogus.c:10:25: error: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Werror=format=]
fprintf(stderr, "%s\n", strerror(errno));
^
bogus.c:10:25: error: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Werror=format=]
bogus.c:4:14: error: unused parameter ‘argc’ [-Werror=unused-parameter]
int main(int argc, char *argv[])
^
cc1: all warnings being treated as errors
$
The 'unused argument' error reminds you that you should be checking that there is an argument to pass to fopen() before you try to open the file.
Fixed code:
#include <string.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
if (argc != 2)
{
fprintf(stderr, "Usage: %s file\n", argv[0]);
return 1;
}
fp = fopen(argv[1], "r");
if (fp == NULL)
{
fprintf(stderr, "%s: file %s could not be opened for reading: %s\n",
argv[0], argv[1], strerror(errno));
return errno;
}
printf("file %s exists\n", argv[1]);
fclose(fp);
return 0;
}
Build:
$ gcc -std=c11 -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes \
> -Wstrict-prototypes -Wold-style-definition bogus.c -o bogus
$
Run:
$ ./bogus bogus
file bogus exists
$ ./bogus bogus2
./bogus: file bogus2 could not be opened for reading: No such file or directory
$ ./bogus
Usage: ./bogus file
$
Note that the error messages include the program name and report to standard error. When the file is known, the error message includes the file name; it is much easier to debug that error if the program is in a shell script than if the message is just:
No such file or directory
with no indication of which program or which file encountered the problem.
When I remove the #include <string.h> line from the fixed code shown, then I can compile it and run it like this:
$ gcc -o bogus90 bogus.c
bogus.c: In function ‘main’:
bogus.c:18:35: warning: implicit declaration of function ‘strerror’ [-Wimplicit-function-declaration]
argv[0], argv[1], strerror(errno));
^
$ gcc -std=c90 -o bogus90 bogus.c
$ ./bogus90 bogus11
Segmentation fault: 11
$
This was tested with GCC 5.1.0 on Mac OS X 10.10.5 — which is, of course, a 64-bit platform.
I solved with including strings.h header
#include <string.h>
I don't think the functionality of this code would be affected by whether its 32-bit or 64-bit architecture: it doesn't matter if pointers are 32- or 64-bit, and if long int is 32 or 64 bit. Inclusion of headers, in this case string.h, should not affect linking to libraries, either. Header inclusion matters to the compiler, not linker. The compiler might warn about the function being implicitly declared, but as long as the linker can find the function in one of the libraries being searched by it, it will successfully link the binary, and it should run just fine.
I just built and ran this code successfully on a 64-bit CentOS box, using clang 3.6.2. I did get this compiler warning:
junk.c:10:33: warning: implicitly declaring library function 'strerror' with type 'char *(int)'
fprintf(stderr, "%s\n", strerror(errno));
^
junk.c:10:33: note: include the header <string.h> or explicitly provide a declaration for 'strerror'
1 warning generated.
The program was given a non-existent file name, and the error message, "No such file or directory," was meaningful. However, this is because the strerror() function is a well-known standard library function, and its declaration was correctly guessed by the compiler. If it is a user-defined function, the compiler may not be so "lucky" at guessing, and then the architecture can matter, as suggested by other answers.
So, the lesson learned: make sure function declarations are available to the compiler and heed the warnings!

How do I remove the following 'implicit declaration of function' warnings?

How do I compile the lex file with gcc without receiving the following warnings?
lex.yy.c: In function `yy_init_buffer':
lex.yy.c:1688: warning: implicit declaration of function `fileno'
lex.l: In function `storeLexeme':
lex.l:134: warning: implicit declaration of function `strdup'
These are the libraries I included.
%{
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
%}
The function yy_init_buffer is not in the file. The following is the function storeLexeme.
int storeLexeme() {
for (int i = 0; i < count; i++) {
char *curr = *(symbolTable + i);
if (strcmp(curr, yytext) == 0) {
return i;
}
}
char *lexeme = (char *)malloc(sizeof(char *));
lexeme = (char *)strdup(yytext);
symbolTable[count] = lexeme;
count++;
return (count - 1);
}
How do I remove the warnings?
Neither strdup nor fileno are ISO C functions, they're part of POSIX.
Now whether they're available on your platform depends on your platform.
If you are using the Microsoft tools, you may want to look into _fileno for the latter (fileno was deprecated in VC2005). A rather excellent version of strdup can be found here.
Although, having blown my own horn with that code, you could also use _strdup since it replaces the also-deprecated strdup :-)
These should hopefully work okay as-is since they're in stdio.h and string.h, two of the include files you're already using.
If you're on a UNIX derivative, those functions should be available in stdio.h (for fileno) and string.h (for strdup). Given that it looks like you're already including those files, the problem is likely elsewhere.
One possibility is if you're compiling in one of the strict modes like __STRICT_ANSI__ in gcc), where neither would be defined.
You should have a look at the top of your generated lex.yy.c and lex.l files to confirm that the header files are being included and also check the command line parameters you're passing to the compiler.
I suggest this option (tell the compiler you are using POSIX):
#define _POSIX_C_SOURCE 1
People seem to have tightened up the feature controls in recent years and hopefully when the consistency is good and widespread we can throw away the automake garbage.
I also had this problem while using flex.
I used -std=gnu99rather than -std=c99 which solved the problem.
flex lang.l && gcc -o lexer -std=gnu99 lex.yy.c -lfl
Consider adding the following line:
extern char *strdup(const char *s);
I faced the problem when I compiled with -std=c99 -pedantic -pedantic-errors. Adding the above line solved the problem for me.
You declare the function before you use it:
//declare the function
int storeLexeme();
//use the function here
or include the header where the function is declared.
C implicitly assumes undeclared functions have return type int and deduces the parameters from how you call the function. This is deprecated in C++.
just place your function below the library calls it will be alright;

Resources