C 指向浇铸指针的指针?

C 指向浇铸指针的指针?,c,pointers,C,Pointers,在C语言中,我遇到了指向强制转换指针的指针(不确定这是否是正确的术语),例如: *(长*)p=10;我一生都无法理解它的含义,或者,另一个例子: *(void*)NULL,或*(char*)0;我只是不能把我的头绕在它周围,有人能给我解释一下这一点,并把我从部分脑损伤中解救出来吗?:) 谢谢 (注:下面给出了此类用法的示例) int main(int argc,char*argv[]){ char*p,*payload=(char*)malloc(1052) 意思是:p是一个“长指针”,我试图将

在C语言中,我遇到了指向强制转换指针的指针(不确定这是否是正确的术语),例如:

*(长*)p=10;我一生都无法理解它的含义,或者,另一个例子:

*(void*)NULL,或*(char*)0;我只是不能把我的头绕在它周围,有人能给我解释一下这一点,并把我从部分脑损伤中解救出来吗?:)

谢谢

(注:下面给出了此类用法的示例)

int main(int argc,char*argv[]){ char*p,*payload=(char*)malloc(1052)


意思是:p是一个“长指针”,我试图将该值分配给此处引用的内存。我们这样做是因为最初我们说p是一个字符指针,我们希望在访问时更改其行为。

第一个星实际上是取消引用浇铸的指针。因此,*(长*)p=10意味着将p强制转换为指向long的指针,并将-4分配给被取消引用的位置。将示例与*p=10进行比较。

将*放在(long*)之前称为“取消引用”指针。这意味着,正如@GrayWizardx所说,您正在修改指针指向的内存中的值。

首先分解该语句:

  long *q = (long*)p;
  *q = 10;
  p += 4;
p参数的类型为
char*
,您一次只能通过该指针读取或写入1个字节。转换为
long*
将创建一个指针,您可以通过该指针从/向同一地址一次读取或写入4个字节。赋值写入字节0x00、0x00、0x00、0x0A。与以下内容相同:

  *p = 10;
  p++;
  *p = 0;
  p++;
  *p = 0;
  p++;
  *p = 0;
取决于字节顺序。赋值后,p需要增加4,因为写入了4个字节


这种技巧在包含非字节数据的字节缓冲区中非常常见。

这是指针算法,基于指针类型,即当您递增cPtr++时,它的char*cPtr还是int*nPtr将移动一个字节,nPtr++将移动4个字节(assumimg char取一个字节,int取4个字节).

当您理解示例代码背后的动机时,您可能会有一个更轻松的时间

代码正在处理4字节的值,这就是为什么
p
被转换为
long*
。构造
*(long*)p=-4;
允许您通过一个赋值将4个字节设置为
0xfffffc
。如果您将
p
作为
char*
离开,您将需要四个单独的赋值,并且您还需要担心平台的安全性

那么,为什么不首先简单地将
p
声明为
long*
?因为代码使用指针算法来计算目标地址:
p+=sizeof(外壳代码)+64-4;
指针算法使用
char*
很容易,因为向指针中添加1将使其前进到下一个字节,正如您所期望的那样。对于指向其他数据类型的指针,情况并非如此!如果
p
被声明为
long*p;
p+=4
将添加4*
sizeof(long)
p

为什么?因为这样可以很容易地遍历
long
变量列表:

long sum_of_longs(long vals[], int num)  { // 'vals[]' contains 'num' long ints.
   long *p;                                // This pointer traverses the array.
   long sum;                               // Running total.

   // Initialize 'p' to the first number in 'vals[]' and
   // increment through the array until 'num' reaches 0.
   //
   // Note that 'p' increases by 4 bytes each time in order
   // to advance to the next long.
   for (sum=0, p=vals;  num > 0;  p++, num--)
      sum += *p;

   return sum;
}
因此,在您的示例中,将
p
定义为
char*
可以很容易地以字节为单位进行指针运算,将其转换为
long*
可以更容易地进行赋值。

codepad.org/iz2TSDfa

这段代码将四个字节的数据写入内存中的零地址。这不是常见或公认的做法,也不适用于一般情况。换句话说:黑魔法

我猜它会触发某种处理器中断


如果您想理解,我建议您学习此代码所针对的汇编/计算机体系结构。

那么,我们为什么不将其更改为(long*)p=-4;?或者,将值分配给此处引用的内存,&(long*)p=-4?/me对此非常困惑……但是,你是什么意思,将值赋给此处引用的内存?如果我们将其更改为(长)p=-4,我们将“说将地址设置为-4”和&(长*)p=-4表示将p的指针*的地址设置为-4,这是不允许的。也不允许将某物的地址设置为-4。允许将无符号值设置为有符号值,但它会将-4转换为4294967292(对于一个4字节
长的
类型)。啊,我现在明白了;好的。那么,当发生类似*(char*)的事情时呢NULL;突然出现?这是一篇好文章的Google缓存链接…由于某些原因,主链接当前处于关闭状态:为了访问指针指向的变量,对吗?好吧。那么*(char*)NULL;?嗯,为什么我们不能只做“p=-4L”?@Grey,你能举个例子说明代码在哪里使用吗?我在原来的问题中没有看到它…一个带有*(unsigned int*)NULL的例子:--我只是在其他地方遇到了*(char*)NULL和*(void*)NULL…说得比我优雅得多。long==仅在windows和32位unix上为4字节。long在64位unix上为8字节。
  *p = 10;
  p++;
  *p = 0;
  p++;
  *p = 0;
  p++;
  *p = 0;
long sum_of_longs(long vals[], int num)  { // 'vals[]' contains 'num' long ints.
   long *p;                                // This pointer traverses the array.
   long sum;                               // Running total.

   // Initialize 'p' to the first number in 'vals[]' and
   // increment through the array until 'num' reaches 0.
   //
   // Note that 'p' increases by 4 bytes each time in order
   // to advance to the next long.
   for (sum=0, p=vals;  num > 0;  p++, num--)
      sum += *p;

   return sum;
}