So I'm new to C and I'm playing around with functions in the GNU C Library when I come across https://www.gnu.org/software/libc/manual/html_node/strfry.html#strfry
Intrigued, I wrote a little tester program:
1 #include <stdio.h>
2 #include <string.h>
3
4 main ()
5 {
6 char *str = "test123abc";
7 char *other;
8
9 other = strfry(str);
10 printf("%s\n", other);
11 return 0;
12 }
gcc test.c outputs test.c:9: warning: assignment makes pointer from integer without a cast
Why?
/usr/include/string.h has the following entry:
extern char *strfry (char *__string) __THROW __nonnull ((1));
How can a char *function(...) return int?
Thanks
Since strfry is a GNU extension, you need to #define _GNU_SOURCE to use it. If you fail to provide that #define, the declaration will not be visible and the compiler will automatically assume that the function returns int.
A related problem, as pointed out by perreal, is that it is undefined behavior to modify a literal string. Once you make the declaration of strfry visible to the compiler, this will be duly reported.
Do note that the strfry function and its cousin memfrob are not entirely serious and are rarely used in production.
To have strfry available, you need
#define _GNU_SOURCE
otherwise the prototype is not exposed and the implicit declaration is assumed to return an int.
The problem is you don't have a prototype in scope for strfry() and the compiler assumes it returns an int. When it wants to assign that int to a char* it complains with the message you specify.
According to my man pages, you need to #define _GNU_SOURCE at the very top of your source code, especially before standard #includes
#define _GNU_SOURCE
/* rest of your program */
You can't modify a literal string:
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
int main () {
char *str = "test123abc";
char other[256];
strcpy(other, str);
strfry(other);
printf("%s\n", other);
return 0;
}
Related
I am cleaning up warnings and found the following error:
warning: assignment makes pointer from integer without a cast buf = aligned_alloc(ALIGN_VALUE,BUF_SZ);
This call is at the very top of the function, essentially:
char* buf;
buf = aligned_alloc(ALIGN_VALUE,BUF_SZ);
It is my understanding that aligned_alloc returns a void *. If cast the return from aligned_alloc to a (char *) I get:
warning: cast to pointer from integer of different size [-Wint-to-pointer-ast] buf = (char*)aligned_alloc(ALIGN_VALUE,BUF_SZ);
The only thing that seems to fix it is
buf = (char*)(uintptr_t)aligned_alloc(ALIGN_VALUE,BUF_SZ);
I have made sure that I am including stdlib.h to avoid implicit declarations referred to in another post. I assumed the cast to char pointer should have resolved this. I am not understanding why the cast to uintptr_t resolves it when void* and uintptr_t are equivalent as far as I understand.
The following is an example of the structure of the file
#include <syslog.h>
#include <linux/fs.h>
#include <linux/hdreg.h>
#include <sys/ioctl.h>
#include <sys/mman.h> // mmap
#include <sys/time.h>
#include <unistd.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <stdio.h>
#include <pthread.h>
void* ax_read_thread(void* arg)
{
fprintf(stderr, "read thread started\n");
ax_priv* priv = (ax_priv*)arg;
char* buf;
uint32_t count = 0;
size_t len, transferred = 0;
buf = (char*)(uintptr_t)aligned_alloc(ALIGN_VALUE,BUF_SZ);
if (buf == NULL){
fprintf(stderr, "Aligned alloc failed\n");
pthread_exit(NULL);
}
while(1){
//do things
}
}
Thank you for all of the help. I see now that the warning is a result of not indicating the proper version when invoking the compiler.
This answer largely summarizes the observations and suggestions from the comments thread, including mine and many others', and wraps them in a bit of expository prose.
In the first place, the problem arises because when you build your program with your present toolchain, in its current form, the aligned_alloc() function is not explicitly declared. In the absence of a declaration, the compiler is inferring its signature: it guesses that the function returns int, and that its parameter types are those obtained via the default argument promotions applied to the types of the actual arguments. The compiler then warns you that those inferences -- especially the return type -- seem inconsistent with how you're actually using the function.
The solution, supposing that the function is available in your C library at all, is to ensure that a correct prototype is provided. You could insert the prototype manually, but you shouldn't. Since it's a standard library function, you should get its declaration from the appropriate header, which for this function is stdlib.h.
HOWEVER, this particular function is new in C11, and evidently you're using a version of GCC that defaults to compiling for an earlier standard. Glibc supports that in part by protecting functions that are new in C11 with a feature-test macro, _ISOC11_SOURCE. This is for your protection: in the event that you're building code written for an earlier standard, and that code happens to provide is own function with the same name as one of C11's new functions, the feature-test system prevents you from suffering a name collision.
If you are indeed writing for C11, as seems to be the case, and if your version of gcc has an option to support C11 (i.e. -std=c11 and/or -std=gnu11), then compiling with that option enabled is your best alternative. If you happen to have a version of Glibc that provides aligned_alloc() but not a version of the compiler that supports a C11 mode, then you have the alternative of manually ensuring that the needed feature test macro is defined to the compiler before any of the standard headers are included. You can do that via a #define at the top of your source file, or via a command-line option to the compiler (e.g. -D_ISOC11_SOURCE=1).
Glibc does have aligned_alloc() from at least version 2.17 (but I think from as early as 2.16). GCC does have a C11 mode since at least version 4.8. If your versions of these components are at least that recent, then it should be sufficient to add the option -std=c11 (to omit GNU extensions) or -std=gnu11 (to support GNU extensions) to your compilation command:
gcc -std=c11 my_program.c
There are old functions such as index, rindex which have now been superseded by strchr and strrchr.
Is there a way to configure the compiler or defines so these functions aren't available?
It can cause confusing warnings when:
accidentally using index name outside of scope for eg - or worse, not warn and use the function in a way that's not intended.
Older GCC versions (4.x) warn when using -Wshadow if you have a variable called index.
See:
http://www.gnu.org/software/libc/manual/html_node/Search-Functions.html#index-index
http://pubs.opengroup.org/onlinepubs/009695399/functions/index.html
Notes:
as #antti-haapala says, the global symbol index shouldn't be redefined since libraries may use it.
This question is regarding the common case when a local variable is called index.
At the time of writing, glibc doesn't mark these functions with the deprecated attribute, so warnings related to using deprecated functions have no effect.
Use the compiler in ISO C mode. The C standard prohibits conforming programs being broken by the presence of identifiers that are not reserved words.
For example, use flags -std=c99.
Sample program:
#include <string.h>
int main()
{
index("abc", 'x');
}
Compiled with -std=c11 -Werror gives:
error: implicit declaration of function 'index' [-Werror=implicit-function-declaration]
You shouldn't redefine these identifiers, as some library that you're linking against could still depend on them existing.
If I understand well, you want to use index as a variable name without conflicting with the index function included in <strings.h>.
In this case you can override using the preprocessor:
#include <stdio.h>
#define index(s, c) deprecated_index(s, c)
#include <strings.h>
int index = 5;
int main(void)
{
printf("%d\n", index);
return 0;
}
Or override index with strchr:
#include <stdio.h>
#include <string.h>
#include <strings.h>
#define index(s, c) strchr(s, c)
int main(void)
{
int index = 5;
char *ptr = index("text", 'x');
printf("%s %d\n", ptr, index);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char aaa[35] = "1.25";
char* bbb = &(aaa[0]);
char** ccc = &(bbb);
float a = strtof(*ccc, ccc);
printf("%f\n", a);
return 0;
}
The code I wrote above should print 1.25, but according to codepad (online C compiler), it does not print 1.25. On codepad, it prints 2097152.000000 . Here's the codepad link
What have I done wrong here?
codepad has an old version of gcc, and presumably of the standard C library. Apparently, strtof is not being declared by the header files you include. (strtof was added in C99.)
Try using an online service with a postdiluvian version of gcc. Or explicitly add the correct declaration:
float strtof(const char* ptr, char** end_ptr);
What's happening is that without the declaration, the compiler defaults the return type of the function to int. Since the function actually returns a float, the float is being interpreted as (not converted to) an integer, and then that integer is converted to a float.
No warning is produced, presumably because -Wall is not in the compiler options, and/or the C standard being used allows the use of non-declared functions.
Right now I am only trying to get my getline() function to work. I have the code from the book and it seems to be identical, but I cant get it to compile. This is homework but this part should be just copying from the book.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//error list
#define ENDOFFILE = -1;
#define TOOMANYNUMS = -2;
#define LIMIT = 256;
//functions declared
int get_line(char line[], int);
//main
main(){
char line[255];
int num[6];
printf("Please input numbers %c: ", line);
get_line(line,LIMIT);
}
//functions
int get_line(char s[],int lim){
int c, i;
for (i=0;i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if(c=='\n'){
s[i]=c;
++i;
}
s[i]='\0';
return i;
}
Now (edited at 10:22) I only get one error:
18 - expected expression before equal
conflicting types for 'getline'
getline might be a function in your standard library, e.g. thisone. If you want to reimplement it, give it a different name.
too few arguments to function 'getline'
You are calling getline() in main() without any arguments, but a few lines above you state that getline takes a char[] and an int. call it like getline(line,sizeof line);
Right now I am only trying to get my getline() function to work.
getline() is a name of Linux function, declared in the stdio.h. C compiler complains that there are two conflicting declarations.
Simply give your getline() function a different name.
Edit1: That:
#define ENDOFFILE = -1;
Should be
#define ENDOFFILE -1
No =, no ; needed for preprocessor directives.
The problem appears to be that the system you are compiling this on appears to have a getline() function already defined, and your definition is conflicting with that. It appears that glibc, the C library used on Linux, has a non-standard getline() function declared in stdio.h. It shouldn't be defined unless you include a line like #define _GNU_SOURCE to opt-in to including non-standard functions, but it may be that this is pre-defined based on how you are compiling your code.
The easiest solution would be to rename your function to something else, but you could also try and find in your compiler options why GNU extensions are being turned on.
Now that you've edited your code, your second problem is that your #define lines are wrong. You don't need an equal or semicolon; these are processed by the preprocessor, which has a different syntax than C, and all you need to do is write #define NAME VALUE.
The proper syntax would be:
#define ENDOFFILE -1
#define TOOMANYNUMS -2
#define LIMIT 256
you need to realize:
it is general an error to write
#define macro like what you wrote,because #define macro is
simply string replacement,so this
statement get_line(line,LIMIT) is
actually get_line(line,=256;)
processed by the compiler,then the
compiling error occurred. Just
change #define LIMIT =256; to
#define LIMIT 256 would be ok.
as is mentioned in the previous
replies,never write codes that
library provided,getline is a function defined in stdio.h.
hope this helps.
What could be the issue here? It doesn't matter what number I choose for str, it is always 26815615859885194199148049996411692254958731641184786755447122887443528060147093953603748596333806855380063716372972101707507765623893139892867298012168192.00
char *str = "2.6";
printf("%f\n", strtof(str, (char**)NULL));
//prints 26815615859885194199148049996411692254958731641184786755447122887443528060147093953603748596333806855380063716372972101707507765623893139892867298012168192.00
whole program:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *str = "2.6";
printf("%f\n", strtof(str, NULL));
return 1;
}
compile with -Wall:
test4.c:7: warning: implicit declaration of function âstrtofâ
What platform are you building for/on? The warning that you say is being emitted:
test4.c:7: warning: implicit declaration of function âstrtofâ
indicates that the compiler doesn't know that strtof() returns a float, so it's going to push an int to the printf() call instead of a double. strtof() is normally declared in stdlib.h, which you're including. But it wasn't a standard function until C99, so the exact compiler platform (and configuration/options you're using) may affect whether it's being made available or not.
strtof is defined in C99 only. It may be that passing the option -std=c99 to the compiler will fix it since default GCC (-std=gnu89) includes only a few C99 features.
Another option is to use the C89-kosher strtod. Which is probably the better option in the long run, anyways. (When do you need singles except in exceptional circumstances?)
Perhaps you've forgotten to include the correct header(s)?
#include <stdlib.h>
#include <stdio.h>
int main() {
printf("%f\n", strtof("2.6", NULL));
return 0;
}
produces:
2.600000
for me...
Given your warnings, you should try adding -std=c99 to get the C99 standard definitions from the header. By default it will assume that the return value is an int and then try to convert that to a float. This will obviously be wrong. Alternatively you could simply supply your own, correct declaration for strtof().
As the others have said, you need -std=c99. But you can also use strtod() which is string to double, and you don't need -std=c99 for that.
I was having problems with strtof() on CentOS 5.5 with glibc 2.5 unless I used -std=c99, but strtod() worked perfectly.