2013-02-02 3 views
6

나는 문자열을 인자로 받아야하는 많은 함수를 가지고 있는데, 이것들은 char*을 사용하지만, 바이트 배열을 기대하는 모든 함수는 또한 char*을 사용한다.문자열과 바이트 배열을 구분합니까?

문제는 null-terminator를 찾을 수 없기 때문에 모든 종류의 오버플로를 일으키는 문자열 배열 함수에 바이트 배열을 전달하는 실수를 쉽게 할 수 있다는 것입니다.

대개 어떻게 이런 경향이 있습니까? 모든 바이트 배열 함수를 uint8_t으로 바꾸면 상상할 수 있습니다. 그런 다음 문자열을 전달할 때 컴파일러가 서명 된 값에 대해 경고합니다. 또는 여기에 올바른 접근 방식은 무엇입니까?

+0

바이트 배열에 대한 래퍼 만들기 ?? –

+0

@VaughanHilts 어떻게 저의 문제가 해결되는지 모르겠습니다. – Muis

+0

문자열 *은 바이트 배열입니다. C에서 배열을 전달할 수는 없지만 첫 번째 요소에 대한 포인터 만 전달할 수 있으므로 일반적으로 크기를 전달해야합니다. 배열에 0 값이 들어 있는지 확인하기 만하면됩니다. 그럴 경우 "문자열"입니다. 그렇지 않으면 그렇지 않습니다. –

답변

1

문제는 당신이 생각하는 것보다 C에서 더 일반적이다를 사용하는 것을 의미한다. char*char[] 함수 파라미터에 대해 동일하기 때문에, 이러한 파라미터는 세 가지 의미 개념을 지칭 할 수있다 :

  • 하나 char 객체 포인터 (이 포인터 타입의 "공식"의 정의이다)
  • char 어레이
  • 문자열이며 대부분의 경우

는 C 표준에서 mondern 인터페이스가 지정되지 않은 바이트 AR void* 위해 사용 가능 ray를 사용하고 있으므로 해당 규약을 준수하고 문자열에만 char*을 사용해야합니다.

char[]은 그 자체로 거의 사용되지 않을 수 있습니다. 나는 이것들에 대해 많은 유스 케이스를 상상할 수 없다. 숫자로 생각하면 signed 또는 unsigned 변형을 사용해야합니다. 비트 패턴 unsigned char을 선택해야합니다.

당신이 정말로 함수 매개 변수로 배열 (char 여부) 당신이 명확하게 표시하여 코드의 캐주얼 독자들에게 그 사실을 표시 할 수 있습니다를 의미하는 경우 :

void toto(size_t n, char A[const n]); 

void toto(size_t n, char *const A); 
에 해당

하지만 의도를 명확하게 나타냅니다. 그리고 미래에는 경계를 확인하는 도구가있을 수도 있습니다.

2

나는 일반적으로 * 다음

typedef struct { 
    unsigned char* data; 
    unsigned long length; 
    unsigned long max_length; 
} array_t; 

같은 배열 뭔가 다음 array_t 통과 주위

하고 *

void array_create(array_t* a, unsgined long length) // allocates memory, sets the max_length, zero length 

void array_add(array_t* a, unsigned char byte) // add a byte 

+1

은'unsigned long' 대신'size_t'를 사용하는 것이 더 낫습니다 –

+0

네가 옳다. –

0

쓰기 array_t 걸릴 배열 함수를 만들 문자열과 바이트를 모두 처리하는 공통 구조체. type 만약

struct str_or_byte 
{ 
    int type; 
    union 
    { 
     char *buf; 
     char *str; 
    }pointer; 
    int buf_length; 
} 

다음 pointer.bufbuf_length 개까지 액세스 문자열이 아니다. 그렇지 않으면 buf_length을 확인하지 않고 직접 pointer.str에 액세스하고 null로 끝나는 문자열로 유지하십시오.

또는 길이 만 고려하여 문자열을 바이트 배열로 유지하십시오. 문자열에 널 문자로 끝나지 마십시오.

struct str_or_byte 
{ 
    char *buf; 
    int buf_length; 
} 

길이를 고려하지 않는 문자열 처리 기능을 사용하지 마십시오. 즉 strncpy, strncat, strncmp ... 대신 strcpy, strcat, strcmp ...

0

c를 사용한다. 내가 사용하는 규칙은 다음과 같습니다 (표준 라이브러리 이후).

void foo(char* a_string); 

void bar(void* a_byte_array, size_t number_of_bytes_in_the_array); 

이것은 쉽게 기억할 수 있습니다. 만약 당신이 하나의 char * ptr를 넘겨 준다면, 그것은 null로 끝나는 char 배열이어야한다.