指向使用索引(如数组)访问的结构的指针

时间:2016-05-13 07:05:06

标签: c pointers struct printf pointer-arithmetic

#include<stdio.h>

struct test{ 
    int a;
    int b;
}m;

int main()
{
    m.a=5;m.b=7; 
    struct test *p;
    p = &m;
    printf("p[0] = %d\n",*(p+0));
    printf("p[1] = %d\n",*(p+1));

    return 0;

}

我得到以下输出:

p [0] = 5 p [1] = 0

有人可以解释一下这种行为吗?有没有办法使用索引打印所有结构成员?

对于错字感到抱歉。

(更新)

因为我可以使用索引0打印第一个元素,虽然指针的类型是“struct test type”,第一个成员是一个整数,但我可以得到正确的值。因此,问题引发了这种行为的原因。如果可以使用索引访问所有成员,就像访问第一个成员一样。

5 个答案:

答案 0 :(得分:2)

在您的代码中,

printf("p[0] = %d\n",*(p+0));
printf("p[0] = %d\n",*(p+1));

调用undefined behavior作为

  1. 您为%d格式说明符传递了错误的参数类型。
  2. 您可以通过*(p+1)
  3. 来访问超出范围的内存

    因此,无法以任何方式解释或证明输出。

    现在,那就说了,让我们稍微分析一下代码。

    首先,

      p = &a;
    

    是错误的,因为没有名为a的变量。结构变量a有一个成员变量 m,可以m.a访问。所以,你可以以某种方式

     p = (struct test*) &m.a;
    

    现在,使用结构的第一个元素的地址作为结构地址是有效的,因为在结构的开头没有填充。但这并不意味着,您可以在结构指针p上直接应用指针算法 并获取每个成员变量,主要是因为

    • 两个元素之间可以有填充
    • 指针p的类型为struct test虽然您可以通过投射来解决)

答案 1 :(得分:1)

获取正确的编译器。使用GCC 5上的默认设置进行编译,编译吐出:

foo.c: In function ‘main’:
foo.c:12:10: error: ‘a’ undeclared (first use in this function)
     p = &a;
          ^
foo.c:12:10: note: each undeclared identifier is reported only once for each function it appears in
foo.c:13:12: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct test’ [-Wformat=]
     printf("p[0] = %d\n",*(p+0));
            ^
foo.c:14:12: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct test’ [-Wformat=]
     printf("p[0] = %d\n",*(p+1));
            ^

也许你的意思是p = &m;

之后,您的代码将调用未定义的行为。 %d期望相应的参数为int,但您提供struct test。此外,在后一个打印件上,指针在m之后指向未初始化的内存,并且打印出垃圾。即使您在第一种情况下打印5这一事实也无法依赖。 C标准没有解释为什么为什么不这种情况发生,C标准说&#34;此时编译器可以生成打印的代码42342,崩溃程序,或做任何其他事情,这个标准就好了。&#34;

在C编译器中,警告通常意味着&#34;标准违规&#34;在这种情况下,可能存在未定义的行为。 C编程语言的新手应始终考虑所有编译器警告,尤其是默认设置为致命错误

答案 2 :(得分:1)

我用gcc编译你的代码,我得到了。

In function ‘main’:
error: ‘a’ undeclared (first use in this function)
   p = &a;
        ^
note: each undeclared identifier is reported only once for each function it appears in
 warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct test’ [-Wformat=]
       printf("p[0] = %d\n",*(p+0));
              ^
warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct test’ [-Wformat=]
    printf("p[0] = %d\n",*(p+1));

假设您的意思是p=&m,这是我的解释

printf("p[0] = %d\n",*(p+0));
printf("p[0] = %d\n",*(p+1));

首先分析像你在printf函数中那样推迟指针是否正确。

*(p+0)将允许您访问struct test variabe m。因为,您已将struct test类型的变量的地址分配给指针p,延迟指针*p*(p+0)将允许您访问变量{{1 }}。但是分配给指针的地址是一个不属于m类型数组的单个变量,延迟struct test会给你 UNDEFINED BEAVAVIOR 。例如,如果((p+1)

*(p+1)就会有效
not in printf statement
  

有没有办法使用索引打印所有结构成员?

你可以。但是c中的运营商没有超载。所以,你可以通过 -

实现这一目标
struct test m[20];
struct test *p;

(*(p+0)).a=2;
(*(p+1)).a=5;

如果指针printf("a=%d, b=%d", p->a, p->b); 指向类型为p的数组,则可以在printf中使用index作为

struct test

我对您未来代码实验的建议将首先分析您的代码给出的警告和错误。警告可以帮助纠正代码中的大多数错误。我总是使用gcc / g ++编译器编译我的c / c ++代码,并使用-Wall,-Wshadow,-Wextra等标志。如果您不理解,可以发出警告。

答案 3 :(得分:0)

您直接将a的地址指定给pam的成员,因此无法直接访问。从代码开始,您应该使用整数指针进行算术运算。

您需要修改代码的一部分

struct test *p;
p = &a;

 int *p;
 p = &m.a;

现在代码应该按照您的意愿工作。

答案 4 :(得分:0)

首先,您的代码中有拼写错误。 请从p = &a;更改为p = &m;,以便删除编译器抱怨的错误。

其次,我猜您期望输出为p [0] = 5且p [1] = 7。 为此,请从

修改代码
printf("p[0] = %d\n",*(p+0));
printf("p[1] = %d\n",*(p+1));

printf("p[0] = %d\n",p->a);
printf("p[1] = %d\n",p->b);

可以工作。