2014-02-23 53 views
-2

在下面的代码:指针操作,内存扫描

#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 

我的问题是,因为它们都指向同一个地址怎么来的,他们都指向了什么以不同的价值;

+0

注意:您应该使用'%p'来显示指针值。 –

+1

更重要的是,'(&argc + 1)'不是获取'argv'的有效方法。你的程序调用未定义的行为。如果您想了解发生的事情,请查看生成的汇编器。但是这通常不会告诉你C的行为。 –

+0

其实对我来说'(&argc + 1)'导致崩溃:-O –

回答

0

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

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'(又名72),因为那是生活在str指向的地址处的字符。

On(3)您正在打印p指向的值。 p指向str,因此您可能预计str的值将如同(1)上的那样打印。然而,你宣称p是一个char指针,因此解引用它只能读取一个字符。所以你得到的仅仅是str的值的第一个字节。

0

所不同的是在类型取消引用指针的:

  • (&argc+1)是一个指向int,解除引用将interprete四个字节为一个整数。

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

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

除此之外,当然,提领(&argc+1)没有C标准的祝福,它可以让编译器生成代码,在您做反引用点做不惜一切代价。这绝对包括打开一个互联网连接,默默下载并安装一个漂亮的小程序来记录你的每一个击键,并直接发送给N​​SA或其他人...所以,尽量避免调用未定义的行为。

0

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

但是,暂时搁置一会儿,即使它们的DID指向相同的地址,您在每种情况下都以不同的方式使用该地址......在(&argc+1)的情况下,您正在打印指针的值(作为整数)。在*(argc+1)的情况下,您正在打印指向第一个指针的int。在&str的情况下,您正在打印ADDRESS-OF str(与str的内容无关)。用*str,您正在打印由str指向的char。与p一样,您正在打印指针的值,与第一种情况(&argc+1)一样。最后,使用*p您正在打印先前指针指向的char

此外,您正在使用%i格式来打印所有这些值,尽管打印的值的实际数据类型各不相同...有些是指针(通常是32位,在大多数实现中),有些是char是8位的。 printf如何处理与相应的格式字符串不匹配的数据值因实现而异,这是不好的做法!当我尝试在Linux/Fedora下使用gcc 4.8.1进行编译时,它会得到多个编译时错误。

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