2015-01-07 7 views
0

안드로이드 용 lwIP를 이식하고 유닉스 용 포트에서 일부 코드를 추출했는데 지금 다음 논리를 컴파일 할 수없는 이유를 모르겠습니다. .struct **와 C. struct * in dereference와 address-of 연산자의 혼동

유닉스 용 포트에 사용 된 기능은 #definetypedef입니다. 나는

#ifndef FUNC_H 
#define FUNC_H 
#include <stdint.h> 

struct sys_sem { 
    unsigned int c; 
}; 

#define sys_mutex_t     sys_sem_t; 
typedef struct sys_sem * sys_sem_t; 

void sys_arch_sem_wait(struct sys_sem **s, int timeout); 

#endif 

나는 또한, 자신의 #define의 복사 func.h의 코드를 작성하고 sys.h

#ifndef SYS_H 
#define SYS_H 

#define sys_mutex_lock(mutex)   sys_sem_wait(mutex) 
#define sys_sem_wait(sem)     sys_arch_sem_wait(sem, 0) 

#endif 

로 붙여 넣기 그리고 내 기능은 내가 자바에서 호출이 기계적 인조 인간; 그것은 com_sample_MainActivity.c

#include "func.h" 
#include "sys.h" 

static sys_mutex_t 
mem_mutex; 

JNIEXPORT jstring JNICALL Java_com_sample_MainActivity_messageFromNativeCode(
     JNIEnv *env, jobject thisObj) { 
    sys_mutex_lock(&mem_mutex); 
    sys_mutex_lock(121); // Even this can be compiled 
    return (*env)->NewStringUTF(env, "Hello from native code!"); 
} 

sys_mutex_tsys_sem_t의 동의어 파일에, 그리고 sys_sem_tsys_sem *의 동의어입니다. 내가 맞습니까? 내 서명 sys_arch_sem_waitstruct sys_sem **s. However, I pass the address of sys_mutex_t which after all the #define s means the same as passing a sys_sem`을 수락하고 코드가 컴파일됩니다.

에도이 나는

sys_mutex_lock(121); // Even this can be compiled. Why? 

그래서 sys_mutex_lock 아무것도 전달할 수

을 할 수 컴파일 할 수 있습니다?

내 테스트.

01-07 14:46:40.695: D/Sample(22086): s != NULL 
01-07 14:46:40.695: D/Sample(22086): *s == NULL 

예상되는 동작 : 여기

#include "func.h" 
#include <android/log.h> 

void sys_arch_sem_wait(struct sys_sem **s, int timeout) { 
    if (s == NULL) { 
     __android_log_print(ANDROID_LOG_DEBUG, "Sample", "s == NULL"); 
    } else { 
     __android_log_print(ANDROID_LOG_DEBUG, "Sample", "s != NULL"); 
    } 
    if (*s == NULL) { 
     __android_log_print(ANDROID_LOG_DEBUG, "Sample", "*s == NULL"); // It causes the failure 
    } else { 
     __android_log_print(ANDROID_LOG_DEBUG, "Sample", "*s != NULL"); 
    } 
} 

그리고는 로그 캣의 출력입니다.

나는이 ...

sys_mutex_lock(<arg>); 

가 ...에 해당,

void sys_arch_sem_wait(struct sys_sem **s, int timeout) 

가 다른 서명 제시 매크로 감안할 때

void sys_arch_sem_wait(struct sys_sem *s, int timeout) 
+2

경고없이 컴파일 되었습니까? –

+0

@SouravGhosh, 타입 비호 환성에 대한 두 가지 경고가 있습니다 : 경고 : 호환되지 않는 포인터 타입 [기본값으로 활성화 됨]에서 'sys_arch_sem_wait'의 인수 1 전달'및 'sys_arch_sem_wait'의 경고 : 전달 인자 1은 캐스트없이 정수에서 포인터를 만듭니다. [기본적으로 사용 설정 됨] ' –

+1

그리고 그 다음에 _ignore_를 선택 했습니까? 왜? 그들은 웬일인지 거기에있다? 그것들은 아주 자명하다. 컴파일러를 비난하지 마십시오. 그것은 자신의 직업이었습니다. 우리는 그 중 하나입니다. :-) –

답변

1

가 있어야 것으로 예상. ..

sys_arch_sem_wait(<arg>, 0); 

... 여기서 sys_arch_sem_wait()의 첫 번째 인수는 struct sys_sem **으로 선언됩니다.

예, sys_mutex_tsys_sem_t의 동의어입니다.

예, sys_sem_tstruct sys_sem *의 동의어입니다.

내 서명 sys_arch_sem_waitstruct sys_sem **s을 허용합니다. 그러나, 나는 #defines이 결국 sys_sem을 전달하는 것과 같은 것을 의미하고 코드가 컴파일되는 sys_mutex_t의 주소를 전달합니다.

번호 사용자는 주소의 역 참조 연산자 (*)와 조작자 (&)를 혼동한다. sys_mutex_t의 주소 유형은 통화에 대해 올바른 유형 인 struct sys_sem **으로 바뀝니다.

sys_mutex_lock에 아무 것도 전달할 수 없습니까?

C는 정수 유형의 모든 값을 모든 포인터 유형으로 변환 할 수 있으며 그 반대의 경우도 가능합니다. C는 또한 모든 객체 유형에 대한 포인터가 다른 객체 유형에 대한 포인터로 변환되도록 허용합니다. 호환되는 C 컴파일러 이 C가 허용하므로 이러한 명령문을 컴파일 할 수 있어야하며 모든 컴파일러에서 기본적으로 허용 할 것으로 기대합니다.

반면에 이러한 변환의 결과가 의미가 있거나 적절한 지 여부는 전혀 다른 질문입니다. 이러한 많은 변환은 정의되지 않은 동작을 가져오고 많은 다른 변환은 정의되지만 원치 않는 동작을 발생시킵니다. 결과적으로, C++ 컴파일러는 최소한 암시적일 때 그러한 경고가 수동으로 비활성화되지 않는다면 그러한 변환에 대한 경고를 발행해야합니다.

결론은 그렇습니다. 컴파일러는 sys_mutex_lock()에 정수 또는 포인터 인수를 전달해야하지만, struct sys_sem **이 아닌 값을 전달하려고하면 경고해야합니다. 그것이 실제로 당신이 관찰하는 것 같습니다.

전반적으로 사용자가 설명하는 컴파일러 동작에는 문제가 없습니다.

+0

나는 당신을 생각합니다. '당신은 주소 연산자 (&)를 참조 연산자 (*)와 혼동하고 있습니다. 그것은 제 실수였습니다. 그래서'& sys_mutex_t '는 포인터의 주소를 의미하는'& (* sys_sem)'을 의미합니다. 그리고 포인터의 주소는 이중 포인터 –

+1

예에 해당합니다. 포인터의 주소는 포인터에 대한 포인터입니다. 나는 그 용어, 또는 아마도 "포인터 포인터"를 선호하지만, 그 포인터를 이중 포인터라고 부를 수도 있습니다. –