2014-04-05 5 views
1

다음은 동일한 작업을 수행하고 동일한 출력을 제공하는 코드 예제입니다. 첫 번째에서는 포인터 인수를 사용하여 포인터를 사용하여 ans을 전역으로 사용하지 않습니다. 제에서, I 만든 ans 포인터 포인터를 다룰 때 *의 추가적인 사용을 배제하는 글로벌 :포인터 또는 전역 변수에 대한 포인터?

예 1

// pointer to pointer 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 

unsigned char serial[] = { 
    0x1,0x2,0x3,0x4 
}; 

void checkSerial(unsigned char* buf, unsigned char ** ans) 
{ 
    int i; 
    unsigned char *part; 

    part = 0; 
    i=2; 

    part = &buf[i]; 

    *ans = (unsigned char*)malloc(2); 
    memset(*ans,0,2); 
    memcpy(*ans,part,2); 
    printf("0x%x\n",**ans); 
    ++(*ans); 
    printf("0x%x\n",**ans); 
} 

int main(void) 
{ 
    unsigned char *ans, *buf; 

    while(1) 
    { 


     buf = malloc(4); 
     memset(buf,0,4);  
     memcpy(buf, serial, sizeof(serial)); 

     checkSerial(buf, &ans); 
     --ans; 
     printf("the value is 0x%x\n", *ans); 
     free(buf); 
     free(ans); 

     sleep(3); 
    } 
    return 0; 
} 

예 2

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 

unsigned char serial[] = { 
    0x1,0x2,0x3,0x4 
}; 

unsigned char ans[2]; 

void checkSerial(unsigned char* buf) 
{ 
    int i; 
    unsigned char *part; 

    part = 0; 
    i=2; 

    part = &buf[i]; 

    int j; 
    for(j=0;j<2;j++) 
    { 
     ans[j] = part[j]; 
    } 

    printf("0x%x\n",*ans); 
    ++(*ans); 
    printf("0x%x\n",*ans); 
} 

int main(void) 
{ 
    unsigned char *buf; 

    while(1) 
    { 


     buf = malloc(4); 
     memset(buf,0,4);  
     memcpy(buf, serial, sizeof(serial)); 

     checkSerial(buf); 

     printf("the value is 0x%x\n", *ans); 
     free(buf); 

     sleep(3); 
    } 
    return 0; 
} 

기술은 C에서 선호?

+2

개인적으로 나는 사용하지 않을 것입니다. 당신은 이미 while 루프에서 buf를 할당하여 시리얼을 넘겨 주므로 ID는 while 루프에도 ans를 할당하고이를 checkSerial에 전달하여 채워지게됩니다. 또한 글로벌 ans는 그 답을 맞추기에 충분히 크지 않습니다. 단지 1 바이트가 2가 아님. – Dampsquid

+0

'- ans' 포인터로'ans' 포인터를 감소시키고 싶습니까? 아마도 당신은 값을 줄이는 것을 의미했을 것입니다. 그것은'- * ans;'...입니까? – CiaPan

+0

전역 변수는 확실히 권장되지 않지만 변수를 서로 멀리 할당하면 포인터에 대한 포인터를 만들면 어셈블리 수준에서 두 수준의 간접 참조가 만들어집니다. 이러한 변수가 단일 캐시에 캐시되지 않으면 잠재적 인 성능 손실이 발생합니다 프로세서가 스톨하고 두 번째 변수의 주소를 계산하고 해당 변수/캐시 라인을 작동하도록 유도합니다. – Recker

답변

3

필요하지 않은 경우 전역 변수를 사용하지 마십시오. 첫 번째 예가 좋습니다.

전역 변수는 모든 함수에서 쉽게 액세스 할 수 있으며 프로그램의 일부에서 읽거나 수정할 수 있으므로 가능한 모든 용도를 기억하거나 추론하기가 어렵습니다.

+0

