' - >' C中的运算符以及它的使用方式

时间:2013-10-29 17:30:47

标签: c pointers structure

编辑 - 使用2星指针更新以获得更多相关性

假设我有一个指向同时包含指针的结构的双星指针。

typedef struct{
    nodeT *ptr;
}nodeT; 

nodeT example; 
nodeT *test1 = &example;
nodeT *test = &test1; 

如果我想要结构中指针的地址,那么语法是什么? 我试过这个:

&(*test->ptr)

在一个想法中,将parethesis减少到实际指针,之后&运算符用于返回地址。

相反,我通过反复试验发现这是正确的语法:

&(*test)->ptr;

此外,我很困惑,为什么以下语法甚至无法取消引用指向结构指针的test指针:

*test->ptr;

根据我的经验,如果没有*test左右的括号,编译器会返回一条语句,通知我我正在尝试访问某些不是结构或联合的一部分。

它必须与分配给我不完全清楚的各种格式元素的优先级有关。

有什么想法吗?

4 个答案:

答案 0 :(得分:4)

test->ptr(*test).ptr

相同

所以,我认为你想要&(test->ptr)(我不确定哪个运营商有更多优先权)。

答案 1 :(得分:3)

.->组件选择运算符等后缀运算符的优先级高于一元*&。因此,*foo->bar将被解释为*(foo->bar); *运算符将应用于foo->bar的结果。同样,&bar.foo将被解释为&(bar.foo)

因此,给出以下声明:

nodeT example;
nodeT *test1 = &example;
nodeT **test2 = &test1;

您将按如下方式访问ptr成员:

  1. example.ptr - 子表达式example的类型为nodeT;不需要间接,因此我们只使用.组件选择运算符;
  2. test1->ptr - 子表达式test1的类型为nodeT *;有一个级别的间接,所以我们需要取消引用 test1才能访问ptr成员。我们通过使用->运算符(隐式地引用test1)来实现这一点,或者我们可以显式地取消引用test1并编写(*test1).ptr
  3. (*test2)->ptr - 子表达式test2的类型为nodeT **;有两个级别的间接,因此我们需要取消引用test2 两次才能访问ptr成员。如果我们想要使用->运算符,或者我们取消引用它两次以使用.运算符 - (**test2).ptr,我们需要明确地取消引用它一次。
  4. 如果左侧操作数是.struct类型,则使用union组件选择运算符,例如example(*test1)或{ {1}}。如果左侧操作数是指针(**test2)->类型,则使用struct运算符,例如union或{{ 1}}。

    现在真正有趣 - test1成员的类型为(*test2),因此如果您想获得ptr指向的nodeT *,您可以写{{ 1}}。子表达式ptr的类型为example.ptr,因此我们使用了example.ptr->ptr组件选择运算符。但是,子表达式example的类型为nodeT,因此我们需要使用.组件选择运算符。或者,我们必须写example.ptr(请记住,nodeT *被解析为->)。

    更进一步,我们可以写(*example.ptr).ptr *example.ptr

    *(example.ptr)

    由于example.ptr->ptr->ptr已经是(*(*example.ptr).ptr).ptr类型,所以更简单一点:

    example.ptr
    example.ptr->ptr
    (*example.ptr).ptr
    example.ptr->ptr->ptr
    (*(*example.ptr).ptr).ptr
    

    最后,test

    nodeT *

答案 2 :(得分:1)

由于test是一个指针,你无法使用.运算符访问它的字段,你必须首先取消引用指针以直接获取结构:

*test

之后,您可以使用.运算符访问该字段:

(*test).ptr

->运算符是取消引用结构指针的快捷方式:

test->ptr

这将得到ptr变量,就像最后一个表达式一样。如果您想要它是ptr指向的地址,那么您就被设置了。

如果您想要ptr变量的地址,那么您需要使用&来获取其地址:

(&test)->ptr

&(*test).ptr

答案 3 :(得分:1)

假设:

nodeT n0 = { 0 };
nodeT n1 = { &n0 };

nodeT *test = &n1;

您可以使用:

test           // Pointer to n1
&test          // Pointer to test itself
test->ptr      // Pointer to n0
(*test).ptr    // Same as test->ptr
&test->ptr     // Pointer to the element of n1 (same as n1 because of the struct def'n
test->ptr->ptr // Pointer to null

例如:

#include <inttypes.h>
#include <stdio.h>

typedef struct nodeT nodeT;
struct nodeT { nodeT *ptr; };

static void print_addr(char * const tag, void *addr)
{
    printf("%-15s = %p\n", tag, addr);
}

int main(void)
{
    nodeT n0 = { 0 };
    nodeT n1 = { &n0 };
    nodeT *test = &n1;

    print_addr("test", test);
    print_addr("&test", &test);
    print_addr("test->ptr", test->ptr);
    print_addr("(*test).ptr", (*test).ptr);
    print_addr("&test->ptr", &test->ptr);
    print_addr("test->ptr->ptr", test->ptr->ptr);

    return 0;
}

示例输出:

test            = 0x7fff58829b10
&test           = 0x7fff58829b20
test->ptr       = 0x7fff58829b00
(*test).ptr     = 0x7fff58829b00
&test->ptr      = 0x7fff58829b10
test->ptr->ptr  = 0x0