指针操作,内存扫描

时间:2014-02-23 16:44:00

标签: c pointers

在以下代码中:

#include <stdio.h>
int main(int argc,char** argv)
{
     char *str = "Hello world";
     char *p = &argc+1;
     printf("%i \n",(&argc+1));         
     printf("%i \n",*(&argc+1));
     printf("%i \n",&str);             
     printf("%i \n",*str);
     printf("%i \n",p);                 
     printf("%i \n",*p);
     return 0;
 }

输出结果为:

-541685632
4196028
-541685632
72
-541685632
-68

我的问题是,因为他们都指向同一个地址,他们所指向的是不是同一个值;

4 个答案:

答案 0 :(得分:2)

当然这是所有未定义的行为,但鉴于&argc+1恰好是&str您的特定实现,这就是您获得在该实现上看到的行为的原因:

首先让我们摆脱&argc+1,而只使用&str

#include <stdio.h>
int main(int argc,char** argv)
{
     char *str = "Hello world";
     char *p = &str;
     printf("%i \n", &str);
     printf("%i \n",*(&str)); // (1)
     printf("%i \n", &str);
     printf("%i \n", *str); // (2)
     printf("%i \n", p);
     printf("%i \n",*p); // (3)
     return 0;
}

开(1)您正在打印*(&str),这当然与str相同。这将打印存储在变量str中的内存地址。

开(2)您正在打印*str。因此,您将指针存储在str中并取消引用它。 *str的值将为'H'(a.k.a。72),因为这是位于str指向的地址的字符。

在(3)上打印p指向的值。 p指向str,因此您可能希望{1}}的值打印得像(1)一样。但是,您将str声明为p指针,因此取消引用它只会读取一个char。所以你得到的只是char值的第一个字节。

答案 1 :(得分:0)

&argc+1指向可能未分配给您的程序的内存。这是不确定的行为,所以如果你的观察与你的期望不同,你不应该感到惊讶。

答案 2 :(得分:0)

区别在于您取消引用的指针类型:

  • (&argc+1)是指向int的指针,取消引用它会将四个字节解释为一个整数。

  • &str是指向char指针的指针,取消引用它会将四个/八个字节解释为一个指向字符的指针。但是,您的代码会将其解除引用两次,因此当您打印*str时,您会在内存中的其他位置打印一个字节。

  • p是指向char的指针,取消引用它只会将一个字节解释为一个字节。

除此之外,当然,取消引用(&argc+1)没有C标准的祝福,它允许编译器发出代码,这些代码可能在您进行解除引用时完全执行任何操作。这绝对包括打开互联网连接以静默下载并安装一个漂亮的小程序来记录您的每次击键并将其直接发送给N​​SA或其他人......所以,尽量避免调用未定义的行为。

答案 3 :(得分:0)

首先,这些并非都指向同一地址......是什么让您认为str的地址与&argc+1相同?在任何平台上,我认为这两个在任何C编译器中都不一样!但是这些事情依赖于编译器和平台,所以试图以这种方式访问​​内存是一个不好的想法,并且非常不便携。

但暂时将所有这些放在一边,即使他们DID指向同一个地址,你在每个实例中以不同的方式使用该地址......在(&argc+1)的情况下,你打印的是值指针(作为整数)。在*(argc+1)情况下,您正在通过第一个指针打印int指向的TO。在&str的情况下,您正在打印地址str(与str的内容无关)。使用*str,您将char打印str指向的p。使用(&argc+1),您将打印指针的值,与第一个案例*p一样。最后,使用char打印前一个指针指向的%i

此外,您使用printf格式打印所有这些值,但打印值的实际数据类型各不相同......有些是指针(在大多数实现中通常为32位) ,有些是8位的char。 {{1}}如何处理与相应格式字符串不对齐的数据值因实现而异,这是不好的做法!

仅供参考,当我尝试使用Linux / Fedora下的gcc 4.8.1进行编译时,会出现多个编译时错误。

总而言之,这里有很多丑陋的东西!