첫 번째 예를 의미한다고 생각합니다. 두 번째 것은 전역 변수가있는 것입니다. –

+0

또한 반환 된 포인터가 호출자에 의해 해제되어야한다면, 나는 그것을 말해주는 함수 프로토 타입 주석을 읽을 것으로 예상된다. –

+0

@ Étienne; 죄송합니다. 수정 된 :) – haccks

0

필자는 개인적으로 전역 변수를 정의하는 것을 좋아하지 않습니다.

그러나 일부 사람들은 포인터 개념이 매우 혼란 스럽다고 말합니다. 그래도 그 생각은하지 않습니다 ..

내 조언은, 당신이 포인터와 혼동하면 전역 변수를 정의하는 것을 피하려고합니다. 그렇지 않으면, 포인터를 사용하십시오 ... :)

+4

포인터는 모든 사소한 프로그래밍 기술의 중추입니다. 그들은 피하지 말아야합니다. – StoryTeller

1

가능한 한 변수를 사용중인 범위에 가깝게 유지하십시오. 이렇게하면 변수 및 잠재적 인 이름 지정 문제에 대한 예기치 않은 값을 방지 할 수 있습니다.

0

TL; DR : 해결 방법 1과 2가 모두 잘못되었습니다.

예제를 작성한 방법은 컴파일 타임에 ans와 buf의 크기를 알기 때문에 malloc을 쓸모 없게 만든다. 컴파일 타임에 실제로 알고 있다면 malloc을 전혀 사용하지 말고, 변수를 선언한다. 스택 C에서는 일반적으로 가능한 한 동적 메모리 할당을 피하고 응용 프로그램에서 버퍼가 가질 수있는 최대 크기를 저장할 수있는 버퍼를 만드는 것을 선호합니다. 그것은 처음부터 이런 종류의 문제를 피합니다. 예제를 작성한 방법은 컴파일시에 ansbuf의 크기를 알기 때문에 malloc을 쓸모 없게 만듭니다. 동적 메모리 할당이 유용 할 수있는 유일한 곳은 컴파일 시간에 크기를 알 수없는 버퍼에 대한 것이지만 여전히 그것을 피할 수 있습니다 (아래 참조). buf이 들어오는 메시지이고 ans이 메시지에 대한 응답 인 경우 적어도 가변 길이 메시지를 사용하는 경우 ans의 크기를 컴파일 할 때 알 수 없습니다.

버전 2가 작동하지 않아 작동하지 않습니다! 먼저 ans을 크기 1의 배열로 선언하고 인덱스 2까지 반복합니다 (이제 편집 한 것입니다). 두 번째로 배열 ans을 전역으로 선언하려면 컴파일시에 크기를 알아야하며, 컴파일시에 크기를 알고 있다면 checkSerial 배열에 ans을 선언하면됩니다. 또한 C에서 여러 함수가 사용하는 변수를 선언 할 때 정적 변수를 선언하는 것을 잊지 마십시오. 그렇지 않으면 프로젝트의 모든 파일에서 액세스 할 수 있습니다.

동적 할당을 피하는 해결책, 당신은 당신이 개 솔루션의 단점을 피하기주의 사항 : 포인터와 전역 변수에 대한 포인터를, 당신은 동적 할당을 사용하지 않기 때문에 또한 프로그램이 누설 할 수 없습니다

enum {MSG_MAX_SIZE = 256 }; 
typedef struct message { 
    uint8_t payload[MSG_MAX_SIZE]; 
    size_t msg_size; 
} message_t; 

void checkSerial(const message_t *buf, message_t *ans) 
{ 
    //parse buf and determine size of answer 
    ... 
    ... 
    //fill answer payload 
    ans->msg_size = buf[42]; 
} 

int main(void) 
{ 
    while (1) { 
     message_t buf; 
     getMsg(&buf); 
     message_t ans; 
     checkSerial(&buf, &ans); 
    } 
} 
관련 문제