为什么指针与下一个存储位置有12个差异

时间:2018-09-07 15:38:49

标签: c pointers

为什么下面的程序在下一个内存位置将内存差异移到下一个位置固定12或它对char / float / int有一些逻辑,所以与下一个位置的差异为-2

包括     #include

int main () {

   char  var;
   char  *ptr;
   char  **pptr;
    char  ***ppptr;
   char  ****pppptr;

   var = 'M';

   /* take the address of var */
   ptr = &var;

   /* take the address of ptr using address of operator & */
   pptr = &ptr;

   ppptr=&pptr;

   ppptr=&pptr;
   ppptr=&pptr;
   pppptr=&ppptr;

   /* take the value using pptr */
   printf("Value of var = %d\n", var );
   printf("Value available at *ptr = %c....and address is %u\n", *ptr ,ptr);
   printf("Value available at **pptr = %c....and address is %u\n", **pptr,pptr);
   printf("Value available at ***ppptr = %c....and address is %u\n", ***ppptr ,ppptr);
   printf("Value available at ****pppptr = %c....and address is %u\n", ****pppptr,pppptr);
   getch();
   return 0;
}
//out put
///-----------------------------------------------
Value of var = 77;
Value available at *ptr = M....and address is 11401207
Value available at **pptr = M....and address is 11401192   why differnceis 12 in memory locaton 
Value available at ***ppptr = M....and address is 11401180
Value available at ****pppptr = M....and address is 11401168

3 个答案:

答案 0 :(得分:1)

您似乎在问,为什么ptr的地址(通过使用pptr字段描述符scanf打印%u的值来判断)为何看起来与下一个声明的局部变量pptr的地址,减少12个字节。我猜想接下来是其他局部变量。

实际上,正如@SouravGhosh在他的答案中已经描述的那样,%u字段描述符与指针参数不正确对应,因此scanf调用的效果包括输出的所有方面,则未定义。

但是,对于该问题而言,实际结果并不重要。 C语言没有理由假设任何函数的局部变量的地址之间存在任何特定顺序或差异。它由编译器决定。因此,对该问题没有普遍的答案。

如果我们假设假设您观察到的输出恰好准确反映了局部变量地址之间的差异(这是不确定的),则表明编译器是有意为之的在变量之间保留填充。出于任何目的,这样做都是完全免费的。例如,编译器可能正在尝试最大程度地减少通过指向本地变量的指针访问局部变量的代码中的一次性错误的潜在影响。

答案 1 :(得分:0)

首先,打印指针的正确方法是使用%p,并且将指针传递到void *时转换为printf,就像printf("%p\n", (void *) ptr);一样。由于您在使用%P的注释中提到了问题中显示的%u,因此与问题中显示的%p不同,我假设错误的大小写是错字,并且您使用ptr重现了该问题结果与问题中显示的结果相似。

在这种情况下,可能发生的情况是编译器将指针pptrppptrpppptrprintf存储在碰巧是12的地址上相隔字节。当然,如果C实现中的指针大小恰好是4或8个字节,则它只能将它们分开存储4或8个字节。但是,编译器可能会在指针之间存储其他内容,也许是您在-S语句中使用的字符串的地址或其他附带值。这使我怀疑您在未启用优化的情况下进行了编译。如果重新编译优化,您可能会看到不同的结果。

无论如何,可以通过要求编译器显示其生成的汇编代码(例如,将nFactorial.Text = factorial.ToString(); 开关与GCC配合使用)来更好地解释结果。

答案 2 :(得分:-1)

使用%u打印指针地址将得到undefined behavior

使用%p格式说明符并将参数强制转换为void *