gcc优化离开复合语句

gcc优化离开复合语句,c,generics,gcc,vector,memcpy,C,Generics,Gcc,Vector,Memcpy,我在c语言中为一个通用的可调整大小的向量实现push_-back操作符时遇到了一个问题。对于泛型,我需要使用一个void指针作为参数,但实际上我希望直接给它赋值 当我用gcc-ottest.c-std=c99编译下面的代码时,它会像我预期的那样打印10。 当我将-O1(或更高版本)添加到编译选项时,程序将打印0 我认为问题出在smempy代码中,因为当我将其替换为memcpy时,我不再有这个问题 简化代码: #include <stdio.h> #include <stdlib

我在c语言中为一个通用的可调整大小的向量实现push_-back操作符时遇到了一个问题。对于泛型,我需要使用一个void指针作为参数,但实际上我希望直接给它赋值

当我用
gcc-ottest.c-std=c99编译下面的代码时,它会像我预期的那样打印
10
。 当我将
-O1
(或更高版本)添加到编译选项时,程序将打印
0

我认为问题出在
smempy
代码中,因为当我将其替换为
memcpy
时,我不再有这个问题

简化代码:

#include <stdio.h>
#include <stdlib.h>

#define get_pointer(value) ({ __typeof__(value) tmp = value; &tmp; })

// copy from src to dst byte by byte
void* smemcpy(void* dst, void const * src, size_t len) {
    char * pdst = (char *) dst;
    char const * psrc = (char const *) src;

    while (len--) {
        *pdst++ = *psrc++;
    }

    return (dst);
}


int main() {
    void* container = malloc(sizeof(int));

    // copy a 10 into the container via a temporary pointer
    smemcpy(container, get_pointer(10), sizeof(int));

    printf("%d\n", ((int*)container)[0]);

    return 0;
}
#包括
#包括
#定义get_指针(值)({{uuuuuuuuuuuuuu类型(值)tmp=value;&tmp;})
//逐字节从src复制到dst
空隙*smemcpy(空隙*dst,空隙常数*src,尺寸长度){
char*pdst=(char*)dst;
char const*psrc=(char const*)src;
而(len--){
*pdst++=*psrc++;
}
返回(dst);
}
int main(){
void*container=malloc(sizeof(int));
//通过临时指针将10复制到容器中
smempy(容器,get_指针(10),sizeof(int));
printf(“%d\n”,((int*)容器)[0]);
返回0;
}
提前感谢您的帮助


B

也许问题出在宏观方面。tmp变量是在一个块中定义的,我猜这个块在赋值之后,也就是说,在输入SMEMPY之前,会立即离开。这样,变量的地址就变得毫无意义了。地址可能会被一些重新利用内存的优化覆盖,或者在未优化的构建中保持不变。只是一个想法,无法确认。

也许问题出在宏观方面。tmp变量是在一个块中定义的,我猜这个块在赋值之后,也就是说,在输入SMEMPY之前,会立即离开。这样,变量的地址就变得毫无意义了。地址可能会被一些重新利用内存的优化覆盖,或者在未优化的构建中保持不变。只是一个想法,无法确认。

获取指针的定义使用表达式中的语句,这是一个。这方面的语义几乎没有文档记录,没有理由相信在语句表达式中声明的对象的存储持续时间会持续到语句的计算之后

因此,在准备对
smempy
的调用时,编译器可以通过创建对象
tmp
,生成其地址作为语句表达式的值,并销毁对象
tmp
来计算
get\u指针
。然后将不再存在的对象的现在无效的地址传递给
smempy
,它复制无效数据,因为
tmp
所用的空间已被重新用于其他目的

当使用
memcpy
时,代码可能会工作,因为
memcpy
是GCC已知的一个特殊函数,GCC以各种特殊方式对其进行优化

复合文字应该有效;C标准指定函数体中的复合文字具有与封闭块相关联的自动存储持续时间。如果我们按如下定义
get\u指针
,则封闭块包括整个
smempy
调用:

#define get_pointer(value) (& (__typeof__(value)) { value })

get_pointer
的定义在表达式中使用一个语句,这是一个表达式。这方面的语义几乎没有文档记录,没有理由相信在语句表达式中声明的对象的存储持续时间会持续到语句的计算之后

因此,在准备对
smempy
的调用时,编译器可以通过创建对象
tmp
,生成其地址作为语句表达式的值,并销毁对象
tmp
来计算
get\u指针
。然后将不再存在的对象的现在无效的地址传递给
smempy
,它复制无效数据,因为
tmp
所用的空间已被重新用于其他目的

当使用
memcpy
时,代码可能会工作,因为
memcpy
是GCC已知的一个特殊函数,GCC以各种特殊方式对其进行优化

复合文字应该有效;C标准指定函数体中的复合文字具有与封闭块相关联的自动存储持续时间。如果我们按如下定义
get\u指针
,则封闭块包括整个
smempy
调用:

#define get_pointer(value) (& (__typeof__(value)) { value })

您的
get\u指针
语句块正在计算临时对象的地址,不是吗?今天是这类问题的第二个,两天内是第三个。@hwd如果是临时对象问题,为什么没有
-O1
,它会工作,或者当我使用
memcpy
?@user1483596:未定义的行为时。我查看了汇编代码。带有-O1的gcc优化了
tmp=value
赋值,但仍将&tmp传递给smemcpy。您的
get\u指针
语句块正在计算临时对象的地址,不是吗?今天这是第二个问题,两天内第三个。@hwd如果这是一个临时对象问题,为什么在没有
-O1
的情况下,或者当我使用
memcpy
时,它会工作?@user1483596:未定义的行为。我查看了汇编代码。带有-O1的gcc优化了
tmp=value
赋值,但仍将&tmp传递给smemcpy。