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时看到的结果