一个关于struct指针的问题,很BT的,哪位牛人看一看?

时间:2022-01-14 04:25:02
话说有一struct是这样的:
struct BTstruct
{
    int i;
    char *a;
    char *b;
};
然后我这样玩:
int main()
{
    struct BTstruct *gh;
    gh = (struct BTstruct *)malloc(128);
    memset(gh,0,128);
    gh->i = 8;
    gh->a = "aaaa";
    gh->b = "bbbb";
    printf("%p---%p\n",gh->b,*((struct BTstruct *)((char *)gh+8)));
    printf("%s---%s\n",gh->b,*((struct BTstruct *)((char *)gh+8)));
    printf("%d---%d\n",gh->i,*gh);
    return 0;
}
这里printf出来的前后值都一样,
我有一点不懂的是这里为什么是*((struct BTstruct *)((char *)gh+8))而不是*((char *)((char *)gh+8))?
我觉得既然以字节为单位走到成员b的位置,b是char型的指针就该是char *啊为什么要用struct BTstruct *才能得到正确的b成员的地址,进而得到b指向的值呢?

忘哪位C大牛能够解答,谢谢!!

14 个解决方案

#1


对于你这种情况,两者是毫无差别的,因为最后%p只要一个指针而已,无论什么类型的指针结果都一样

#2


   指针类型 不影响指向的内存区域内容 \(^o^)/~

   指针进行移位时 偏移量不一样而已

#3


可怕的写法

gh->a = "aaaa"; 


printf 确实不认是什么类型的指针

#4


int main()

