Почему эти переменные явно меняют тип? - PullRequest
3 голосов
/ 02 января 2011

Python избаловал меня, и попытка обернуть мой разум вокруг C теперь кровопролитие глупых ошибок.Это тот, который я не совсем понимаю.

Я хотел C эквивалент Python's os.path.split, но точного эквивалента нет.strsep выглядит достаточно схожим образом, но требует простого массажа.

Во-первых, я определил свой тип пути: строка заданной длины.

#define MAX_PATH_LEN 200 /* sigh */
typedef char t_path[MAX_PATH_LEN];

Затем я написал некоторый код, который выполняет настоящий массаж, пытаясь избежать побочных эффектов - просто чтобы защитить вещи от дурака.

typedef struct {
    t_path next;
    t_path remainder;
} t_path_next

t_path_next path_walk_into(t_path path) {
    t_path_next output;

    t_path my_next, my_remainder = "/";
    strncpy(my_next, path, MAX_PATH_LEN);

    strsep(&my_next, my_remainder);

    output.remainder = my_remainder;
    output.next = my_next;
    return output;
}

gcc, однако, не впечатлил.

badp@delta:~/blah$ gcc path.c -Wall
path.c: In function ‘path_walk_into’:
path.c:39: warning: passing argument 1 of ‘strsep’ from incompatible pointer type
/usr/include/string.h:559: note: expected ‘char ** __restrict__’ but argument is of type ‘char (*)[200]’
path.c:41: error: incompatible types when assigning to type ‘t_path’ from type ‘char *’
path.c:42: error: incompatible types when assigning to type ‘t_path’ from type ‘char *’

Я сбит с толку запиской - чем char ** и char (*)[200] действительно отличаются - но ошибка еще более странная.Я хочу назначить переменную, которую я объявил t_path, в поле типа t_path, но я не получаю.

Почему это так?


Для всех, кого это интересуетВот правильно работающая версия функции:

t_path_next path_walk_into(t_path path) {
    t_path_next output;
    t_path my_path, delim = "/";
    char* my_path_ptr = my_path;    
    strncpy(my_path, path, MAX_PATH_LEN);

    strsep(&my_path_ptr, delim); //put a \0 on next slash and advance pointer there.

    if (my_path_ptr == NULL) //no more slashes.
        output.remainder[0] = 0;
    else
        strncpy(output.remainder, my_path_ptr, MAX_PATH_LEN);
    strncpy(output.next, my_path, MAX_PATH_LEN);

    return output;
}

Ответы [ 2 ]

4 голосов
/ 03 января 2011

Ошибки: Вы не можете напрямую назначить массив, такой как строка, в C. Вы должны скопировать char по char или вызвать str (n) cpy, что сделает это за вас.

3 голосов
/ 03 января 2011
  • Предупреждение: вы, вероятно, уже знаете, что массив может распадаться на указатель. Это, например, то, что делает массив приемлемым в качестве аргумента функции, где ожидается указатель. В вашем случае у вас есть указатель на массив: нет такой причины, чтобы преобразовывать его в указатель на указатель.

    Для справки, стандарт C99 гласит (6.3.2.1/3):

    За исключением случаев, когда это операнд оператора sizeof или унарный оператор & , или является строковый литерал, используемый для инициализации массива, выражение, имеющее тип «массив типа», преобразуется в выражение с указателем типа ‘‘ на тип ’’ , которое указывает на начальный элемент объект массива и не является lvalue.

    Вы находитесь в контексте унарного &: для вас нет конверсии.

  • Из-за ошибки: она уже получена, но присвоение массива напрямую невозможно. Вы можете использовать strcpy или strncpy.

...