Странное поведение при возврате "строки" с C - PullRequest
0 голосов
/ 24 декабря 2018

Я новичок в C, и я обнаружил, что моя программа работает очень странно:

Вот код:

#include <stdbool.h>
#include <string.h>
#include <conio.h>
#include <stdio.h>

char * p(char arg[] , char sym[] , int i , bool rv) {
    char head[i],w[i];
    strncpy(head,arg,i); head[i] = "\0";
    int l;
    for (l = 0 ; l <= (int)(strlen(sym) / i) ; l++) {
        strncpy(w,sym+l*i,i); w[i] = "\0";
        if (strcmp(head,w) == 0) {
            if (rv) { return head; } else {
                char v[strlen(arg) - i];
                strcpy(v,arg+i);
                v[strlen(arg)-i] = "\0";
                return v;
            };
        };
    };
    return arg;
}

int main() {
    printf(p("/parameter","+-\\/",1,false));
    getch();
}

Проблема MAIN заключается в том, чтовозвращаемое значение функции - это либо «строка» случайно сгенерированных кодов, либо просто ничего.

Ожидалось, что он вернет / для return h; и parameter для return v;.

Другая проблема заключается в том, что при компиляции программы не обнаружено ни одной ошибки, кроме множества предупреждений о том, что function returns address of local variable и assignment makes integer from pointer without a cast.

С другой стороны, return arg; в очень мирном ине выдает никакой ошибки.(Попробуйте изменить мои коды в p("/parameter","+-\\/",1,false), если не верите.) Что я сделал не так?


Использование функции:

p (« arguments_passed_to_check », « символов_принято to_be_at_the_front », «Отдельные_for_each_ i _characters», «return_header_instead_of_parameter»)

ожидаемый 1037

ожидаемый результат: 1037 **p("-argue","/\\-",1,false) возвращает argue

p("/help","me",1,false) возвращает /help

p("/help","me",1,true) возвращает (null)

p("--parameter","--++",2,false) возвращает parameter

p("--parameter","--++",2,true) возврат --


Резюме для чего я прошу помощи:

  • За исключением return arg, другие возвращаемые деталистранно: return head; выдаёт случайные символы;return v; вообще ничего не возвращает.Как я могу позволить им работать как ожидаемые результаты?

  • Почему есть эти предупреждения?

1 Ответ

0 голосов
/ 24 декабря 2018
  1. Поскольку head определяется как char head[i], его последний элемент - head[i-1].Попытка доступа head[i] имеет поведение, не определенное стандартом C.

  2. Поскольку w определяется как char w[i], его последний элемент - w[i-1].Попытка доступа w[i] имеет поведение, не определенное стандартом C.

  3. Поскольку v определяется как char v[strlen(arg) - i], его последний элемент - v[strlen(arg) - i - 1].Попытка доступа к v[strlen(arg) - 1] имеет поведение, не определенное стандартом C.

  4. Поскольку w определяется внутри заключенного в фигурные скобки блока операторов без extern или static,он имеет автоматическую продолжительность хранения, связанную с блоком, поэтому он существует только тогда, когда функция является блоком.Когда выполняется оператор return, w перестает существовать (в абстрактной машине Си).Оператор return w; пытается вернуть указатель на первый элемент w (поскольку в этом случае массив автоматически преобразуется в указатель на его первый элемент).При выполнении этого оператора return указатель становится недействительным.

  5. Поскольку v определен внутри заключенного в фигурные скобки блока операторов без extern или static, онимеет автоматическую продолжительность хранения, связанную с блоком, поэтому v существует только во время выполнения оператора.Когда return v; выполняется, выполнение блока заканчивается, и возвращаемый указатель становится недействительным.

  6. head[i] является символом, но "\0" является строкой, содержащей один символ,поэтому head[i] = "\0"; - неправильное назначение.Строка будет преобразована в указатель на свой первый элемент, в результате чего будет предпринята попытка назначить указатель на char.Это нарушение ограничения, и ваш компилятор должен выдать предупреждение за него.Та же проблема возникает в w[i] = "\0"; и v[strlen(arg)-i] = "\0";.Правильный код будет head[i] = '\0'; (как только размер head будет установлен для включения элемента head[i]).

Средства защиты включают:

  • Определите, чтобы каждый массив был достаточно большим для всех элементов, которые должны быть записаны в него.
  • Чтобы вернуть строки, созданные внутри функции, либо динамически выделите для них место (как в malloc), создайте строки внутримассивы, предоставляемые вызывающей стороной, или использовать массивы со статической продолжительностью хранения.Если вы используете первую опцию, динамически создаваемые массивы, вы должны предусмотреть освобождаемое пространство (например, когда вызывающая сторона передает их free, когда с ними делается).Вам следует избегать использования массивов со статической продолжительностью хранения, поскольку они имеют ограниченное и проблемное использование (например, тот факт, что для каждого определения существует только один такой массив, но функция может вызываться несколько раз вызывающими программами, каждый из которых хочет иметь свои собственные отдельные данные).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...