在gcc statement-expression中声明一个数组并返回一个指向它的指针? [英] Declare an array in gcc statement-expression and return a pointer to it?

查看:231
本文介绍了在gcc statement-expression中声明一个数组并返回一个指向它的指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经考虑过了。
这是代码:

  #define IP_VAL(id)({\ 
char ip [32] = {0}; \
sprintf(ip,192.168.0。%d,id& 0xff); \
(char *)ip; \
})

它确实有效,但我想知道宏是否会引发问题?



我是这样使用的:

  function(IP_VAL(id)); 

但我不确定这是否完全正常。 ip [32] 是否超出了操作范围?



非常感谢您编辑我的问题:)



我已经测试过这样简单的例子:

  main ){
int a = 1;
int b = 2;
a = b;
a =({
int c = 3;
c;
});
a =({
int d = 4;
d;
});
a =({
int c = 5;
c;
});
({
int c = 6;
c;
});
({
int c = 7;
c;
});
({
int c = 8;
c;
});
}



和objdump它:

  080483ed< main> ;: 
80483ed:55 push%ebp
80483ee:89 e5 mov%esp,%ebp
80483f0:83 ec 20 sub $ 0x20,%esp
80483f3:c7 45 e0 01 00 00 00 movl $ 0x1,-0x20(%ebp)
80483fa:c7 45 e4 02 00 00 00 movl $ 0x2,-0x1c( %ebp)
8048401:8b 45 e4 mov -0x1c(%ebp),%eax
8048404:89 45 e0 mov%eax,-0x20(%ebp)
8048407:c7 45 e8 03 00 00 00 movl $ 0x3,-0x18(%ebp)
804840e:8b 45 e8 mov -0x18(%ebp),%eax
8048411:89 45 e0 mov%eax,-0x20(% ebp)
8048414:c7 45 ec 04 00 00 00 movl $ 0x4,-0x14(%ebp)
804841b:8b 45 ec mov -0x14(%ebp),%eax
804841e: 89 45 e0 mov%eax,-0x20(%ebp)
8048421:c7 45 f0 05 00 00 00 movl $ 0x5,-0x10(%ebp)
80 48428:8b 45 f0 mov -0x10(%ebp),%eax
804842b:89 45 e0 mov%eax,-0x20(%ebp)
804842e:c7 45 f4 06 00 00 00 movl $ 0x6 ,-0xc(%ebp)
8048435:c7 45 f8 07 00 00 00 movl $ 0x7,-0x8(%ebp)
804843c:c7 45 fc 08 00 00 00 movl $ 0x8,-0x4( %ebp)
8048443:c9离开
8048444:c3 ret

认为'c'和'd'就像'a'和'b'一样,它们是'main()'堆栈中的变量。区别在于它们的范围。在这个例子中,每个'c'都有不同的地址。



我认为宏'IP_VAL'有效,但我不知道gcc编译选项会影响它,不是?

解决方案

这不是标准的C,而是一个gcc扩展。它不被安全地使用。



ip 数组的生存期限制在它声明的范围内。您正在将此数组的指针返回到statement-expression的外部,其中该数组不再存在。有些人认为,终身是完整表达的持续时间,但GCC文档中没有任何内容似乎支持这种说法。解引用这个指针可能会导致任何事情。它看起来很幸运。



将数组声明为 static 将解决问题,但接下来是静态的本地数组可以让你编写一个不依赖于gcc扩展的简单函数。



另一种解决问题的方法如下:

  #define IP_VAL(id)\ 
(\
(\
{\
struct {char ip [32];} p; \
sprintf(p.ip,192.168.0。%d,id& 0xff); \
p; \
} \
).ip \

该版本没有指向任何可能过期的本地变量的指针。


I have thought about it. And this is the code:

#define IP_VAL(id) ({ \
    char ip[32] = {0}; \
    sprintf(ip,"192.168.0.%d",id&0xff); \
    (char *)ip; \
})

It really works, but I wonder whether problems will be caused by the macro?

I used it like this:

function(IP_VAL(id));

But I am not sure it is absolutely OK. Is the ip[32] out of the action scope?

Thank you very much for editing my question : )

I have tested the simple example like this:

main(){
    int a = 1;
    int b = 2;
    a = b;
    a = ({
            int c = 3;
            c;
        });
    a = ({
            int d = 4;
            d;
        });
    a = ({
            int c = 5;
            c;
        });
    ({
        int c = 6;
        c;
    });
    ({
        int c = 7;
        c;
    });
    ({
        int c = 8;
        c;
    });
}

And objdump it:

080483ed <main>:
 80483ed:   55                      push   %ebp
 80483ee:   89 e5                   mov    %esp,%ebp
 80483f0:   83 ec 20                sub    $0x20,%esp
 80483f3:   c7 45 e0 01 00 00 00    movl   $0x1,-0x20(%ebp)
 80483fa:   c7 45 e4 02 00 00 00    movl   $0x2,-0x1c(%ebp)
 8048401:   8b 45 e4                mov    -0x1c(%ebp),%eax
 8048404:   89 45 e0                mov    %eax,-0x20(%ebp)
 8048407:   c7 45 e8 03 00 00 00    movl   $0x3,-0x18(%ebp)
 804840e:   8b 45 e8                mov    -0x18(%ebp),%eax
 8048411:   89 45 e0                mov    %eax,-0x20(%ebp)
 8048414:   c7 45 ec 04 00 00 00    movl   $0x4,-0x14(%ebp)
 804841b:   8b 45 ec                mov    -0x14(%ebp),%eax
 804841e:   89 45 e0                mov    %eax,-0x20(%ebp)
 8048421:   c7 45 f0 05 00 00 00    movl   $0x5,-0x10(%ebp)
 8048428:   8b 45 f0                mov    -0x10(%ebp),%eax
 804842b:   89 45 e0                mov    %eax,-0x20(%ebp)
 804842e:   c7 45 f4 06 00 00 00    movl   $0x6,-0xc(%ebp)
 8048435:   c7 45 f8 07 00 00 00    movl   $0x7,-0x8(%ebp)
 804843c:   c7 45 fc 08 00 00 00    movl   $0x8,-0x4(%ebp)
 8048443:   c9                      leave  
 8048444:   c3                      ret

So I think the 'c' and the 'd' is just like 'a' and 'b',they are the variables in the stack of 'main()'. The difference is their scopes. And in the example, every 'c' has different addresses.

I think the macro 'IP_VAL' works, but I do not know the gcc compile option will affect it or not ?

解决方案

This is not standard C but a gcc extension. It is not being used safely.

The lifetime of the ip array is restricted to the scope it is declared in. You are returning a pointer into this array to the outsides of the statement-expression, where the array no longer exists. Some people suggest that the lifetime is the duration of the full expression, but nothing in GCC documentation seems to support this claim. Dereferencing this pointer may result in anything. It appears to work by sheer luck.

Declaring the array as static will fix the problem, but then a static local array lets you write a simple function which doesn't depend on a gcc extension.

Another way to cope with the problem is as follows:

#define IP_VAL(id) \
    ( \
     ( \
      { \
       struct { char ip[32]; } p; \
       sprintf (p.ip, "192.168.0.%d", id&0xff); \
       p; \
      } \
     ).ip \
    )

This version doesn't have any pointers that point to any potentially expired local variables.

这篇关于在gcc statement-expression中声明一个数组并返回一个指向它的指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