{

    struct BTstruct *gh;

    gh = (struct BTstruct *)malloc(128);

    memset(gh,0,128);

    gh->i = 8;

    gh->a = "aaaa";

    gh->b = "bbbb";

    printf("%p---%p\n",gh->b,*((struct BTstruct *)((char *)gh+8)));

    printf("%s---%s\n",gh->b,*((struct BTstruct *)((char *)gh+8)));

    printf("%d---%d\n",gh->i,*gh);



     printf("%p---%p\n",gh->b,*((char *)((char *)gh+8)));

    char *p = "bbbb";

    printf("%p\n", *p);
    printf("*p\n", p);//编译器优化后,p和gh->b一样了

    //printf("%s\n", *p);

    return 0;



对着比较一下吧
//printf("%s\n", *p); 这个就会发生错误了,字符串没法终止,而你本身可以终止,因为有memset

归咎一点, 对什么样的指针就进行什么样的解引用,也就是取几个字节的问题



#5


引用楼主 lantianye 的回复:
我有一点不懂的是这里为什么是*((struct BTstruct *)((char *)gh+8))而不是*((char *)((char *)gh+8))?
我觉得既然以字节为单位走到成员b的位置,b是char型的指针就该是char *啊为什么要用struct BTstruct *才能得到正确的b成员的地址,进而得到b指向的值呢?

忘哪位C大牛能够解答,谢谢!!


这里涉及到printf函数的使用问题,你的格式串中%p要求printf函数用4个字节去读变量的值,而如果用char *强制转换后相当于只提供了一个字节的值,其他三个字节的值没有提供,当然得不得b的指向了
ps:printf函数仍会读四个字节,但并非原来的四个字节,因为会类型提升,其他三个字节扩充为符号位

#6


引用楼主 lantianye 的回复:
     gh->a = "aaaa";
     gh->b = "bbbb";


无知无畏啊!真是恐怖!

#7


那个位置确实不能用char *代替。举个例子

char *str = "abc";
int a = str;
int b = *(char *)(&str);

那a和b的值是一样的么,楼主的2种不同的指针的区别和这里是一样的。
明显,b中,因为char *的存在(char *表示指向的值是一个字节为单位的),导致b只取&str这个地址所指向的数值中的一个字节,而a则是取的4个字节,这就是a和b不同的原因,所以只要将char改为随意一个4字节类型,a和b都是一样的,所以char *改为int *或者long *都是可以的。另外,实验了一下,*(struct *)value和*(int *)value是等效的。

#8


5楼的回答也是正解。

#9


DING

#10


引用 7 楼 happy1986 的回复:
那个位置确实不能用char *代替。举个例子
C/C++ codechar*str="abc";int a= str;int b=*(char*)(&str);
那a和b的值是一样的么,楼主的2种不同的指针的区别和这里是一样的。
明显,b中,因为char *的存在(char *表示指向的值是一个字节为单位的),导致b只取&str这个地址所指向的数值中的一个字节,而a则是取的4个字节,这就是a和b不同的原因,所以只要将char改为随意一个4字节类型,a和b都是一样的,所以char *改为int *或者long *都是可以的。另外,实验了一下,*(struct *)value和*(int *)value是等效的。

正解!顶!

#11


学了一学期的DOS C就是不行,看不懂...

#12


学下下

#13


看不懂...

#14


引用 5 楼 borefo 的回复:
引用楼主 lantianye 的回复:

我有一点不懂的是这里为什么是*((struct BTstruct *)((char *)gh+8))而不是*((char *)((char *)gh+8))?
我觉得既然以字节为单位走到成员b的位置,b是char型的指针就该是char *啊为什么要用struct BTstruct *才能得到正确的b成员的地址,进而得到b指向的值呢?

忘哪位C大牛能够解答,谢谢!!


这里涉及到printf函数的使用问题,你的格式串中%p要求printf函数用4个字节去读变量的值,而如果用char *强制转换后相当于只提供了一个字节的值,其他三个字节的值没有提供,当然得不得b的指向了
ps:printf函数仍会读四个字节,但并非原来的四个字节,因为会类型提升,其他三个字节扩充为符号位


我同意你的说法!

#1


对于你这种情况,两者是毫无差别的,因为最后%p只要一个指针而已,无论什么类型的指针结果都一样

#2


   指针类型 不影响指向的内存区域内容 \(^o^)/~

   指针进行移位时 偏移量不一样而已

#3


可怕的写法

gh->a = "aaaa"; 


printf 确实不认是什么类型的指针

#4


int main()

{

    struct BTstruct *gh;

    gh = (struct BTstruct *)malloc(128);

    memset(gh,0,128);

    gh->i = 8;

    gh->a = "aaaa";

    gh->b = "bbbb";

    printf("%p---%p\n",gh->b,*((struct BTstruct *)((char *)gh+8)));

    printf("%s---%s\n",gh->b,*((struct BTstruct *)((char *)gh+8)));

    printf("%d---%d\n",gh->i,*gh);



     printf("%p---%p\n",gh->b,*((char *)((char *)gh+8)));

    char *p = "bbbb";

    printf("%p\n", *p);
    printf("*p\n", p);//编译器优化后,p和gh->b一样了

    //printf("%s\n", *p);

    return 0;



对着比较一下吧
//printf("%s\n", *p); 这个就会发生错误了,字符串没法终止,而你本身可以终止,因为有memset

归咎一点, 对什么样的指针就进行什么样的解引用,也就是取几个字节的问题



#5


引用楼主 lantianye 的回复:
我有一点不懂的是这里为什么是*((struct BTstruct *)((char *)gh+8))而不是*((char *)((char *)gh+8))?
我觉得既然以字节为单位走到成员b的位置,b是char型的指针就该是char *啊为什么要用struct BTstruct *才能得到正确的b成员的地址,进而得到b指向的值呢?

忘哪位C大牛能够解答,谢谢!!


这里涉及到printf函数的使用问题,你的格式串中%p要求printf函数用4个字节去读变量的值,而如果用char *强制转换后相当于只提供了一个字节的值,其他三个字节的值没有提供,当然得不得b的指向了
ps:printf函数仍会读四个字节,但并非原来的四个字节,因为会类型提升,其他三个字节扩充为符号位

#6


引用楼主 lantianye 的回复:
     gh->a = "aaaa";
     gh->b = "bbbb";


无知无畏啊!真是恐怖!

#7


那个位置确实不能用char *代替。举个例子

char *str = "abc";
int a = str;
int b = *(char *)(&str);

那a和b的值是一样的么,楼主的2种不同的指针的区别和这里是一样的。
明显,b中,因为char *的存在(char *表示指向的值是一个字节为单位的),导致b只取&str这个地址所指向的数值中的一个字节,而a则是取的4个字节,这就是a和b不同的原因,所以只要将char改为随意一个4字节类型,a和b都是一样的,所以char *改为int *或者long *都是可以的。另外,实验了一下,*(struct *)value和*(int *)value是等效的。

#8


5楼的回答也是正解。

#9


DING

#10


引用 7 楼 happy1986 的回复:
那个位置确实不能用char *代替。举个例子
C/C++ codechar*str="abc";int a= str;int b=*(char*)(&str);
那a和b的值是一样的么,楼主的2种不同的指针的区别和这里是一样的。
明显,b中,因为char *的存在(char *表示指向的值是一个字节为单位的),导致b只取&str这个地址所指向的数值中的一个字节,而a则是取的4个字节,这就是a和b不同的原因,所以只要将char改为随意一个4字节类型,a和b都是一样的,所以char *改为int *或者long *都是可以的。另外,实验了一下,*(struct *)value和*(int *)value是等效的。

正解!顶!

#11


学了一学期的DOS C就是不行,看不懂...

#12


学下下

#13


看不懂...

#14


引用 5 楼 borefo 的回复:
引用楼主 lantianye 的回复:

我有一点不懂的是这里为什么是*((struct BTstruct *)((char *)gh+8))而不是*((char *)((char *)gh+8))?
我觉得既然以字节为单位走到成员b的位置,b是char型的指针就该是char *啊为什么要用struct BTstruct *才能得到正确的b成员的地址,进而得到b指向的值呢?

忘哪位C大牛能够解答,谢谢!!


这里涉及到printf函数的使用问题,你的格式串中%p要求printf函数用4个字节去读变量的值,而如果用char *强制转换后相当于只提供了一个字节的值,其他三个字节的值没有提供,当然得不得b的指向了
ps:printf函数仍会读四个字节,但并非原来的四个字节,因为会类型提升,其他三个字节扩充为符号位


我同意你的说法!