2011-04-21 4 views
-2

C에서 작성한 코드에서 연산자 '->'를 사용하는 동안 이상한 부작용이 나타납니다. 사용 된 포인터가 켜져 쓰레기로 변경되었습니다. 더 구체적으로연산자에서 '->'를 사용하는 이상한 부작용

:

나는 다음과 같은 구조체가 : 나는 디버거를 사용할 때 내가 알아 낸

ListElement ListGetFirst(List list) 
{ 
    if(list == NULL || list->head==NULL) 
    { 
    return NULL; 
    } 
    list->current=list->head; 
    Node* head =list->head; // here is the problem 
    ListElement data = (*head)->data; 
    return data; 
} 

:

typedef void* ListElement ; 

typedef struct List_t* List ; 

typedef struct Node_t* Node; 

Struct Node_t { 
    ListElement data ; 
    Node next; 
} 

Struct List_t { 
    Node* head; 
    Node* current 
} 

나는 ListGetFirst()를 다음을 사용, 내가 유선 동작을 얻을 수를 표시된 포인터에서 포인터 목록 -> 머리글이 바뀌었다.

난 정말 아무 생각도 이유가 없다, 나는 알고하지 않았다 '->'부작용 사전에

감사

+0

대부분의 경우 오해를 느끼고 있습니다. – NPE

+1

아니요, -> C에서 부작용이 없습니다. 왜'return list-> head-> data'를하지 않습니까? – Brad

+7

그것은 여러분의 코드이며,'->'의 "부작용"은 아닙니다. 그 정도는 확실합니다. – meagar

답변

4

GAH, 형식 정의 뒤에 숨겨진 포인터; 유형이 완전히 불투명하지 않는 한, 거의 항상 나쁜 주주입니다. 제 이익을 위해 typedef를 꺼내서 여러분이 실제로 놀고있는 것을보다 쉽게 ​​볼 수있게 할 것입니다.

struct Node_t { 
    void *data ; 
    struct Node_t *next; 
}; 

struct List_t { 
    struct Node_t **head; 
    struct Node_t **current; 
}; 

void *ListGetFirst(struct List_t *list) 
{ 
    if(list == NULL || list->head==NULL 
    {   
    return NULL; 
    } 
    list->current=list->head;    
    struct Node_t **head =list->head; // here is the problem 
    void *data = (*head)->data; 
    return data;   
}   

나는 nuthin '을 얻었습니다. 유형이 모두 일치하는 것으로 보입니다. -> 연산자는 가장 두드러지게 이 아니며에는 부작용이 없습니다. 포인터를 역 참조하는 것뿐입니다. headcurrent에 대한 간접 지정의 추가 수준은 struct List_t입니다. 헤드 스크래 처 (head scratcher)가되어 할당이나 할당이 올바르게되어 있는지 궁금합니다. 내가 생각할 수있는 것은 list->head이 실제로 소유하고있는 메모리를 가리키고 있지 않으며, 그 점에 도달하면 어떻게 든 덮어 쓰게됩니다 (IOW, 코드의 다른 곳에서 정의되지 않은 동작이 호출 됨).

요약하면 문제는 게시 한 코드에 없습니다. 아마 당신이리스트 요소를 할당하고 할당하는 곳일 것입니다.

+0

고마워, 그게 내가 찾고 있던 해답이야. – RanZilber

9

당신이 정확하게 당신이 원하는 무엇을 확신 할 수 있습니까? 당신이 Node_t에 대한 포인터로 노드를 정의하기 때문에

typedef struct Node_t* Node; 

Node* head =list->head; 

, 당신은 일을해서는 안 :

Node head =list->head; 

편집을이 : 전체를 요약하면, 나는 생각이 타입 정의가

한다 오해의 소지가 있습니다.

typedef struct Node_t* Node; 

간단히 말하면 :

typedef struct Node_t Node; 
+1

맞아요. 그렇지 않으면 Node_t **가 생깁니다. – SolarBear

+0

@karlphillip - 구조체를보십시오. 나는 list_t struct Node * 변수에 있고 Node는 갖지 않기로 결정했다. – RanZilber

+1

나는 Karl이 이것을 가지고 있다고 생각한다; 포인터의 주소 인 Node *를 사용하고 있습니다. 포인터의 값은 목록의 주소가 아닙니다. – Jess

1

포인터를 사용하고 있습니다.

List_t에 머리를 Node *로 정의합니다. 여기서 Node는 이미 Node_t *입니다.

HTH

마리오

+0

그게 내 대답에 4 분 전에 게시 한 것이 아닌가? = P – karlphillip

+0

@Mario 스푼 - 나는 그런 목록을 만들어 달라는 요청을 받았습니다. 그 이상하고 더 나은 솔루션은 단 하나의 포인터로 구현하는 것이지만,이 솔루션에 국한된다는 것을 알고 있습니다. 왜 그게 문제가되어야합니까? – RanZilber

+0

@karlphillip : grrrrrrrrrr ;-) –

관련 문제