微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用带有未初始化变量的 memset

如何解决使用带有未初始化变量的 memset

这是没有未定义行为的有效 C 代码吗?

int main(){
 int a;
 memset(&a,5,sizeof(int));

 return a;
}

我假设这等于只执行 int a = 5

我试图理解在上面的例子中仅仅声明一个变量(没有定义它)是否足以将它放在堆栈中。

解决方法

这是没有未定义行为的有效 C 代码吗?

是 - 一旦 a 变量在给定范围内声明(如函数或其他 { ... } 分隔块),获取其地址并使用该地址访问变量是有效的 在该范围内(就像您的 memset 调用一样)。 当该作用域结束(即不再“活动”)时尝试使用该地址将导致未定义的行为;例如,以下是 UB:

int main()
{
    int* p;
    { // New scope ...
        int a;
        p = &a; // Pointer to "a" is valid HERE
    } // The scope of "a" (and its 'lifetime') ends here
    memset(p,5,sizeof(int)); // INVALID: "p" now points to a dead (invalid) variable
}

但是,您的代码示例中有一个主要警告……

我假设这等于做 int a = 5。

有问题:它正在将 5 分配给 a 变量的每个组件字节,所以它这样做(假设是 4 字节的 int) :

int a = 0x05050505;

与以下相同:

int a = 84215045;
,

来自 C 标准(7.23.6.1 memset 函数)

2 memset 函数复制 c 的值(转换为无符号数 char) 指向的对象的前 n 个字符中的每一个 s.

所以这个电话

memset(&a,sizeof(int));

不会将变量 a 设置为等于 5。在内部变量看起来像

0x05050505

这是一个演示程序

#include <stdio.h>
#include <string.h>

int main(void) 
{
    int a;
    
    memset( &a,sizeof( int ) );
    
    printf( "%#x\n",( unsigned )a );
    
    return 0;
}

它的输出是

0x5050505

您应该谨慎地将函数 memset 与整数一起使用,因为它通常会产生陷阱值。此外,结果取决于内部整数如何从 MSB 或 LSB 开始存储。

附言您在没有链接的块范围内声明了一个变量。它也是一个具有自动存储期限的变量定义。由于变量未显式初始化,因此它具有不确定的值。您可以应用运算符&的地址来获取定义变量的内存范围的地址。

,

这不是未定义的行为。问题是它不是你所期望的。

结果

memset(&a,sizeof(int));

包括将整数 5 的四个字节中的每一个设置为 a

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。