繁体   English   中英

为什么在字符串为STRING和ASCII值的情况下,在int 45的情况下遵循C代码打印45,在STRING和ASCII值的情况下遵循36?

[英]Why does following C code print 45 in case of int 45 and 36 in case of STRING and ASCII value of CHAR?

struct s{
int a;
char c;
};
int main()
{
    struct s b = {5,'a'};
    char *p =(char *)&b;
    *p = 45;
    printf("%d " , b.a);
    return 0;
}

如果*p更改为任何character ,则不输出ASCII值;如果*p更改为任何string ("xyz") ,则不打印36 为什么会这样呢?

能否给出结构s和* p的内存映射?

根据我的结构记忆

s as z-> (****)(*) assuming 4 byte for int . 并且当s初始化时,它将变为(0000000 00000000 00000000 00000101)(ASCII OF char a) ,* p指向z的起始地址。 * p是字符指针,因此它将在每个BYTE位置存储ASCII值,即在每个*处将由char的ASCII占用。 但是现在我们将其设置为45,因此z将变为(45 0 0 5 )(ASCII of char a) 但这不是真的吗?

你的结构看起来像小尾数:

00000101 00000000 00000000 00000000 01100001

所以p点到5和覆盖它。 在printf的4个小端排序的字节打印45

如果你想尝试它大端754974725会是这个结果,因为p指向INT的MSB侧。

一个简单的测试程序,以找出是否你是在很少或大端:

int main()
{
  int a = 0x12345678;
  unsigned char *c = (unsigned char*)(&a);
  if (*c == 0x78)
    printf("little-endian\n");
  else
    printf("big-endian\n");
  return 0;
}

通过char *指针写入该结构时,会将45存储在该结构的第一个字节中。 如果您使用的是Little-Endian实现,则将写入ba的低端。 如果您使用的是Big-Endian实现,则将写入ba高端。

这是分配*p=45之前和之后带有16位int的实现上的结构通常发生什么情况的可视化。 注意,该结构被填充为sizeof(int)的倍数。

小端

Before:  a [05][00]  (int)5
         c [61]
           [  ]

After:   a [2d][00]  (int)45
         c [61]
           [  ]

大端

Before:  a [00][05]  (int)5
         c [61]
           [  ]

After:   a [2d][05]  (int)11525
         c [61]
           [  ]

如果使用更大的整数,则可以使用更多方式对字节进行排序,但是在现实生活中,您几乎不可能遇到以上两种情况。

但是 ,由于以下两个原因,下一行调用了未定义的行为

printf("%d " , b.a);
  1. 您正在通过其他类型的指针修改ba的一部分。 可以给出ba “陷阱表示”,并读取包含陷阱表示的值可导致未定义的行为。 (不,您在现实生活中不太可能会遇到陷阱表示形式(整数类型)。)
  2. 您正在调用没有函数声明的可变参数函数。 可变参数函数通常具有不常用的参数传递方式,因此编译器必须对此有所了解。 通常的解决方法是#include <stdio.h>

未定义的行为意味着可能发生任何事情,例如打印错误的值,使程序崩溃或(完全是最糟糕的事情)完全按照您的期望进行。

C标准保证的结构的第一个成员的地址是该结构的地址。 也就是说,就您而言

int* p =(int*)&b;

一种安全的演员。 但访问的标准方式char从结构的地址成员。 这是因为标准不说的连续成员在内存中的任何连续性:其实编译器可能会或可能不会插入成员之间的空隙(称为结构填料),以适应芯片组。

所以,你在做什么,基本上是不确定的。

因为这

*p = 45;

将p指向的值更改为45。然后将p指向b。

尝试构造此指针。

#include<stdio.h>

    struct s{
    int a;
    char c[1];
    };

    int main()
    {
        struct s *p;
        struct s b = {5, 'a'};
        p = &b;

        printf("%d %s", p->a, p->c);
        return 0;
    }

如果您希望Pointers作为结构成员而不是char数组。 尝试这个..

#include<stdio.h>

struct s{
int a;
char *c;
};

int main()
{
    struct s b = {5, "a"};

    printf("%d %s", b.a, b.c);
    return 0;
}

char *p = (char*) &b; -在此行中, p指向b结构的开头,作为char指针。

*p = 45; 将45写入b的存储空间, ba也可以访问该存储空间。

当您打印printf("%d ", ba); 你会打印存储在指定为堆栈存储器的45 a成员struct b ,你会得到45。

尝试自己调试一下,您会在监视窗口中看到它

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM