предупреждение C4047: '=': 'int' отличается по уровню косвенности от 'char *' - PullRequest
1 голос
/ 11 января 2010
int utstrlen(char* src){
    int length=0 ;
    if(isOurs(src) ==1){
        length = src - 2 * sizeof(int);
    }
    return length;
}

Я получил предупреждение C4047: «=»: «int» отличается по уровням косвенности от ошибки «char *» от строки length = src - 2 * sizeof(int); Может кто-нибудь объяснить, что с ним не так? Спасибо!

Ответы [ 5 ]

3 голосов
/ 11 января 2010

Исходя из вашего предыдущего вопроса , вы хотите

length = *((int *)(src - 2 * sizeof(int)));

хотя это не предполагает заполнения. Лучше было бы использовать offsetof():

String *beg = (String *)(src - offsetof(struct String, ptr));
length = beg->length;

Я предполагаю, что вы используете структуру из вашего предыдущего вопроса.

1 голос
/ 11 января 2010

Я подозреваю, что у вас есть строковая структура:

struct string {
    int length;
    int somethingelse; /* thanks alok */
    char *str;
}

а эта функция пытается получить доступ к полю длины при указателе на строку? Я прав? Я предполагаю, что именно это проверяет isOurs (чтобы убедиться, что это не какая-то старая строка). В этом случае вы хотите это:

length = (*((int*)(src - 2))) * sizeof(int);

int utstrlen(char* src){
    int length=0 ;
    if(isOurs(src) ==1){
          length = *((int*)(src - (2 * sizeof(int)))); /* from str moveback 2 ints worth*/
    }
    else {
        //return strlen(src) ?
    }
    return length;
}

Но в идеале вы бы этого не делали. Это не портативный или ремонтопригодный. Что произойдет, если компилятор вставит отступ, о котором вы не знаете? Стандарт C99 гласит, что он не будет помещать отступ между массивом размером 0 и предыдущим полем, но ничто не помешает ему сходить с ума от других (например, если у вас есть смесь типов).

Что произойдет, если кто-то придет позже и вставит больше данных в структуру? Естественно, они должны были бы поместить это перед полем str, поскольку «структура взломать» работает, имея его в конце. В идеале для этого следует использовать offsetof (), который является стандартным макросом. Alok предлагает лучшее решение здесь и Интерпретация уродливого макроса (всего 1 строка)

edit (кажется, что за 2 минуты мне потребовалось набрать этот последний последний абзац, ответ Alok на offsetof () был принят поверх этого;))

0 голосов
/ 11 января 2010

src - 2 * sizeof(int) является арифметикой указателя - результатом этого выражения является еще один char* указатель. Вы пытаетесь присвоить char* для length, то есть int, и именно поэтому вы получаете ошибку. Я не знаю, что должна делать эта функция, но если вы действительно этого хотите, вы можете привести значение к int: length = (int)(src - 2 * sizeof(int)). Но опять же, я не вижу смысла в вашей функции.

0 голосов
/ 11 января 2010

Конечно.

src - указатель; 2 * sizeof(int) является целочисленным значением.

Хотя это действительно законно

  1. для вычитания двух указателей друг от друга (в результате различия в их адресах, как целое число целочисленный тип, возможно size_tptrdiff_t) а также

  2. для вычитания целого числа из указателя (в результате получается указатель на местоположение немного перед этим указателем),

Недопустимо пытаться присвоить результат из (2) целочисленной переменной (length).

0 голосов
/ 11 января 2010

src является char *; длина составляет int. Поэтому компилятор обрабатывает эту строку как:

length = (int) (src - 2 * sizeof(int));

Я не уверен, что вас смущает насчет предупреждения, и я также не понимаю, что пытается сделать ваш код. Поэтому я предлагаю попробовать следующий тестовый код и посмотреть, что он печатает:

void test(void) {
    char *foo = "hello\n";

    printf("%s\n", foo);
    printf("%d\n", (int) foo);
    printf("%s\n", foo+1);
    printf("%d\n", ((int) foo) + 1);
}

вы заметите, что арифметика имеет больше смысла при одном использовании указателя, чем при другом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...