silverviolet 发表于 2023-11-6 14:02

对于s3c2440_lcd_test.c中p = (unsigned short *)fb_base;的不解

       int fb_base的定义追溯到lcd.h中
/* framebuffer的地址 */
unsigned int fb_base;
    在lcd_test.c中对于fb_base的定义如下
void lcd_test(void)
{
        unsigned int fb_base;
        int xres, yres, bpp;
        int x, y;
        unsigned short *p;
        unsigned int *p2;
      ......;
   /* 获得LCD的参数: fb_base, xres, yres, bpp */
get_lcd_params(&fb_base, &xres, &yres, &bpp);

/* 往framebuffer中写数据 */
if (bpp == 16)
{
        /* 让LCD输出整屏的红色 */

        /* 565: 0xf800 */

        p = (unsigned short *)fb_base;
        for (x = 0; x < xres; x++)
                for (y = 0; y < yres; y++)
                        *p++ = 0xf800;
       ......;
}
       疑惑于(unsigned short*)fb_base是个指针,fb_base通过类型转换把unsigned int转换成 unsigned short赋值给p?
      
       当p的类型是float*,int*,double*时候,fb_base的类型可以是short,反之,当p的类型是short*,fb_base的类型不能是float,double,(int可以)
这是何解?
       #include<iostream>
using namespace std;
float s = 1000.123;
short * p =NULL ;


int main()
{
       
       
        p = (short *)s;
        cout << "s =" << s << endl;
        cout << "&s =" << &s << endl;
        cout << "p =" << p << endl;
        cout << "&p =" << &p << endl;
       
        return 0;
}
附图如下

imcuer 发表于 2023-11-6 14:16

本帖最后由 imcuer 于 2023-11-6 14:26 编辑

(unsigned short *)fb_base; 就是将 fb_base 地址中存放的内容看做是 unsigned short 类型,当然里面存放的可能不是真正的 unsigned short 类型,这时用强类型转换 (unsigned short*) 明确指示一下,即将 fb_base中的内容看做是 unsigned short 内容了,之后就可以将其赋值给其它相应类型的变量了,这样就可以避免了编译器的报错,编译器允许你在不同类型之间相互赋值,但要求你要明确声明一下,编译器只对语法负责,不对结果负责。因为只有你能确认内存中的数值是不是可转化的。

silverviolet 发表于 2023-11-6 20:11

imcuer 发表于 2023-11-6 14:16
(unsigned short *)fb_base; 就是将 fb_base 地址中存放的内容看做是 unsigned short 类型,当然里面存放 ...

      首先谢谢您的答复,我看过有种解释跟您的很像,
      如下:
      代码中直接访问寄存器: *(volatile unsigned short *)的含义
*(volatile unsigned short *)0x20000000 的意义
volatile 表示 禁止编译器优化.

unsigned short * 的意思是定义一个2个字节的地址指针, 连起来就是在0x20000000地址位置上输出一个2个字节长的数据。

( unsigned short * )是声明了一个 指针,
指针本身就是数值,

unsigned short *p = ( unsigned short * )0x20000000;
*p = 0; 与 *( unsigned short * )0x2000000 = 0;是一样的。

(volatile unsigned short *)0x20000000=XXX -->0x20000000被定义成一个指针,指向xxx地址。

*(volatile unsigned short *)0x20000000=XXX -->0x20000000指向的地址的值是xxx。
          当p的类型是float*,int*,double*时候,fb_base的类型可以是short,反之,当p的类型是short*,fb_base的类型不能是float,double,(int可以),等号右边类型只能比左边类型的字节长度要长才行{:1_926:}
这是何解?

imcuer 发表于 2023-11-7 08:55

当p的类型是short*时, 由于short类型占两个字节空间, float类型占四个字节空间,当用 short* 取 float 内容时,只能取出float四个字节中的两个字节, 所以编译器提示无法将 float 转成 short, 反之如果 当p的类型是float*,int*,double*时候, 由于float 占4个字节,int 占4个字节,double占8个字节,那么*p可以完整的取出 short 的4个字节,不存在截断的问题,但此时要注意越界的问题,例如用 double 型指针取 short 类型数值时。

yes2 发表于 2023-11-7 09:14

本帖最后由 yes2 于 2023-11-7 09:19 编辑

imcuer 发表于 2023-11-7 08:55
当p的类型是short*时, 由于short类型占两个字节空间, float类型占四个字节空间,当用 short* 取 float 内 ...
我不太认可你的回答。楼主转换失败是因为float无法直接转换为指针,编译器一般不管这事,实在是它觉得这转换太不符合逻辑了所以报个错。
改成这样就能通过编译:p=(short*)(int)s;
或者这样更精确:p = (short*)*(int*)&s;
但是这样大概率会崩,因为一个浮点数的二进制数值,强制作为指针去访问的话,结果可以说是未定义的。

对于强制类型转换, 开发者最好能搞清楚原理,以及在实际编码中明白自己在做什么。
比如简单的,楼主的1000.123,int n = (int)s; 这样会转出一个n=1000;
如果是指针类型的就更要做到心里有数,比如const char* str = "123"; str中存储的是字符串,也可以当做整数来读取int* pn = (int*)str; 那么*pn就是0x333231。

楼主的问题,其实就是整数强制转换为指针成功但是浮点转换为指针没成功。这个可能是编译器最后的防线了,开发者如果清楚自己在做什么,那么就可以像我开头写的那样绕过去,如果绕不过去,那大概率是不清楚自己在做什么的,容易crash。
建议多使用调试功能,调试功能里可以查看内存,涉及内存和数组,指针强制转换之类的,除了语法学会之外,配合调试查看内存可以更快进步

silverviolet 发表于 2023-11-8 11:35

yes2 发表于 2023-11-7 09:14
我不太认可你的回答。楼主转换失败是因为float无法直接转换为指针,编译器一般不管这事,实在是它觉得这 ...

      谢谢您的留言,我懂了,指针类强制类型转化避开float,double{:1_919:}
页: [1]
查看完整版本: 对于s3c2440_lcd_test.c中p = (unsigned short *)fb_base;的不解