【问题标题】:C- void pointersC-空指针
【发布时间】:2020-08-31 13:21:48
【问题描述】:
#include<stdio.h> 
int main() 
{ 
   int a[2] = {1, 2}; 
   void *ptr = &a; 
   ptr = ptr + sizeof(int); 
   printf("%d", *(int *)ptr); 
   return 0; 
} 

对于这段代码,我得到 2 作为输出 但我刚刚读到 a=&a[0] ,即数组的名称 = 数组的基地址 那么为什么如果我写了 void *ptr=&a 它会给出正确的输出,实际上是把 ptr=&&a[0] 这是未定义的行为吗

ps:我是初学者,第一次发问题请详细解释一下

编辑:如果我们使用 int *ptr ,即整数指针,为什么它不起作用

【问题讨论】:

  • a 表示&amp;a[0] 仅在a 不起作用的地方。否则a 仅表示a。在这种情况下,a 仅表示 a
  • ptr = ptr + sizeof(int); 引发编译错误。对 void 指针执行算术是不合规的。 (只有 GNU 扩展才允许。)然后一旦执行(如果您的编译器允许。),使用该指针将调用未定义的行为。
  • 除非您使用提供扩展的编译器,否则您发布的代码将永远不允许您构建,因此无法运行。您使用的是什么编译器(和编译器版本)?发布的代码是否完全是您正在运行的代码?
  • 是的,它与我在 gcc (tdm-1) 5.1.0 中使用的代码完全相同,我不太了解它

标签: c


【解决方案1】:

这里只有 一个 错误 - void 指针算法是 GCC 扩展!

ptr.c: In function ‘main’:
ptr.c:7:14: warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arith]
    7 |    ptr = ptr + sizeof(int);
      |              ^

您应该改用字符指针:

#include<stdio.h> 

int main(void) 
{ 
   int a[2] = {1, 2}; 
   void *ptr = &a; 
   ptr = (char*)ptr + sizeof(int); 
   printf("%d", *(int *)ptr); 
   return 0; 
}

void 类型不是完整类型,因此您无法对其进行算术运算。

至于

void *ptr = &a; 

void *ptr = a; 

&amp;a 将是一个指向数组的指针,即int (*)[2] 类型,而a 在类型衰减之后将是指向第一个元素的指针,即@987654331 类型@。但它们都将指向相同的内存位置,并且在转换为void * 后会得到完全相同的相同 指针值。

至于为什么它不适用于整数指针-当然可以,但是您需要将其递增not by sizeof(int) but by 1

【讨论】:

  • 但是如果我使用 int* 指针代替 char* 我得到一个垃圾值,它实际上是由 ptr=(int*)ptr+1 解决的,为什么会这样?
【解决方案2】:

所有表达式a&amp;a&amp;a[0] 将产生相同的地址1 - 数组的地址与其第一个元素的地址相同:

   +---+
a: | 1 | a[0]
   +---+
   | 2 | a[1]
   +---+

区别在于表达式的类型。 a 具有 int [2] 类型,但除非它是 sizeof 或一元 &amp; 运算符的操作数,否则它会“衰减”为类型 int *,并且表达式的值将是第一个元素的地址2&amp;a[0] 的类型为 int *&amp;a 的类型为 int (*)[2](指向 int 的 2 元素数组的指针)。

这就是为什么你写的时候它不起作用

int *ptr = &a; // int * = int (*)[2]

类型不兼容。如果你写了它工作

int *ptr = a; // int * = int *

同样,a 的类型为 int [2],但除非它是 sizeof 或一元 &amp; 运算符的操作数,否则它会“衰减”为类型 int *,其值是第一个元素的地址- 在这种情况下,它等同于写&amp;a[0]


  1. 不考虑任何类型转换 - 在 x86 和 x86-64 等平台上,int *int (*)[2] 具有相同的大小和表示形式,但不能保证所有地方都如此。
  2. 这很重要 - 数组表达式不是指针。它将根据需要转换为指针,但没有单独的指针对象明确指向数组的第一个元素。

【讨论】:

    猜你喜欢
    • 2011-09-17
    • 1970-01-01
    • 2011-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多