Code as below:
#include"stdio.h"
#define MySTRING(ident, str) \
({\
char str_##ident[16]; \
memset((char *)str_##ident, 0x00, sizeof(str_##ident)); \
memcpy(str_##ident, (str), strlen((str))); \
str_##ident; \
})
int main(int argc, char **argv)
{
printf("%u, %u\n", MySTRING(qw, "1.1.1.1"), MySTRING(er, "2.2.2.2"));
}
Tetst result:
[root@cza temp]# gcc -O0 ./fly.c
[root@cza temp]# ./a.out
3959297344, 3959297360
[root@cza temp]# gcc -O2 ./fly.c
[root@cza temp]# ./a.out
2017090240, 2017090240
It seems like gcc optimistic make a difference on it.
The second result is not what I want, but in my app build template, O2 have been set.
I'd like to know the detail on why O2 make it difference, or is it a bug on GCC?
PS My colleague told me the prefix "volatile" can work.
Your code is a gcc extension called Statement Expression . The statements in the braces are executed, and the value of the final statement is the value of the expression. Any objects created are destroyed when the statement ends.
Being in a macro makes no difference; your code (update: the original code) is:
printf("%u, %u\n", ({ char ip_qw[16]; ip_qw; }), ({ char ip_er[16]; ip_er; }) );
When the ip_qw
block ends, ip_qw
is destroyed, so that memory is freed up for ip_er
to use. This explains why it is possible to see the same address for both.
Your code is invalid because the printf
function will access the contents of the 16-byte arrays after they have been destroyed.
Fortunately, Standard C has a solution. Objects that are returned by value are guaranteed to hang around until the end of the statement in which the function call was made. Arrays can't be returned by value, but structs can, so we can go:
#include <stdio.h>
#include <string.h>
struct MS
{
char str[16];
};
struct MS make_MS(char const *str)
{
struct MS ms;
strcpy(ms.str, str);
return ms;
}
#define MySTRING(s) make_MS(s).str
int main(int argc, char **argv)
{
printf("%s, %s\n", MySTRING("1.1.1.1"), MySTRING("2.2.2.2"));
}
Notes:
%p
to print pointers (makes a difference on 64bit system) memset
and memcpy
was not any safer than strcpy
; in robust code you should change this strcpy
to a snprintf(ms.str, sizeof ms.str, "%s", str);
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.