Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 指针上移和下移_C_Pointers_Type Conversion_Downcast - Fatal编程技术网

C 指针上移和下移

C 指针上移和下移,c,pointers,type-conversion,downcast,C,Pointers,Type Conversion,Downcast,指针向下投射 int* ptrInt; char * ptrChar; void* ptrVoid; unsigned char indx; int sample = 0x12345678; ptrInt = &sample; ptrVoid = (void *)(ptrInt); ptrChar = (char *)(ptrVoid); /*manipulating ptrChar */ for (in

指针向下投射

    int* ptrInt;
    char * ptrChar;
    void* ptrVoid;
    unsigned char indx;
    int sample = 0x12345678;

    ptrInt = &sample;
    ptrVoid = (void *)(ptrInt);
    ptrChar = (char *)(ptrVoid);

    /*manipulating ptrChar */
    for (indx = 0; indx < 4; indx++)
    {
        printf ("\n Value: %x \t Address: %p", *(ptrChar + indx), ( ptrChar + indx)); 
    }
unsigned int * ptrUint;
void * ptrVoid;
unsigned char sample = 0x08;

ptrVoid = (void *)&sample;
ptrUint = (unsigned int *) ptrVoid;

printf(" \n &sample: %p \t ptrUint: %p ", &sample, ptrUint );
printf(" \n sample: %p \t *ptrUint: %p ", sample, *ptrUint );  
问题: 为什么将样本划分为字符大小的数据?当执行指针运算时,它是如何得到它的剩余值的? 这是怎么可能的


指针向上投射

    int* ptrInt;
    char * ptrChar;
    void* ptrVoid;
    unsigned char indx;
    int sample = 0x12345678;

    ptrInt = &sample;
    ptrVoid = (void *)(ptrInt);
    ptrChar = (char *)(ptrVoid);

    /*manipulating ptrChar */
    for (indx = 0; indx < 4; indx++)
    {
        printf ("\n Value: %x \t Address: %p", *(ptrChar + indx), ( ptrChar + indx)); 
    }
unsigned int * ptrUint;
void * ptrVoid;
unsigned char sample = 0x08;

ptrVoid = (void *)&sample;
ptrUint = (unsigned int *) ptrVoid;

printf(" \n &sample: %p \t ptrUint: %p ", &sample, ptrUint );
printf(" \n sample: %p \t *ptrUint: %p ", sample, *ptrUint );  
输出:

 Value: 00000078         Address: 0022FF74
 Value: 00000056         Address: 0022FF75
 Value: 00000034         Address: 0022FF76
 Value: 00000012         Address: 0022FF77
 &sample: 0022FF6F       ptrUint: 0022FF6F
 sample: 00000008        *ptrUint: 22FF6F08    <- Problem Point
&示例:0022FF6F ptrint:0022FF6F

示例:00000008*ptrint:22FF6F08在第一个示例中,您使用的是字符指针,因此每次访问一个字节的数据。内存是字节可寻址的,因此当您向指针添加一个字节时,您将访问下一个更高的内存地址。这就是for循环所发生的情况。使用字节指针告诉编译器仅访问单个字节,当您使用%p打印时,其余位将显示为0


在第二个示例中,我认为正在发生的是一个字节被分配给示例字节,然后接下来的4个字节被分配给ptrunt。因此,当您从sample的内存地址开始获取值并将其转换为4字节指针时,您只会看到sample中的值加上ptt的前3个字节。如果将其转换为字符指针并打印,则在输出中只能看到8。

在第一个示例中,您使用的是字符指针,因此每次访问一个字节的数据。内存是字节可寻址的,因此当您向指针添加一个字节时,您将访问下一个更高的内存地址。这就是for循环所发生的情况。使用字节指针告诉编译器仅访问单个字节,当您使用%p打印时,其余位将显示为0


在第二个示例中,我认为正在发生的是一个字节被分配给示例字节,然后接下来的4个字节被分配给ptrunt。因此,当您从sample的内存地址开始获取值并将其转换为4字节指针时,您只会看到sample中的值加上ptt的前3个字节。如果将其转换为char指针并打印,则在输出中只能看到8。

这些不是向上转换和向下转换,这意味着某种继承层次结构

在第一个示例中,将指向整数的指针视为指向字符的指针。增加指向int的指针会增加4,增加指向char的指针会增加1(假设为32位int和8位char)。取消对它们的引用将分别生成一个int和一个char。因此,将碎片划分为字节


在第二个示例中,将名为sample的无符号char变量视为指向int的指针,并取消对它的引用。实际上,您正在从0x08内存地址读取垃圾。我想你忘了一个&。您还向第二个printf传递了一个1字节的char和一个4字节的int,而不是4+4字节,这会弄乱printf,从堆栈中读取的字节比您给他的多3个字节。这恰好是为printf的第一个调用提供的ptrint值的一部分。使用%c而不是%p应该可以解决这个问题。

这些不是升级和降级,这意味着某种继承层次结构

在第一个示例中,将指向整数的指针视为指向字符的指针。增加指向int的指针会增加4,增加指向char的指针会增加1(假设为32位int和8位char)。取消对它们的引用将分别生成一个int和一个char。因此,将碎片划分为字节


在第二个示例中,将名为sample的无符号char变量视为指向int的指针,并取消对它的引用。实际上,您正在从0x08内存地址读取垃圾。我想你忘了一个&。您还向第二个printf传递了一个1字节的char和一个4字节的int,而不是4+4字节,这会弄乱printf,从堆栈中读取的字节比您给他的多3个字节。这恰好是为printf的第一个调用提供的ptrint值的一部分。使用%c而不是%p应该可以解决这个问题。

其他答案已经解释了为什么你看到了你看到的东西

我要补充的是,您的第二个示例依赖于未定义的行为。取消引用指向最初不是
int
的数据的
int*
是无效的。i、 e:

char x = 5;
int *p = (int *)&x;
printf("%d\n", *p);  // undefined behaviour

其他答案已经解释了为什么你看到了你所看到的

我要补充的是,您的第二个示例依赖于未定义的行为。取消引用指向最初不是
int
的数据的
int*
是无效的。i、 e:

char x = 5;
int *p = (int *)&x;
printf("%d\n", *p);  // undefined behaviour

对不起,应该是%x。。。他太专注于这个问题了。我忘记了正确的格式。抱歉。对不起,应该是%x。。。他太专注于这个问题了。我忘记了正确的格式。抱歉。哦,您的意思是说在第一个示例中,*(ptrChar+indx)不可能有垃圾值。好吧,这很有道理。但是为什么*(ptrChar+0)以0x78开始?对于第二个示例,我想知道为什么编译器会添加垃圾值,因为如果我们添加
(unsigned int)(charTypeVariable)
charTypeVariable只会用0加宽数据,使其适合无符号整数。这与处理指针变量不同吗?这是little-endian(x86)系统中字节的排序方式。最低有效字节位于最低内存地址。在本例中,0x78是初始化为sample的字中的最低有效字节。另一方面,苹果电脑是big-endian的,所以在这样的系统上它会打印出相反的内容。而且,如果没有办法删除垃圾值的话。掩蔽
*ptrint&0x000000ff吗?编译器没有添加垃圾值。它只是尽可能地利用所有的内存。创建无符号字符时,分配的是8位。然后,您也在同一上下文中分配了一些指针,因此编译器可能会连续地分配所有这些变量。这是当您将字符转换为无符号int-an时看到的结果