在gcc语句表达式中声明数组并返回指向它的指针?

在gcc语句表达式中声明数组并返回指向它的指针?,c,arrays,gcc,macros,c-preprocessor,C,Arrays,Gcc,Macros,C Preprocessor,我已经考虑过了。 这是代码: #define IP_VAL(id) ({ \ char ip[32] = {0}; \ sprintf(ip,"192.168.0.%d",id&0xff); \ (char *)ip; \ }) 它确实有效,但我想知道问题是否会由宏引起 我是这样用的: function(IP_VAL(id)); main(){ int a = 1; int b = 2; a = b; a = ({

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

#define IP_VAL(id) ({ \
    char ip[32] = {0}; \
    sprintf(ip,"192.168.0.%d",id&0xff); \
    (char *)ip; \
})
它确实有效,但我想知道问题是否会由宏引起

我是这样用的:

function(IP_VAL(id));
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;
    });
}
但我不确定这是否绝对可以。
ip[32]
是否超出操作范围

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

我已经测试了如下简单示例:

function(IP_VAL(id));
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 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
080483ed:
80483ed:55%推压ebp
80483ee:89 e5 mov%esp%ebp
80483f0:83 ec 20子$0x20,%esp
80483f3:c7 45 e0 01 00移动$0x1,-0x20(%ebp)
80483fa:C745E40200MOVL$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移动$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 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 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移动$0x6,-0xc(%ebp)
8048435:c7 45 f8 07 00 00 movl$0x7,-0x8(%ebp)
804843c:c7 45 fc 08 00 movl$0x8,-0x4(%ebp)
8048443:c9离开
8048444:c3 ret
所以我认为'c'和'd'就像'a'和'b',它们是'main()'堆栈中的变量。区别在于它们的范围。在这个例子中,每个“c”都有不同的地址


我认为宏“IP_VAL”可以工作,但我不知道gcc编译选项是否会影响它?

这不是标准C,而是gcc扩展。它没有被安全地使用

ip
数组的生存期限制在其声明的范围内。您将返回一个指向该数组的指针,指向语句表达式的外部,该数组不再存在。有些人认为生命周期就是完整表达式的持续时间,但GCC文档中似乎没有任何内容支持这一说法。取消引用此指针可能会导致任何结果。它似乎完全靠运气起作用

将数组声明为
static
将解决此问题,但是静态本地数组允许您编写一个不依赖于gcc扩展的简单函数

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

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

这个版本没有指向任何可能过期的局部变量的指针。< /P> C或C++?选择一个或另一个,而不是两个。这当然不好。使用函数。宏不是函数!我删除了C++标签,因为你要的是C,而你的代码没有显示任何C++。C和C++是不同的语言,也注意到是GCC扩展。这不是一个标准的C功能。这是一个不错的功能,但我无法理解两个示例之间的本质区别。一个版本有(1)一个作用域变量和(2)一个指向在作用域之外访问的变量的指针。另一个具有(1)临时结构内的临时数组,该临时结构衰减为指向其第一个元素的指针(2),该指针在该临时结构仍处于活动状态时被访问。为了更好地将其可视化,请将两个宏都重写为函数。一个返回一个指向其局部变量的指针,另一个返回一个按值的结构。为什么不简单:#define IP_VAL(id)({\char IP[32]={0};\sprintf(IP,“192.168.0.%d”,id&0xff);\IP;\})我假设它按值返回数组,类型为char[32]因此,在家长中使用是安全的expression@user377178不能按值传递数组,没有这样的东西。正因为如此,我现在可以看到这个。谢谢我的实验表明,gcc即使在通过指针时也会保留缓冲区。不过,安全总比抱歉好。