Проблема с функцией C типа char указатель, кто-то может объяснить? - PullRequest
4 голосов
/ 07 апреля 2010

Может кто-нибудь помочь мне найти ошибки в этой функции C?

    char* f(int i) {
            int i; 
            char buffer[20];
            switch ( i ) {
                    1: strcpy( buffer, "string1");
                    2: strcpy( buffer, "string2");
                    3: strcpy( buffer, "string3");
                    default: 
                    strcpy(buffer, "defaultstring");
            }
            return buffer;
    }

Я думаю, что это связано с преобразованием типов. Мой компилятор выдает предупреждение, что «объявление int i затеняет параметр».

Ответы [ 11 ]

8 голосов
/ 07 апреля 2010
  char* f(int i) {
            int i; 

Ошибка 1: локальный параметр 'i' скрывает аргумент 'i' для функции

        char buffer[20];
        switch ( i ) {

Ошибка 2: вы используете локальную переменную 'i', которая не инициализирована.

                1: strcpy( buffer, "string1");
                2: strcpy( buffer, "string2");
                3: strcpy( buffer, "string3");
                default: 
                strcpy(buffer, "defaultstring");
        }
        return buffer;

Ошибка 3: вы возвращаете указатель на элемент в локальном массиве, этот указатель недействителен, когда функция возвращает «буфер» вышел из области видимости.

6 голосов
/ 07 апреля 2010

Ну, во-первых, вам не хватает объявления 'case' в вашем операторе switch, а также разрывы в конце оператора. Попробуйте изменить свой код на это:

    char* f(int i) {
            int i; 
            char buffer[20];
            switch ( i ) {
                    case 1: strcpy( buffer, "string1"); break;
                    case 2: strcpy( buffer, "string2"); break;
                    case 3: strcpy( buffer, "string3"); break;
                    default: 
                    strcpy(buffer, "defaultstring"); break;
            }
            return buffer;
    }

Кроме того, вы переопределяете свой параметр i локальной переменной с именем i. Так что удалите это:

    char* f(int i) {
            char buffer[20];
            switch ( i ) {
                    case 1: 
                         strcpy( buffer, "string1"); 
                         break;
                    case 2: 
                         strcpy( buffer, "string2"); 
                         break;
                    case 3: 
                         strcpy( buffer, "string3"); 
                         break;
                    default: 
                         strcpy(buffer, "defaultstring"); 
                         break;
            }
            return buffer;
    }

Наконец, вы возвращаете указатель на символ, который указывает на локально статически объявленный массив символов с именем buffer. buffer выпадает из области видимости, как только возвращается указатель на его первый элемент (что делает ваш оператор return). Это означает, что вы получите указатель на переменную, которой больше не существует. Чтобы это исправить, вы можете передать указатель на буфер в функцию, например так:

    void f(char *buffer, int i) {
            switch ( i ) {
                    case 1: 
                         strcpy( buffer, "string1"); 
                         break;
                    case 2: 
                         strcpy( buffer, "string2"); 
                         break;
                    case 3: 
                         strcpy( buffer, "string3"); 
                         break;
                    default: 
                         strcpy(buffer, "defaultstring"); 
                         break;
            }
    }

Эта последняя версия должна работать, при условии, что вы убедитесь, что buffer достаточно длинный, чтобы принять строку. Если вы действительно хотите сделать его безопасным, возьмите также длину buffer и сравните ее с длиной копируемой строки.

2 голосов
/ 07 апреля 2010

Существует три больших проблемы:

  1. int i объявлен как параметр функции и как локальная автоматическая переменная.Удалите оператор int i; в строке 2.
  2. Ключевое слово case должно обрабатывать каждое значение в операторе переключения (например, case 1: вместо 1:).
  3. Вы возвращаетеуказатель на автоматическую переменную.Переменная char buffer[20]; помещается в стек и больше не действительна после возврата из функции.Вместо этого вы должны выделить память в куче и вернуть указатель на нее.

Исправленная функция с использованием strdup вместо strcpy :

char * f(int i) {
    switch (i) {
    case 1:
        return strdup("string1");
    case 2:
        return strdup("string2");  
    case 3:
        return strdup("string3");
    default:
        return strdup("defaultstring");
    }
}
2 голосов
/ 07 апреля 2010

Здесь применено несколько исправлений

    const char* f(int i) {
            switch ( i ) {
                    case 1: return "string1";
                    case 2: return "string2";
                    case 3: return "string3";
            }
            return "defaultstring";
    }
1 голос
/ 07 апреля 2010
  1. Вам не нужен локальный int i, если вам дали int i.
  2. Инстада

    1: blabla;

вам понадобится

case 1: blabla; break;

(для 1: 2: и 3: но не для значения по умолчанию)

3. Я не уверен в этом (долгое время не делал C), но думаю, что буфер будет пуст после завершения функции Таким образом, вам придется передать массив символов (и размер), а затем изменить его. В этом случае вам не нужно ничего возвращать.

1 голос
/ 07 апреля 2010

Здесь есть несколько проблем

  1. Вы переделываете i в строке 2. i уже является параметром функции. Вам не нужно переопределять его.

  2. Ваш синтаксис для оператора switch неверен. Правильный синтаксис выглядит примерно так: case 1: /* do stuff */ break; case 2: /* do other stuff */ break;

  3. Вы пытаетесь вернуть указатель на выделенный стеком буфер. Это вызовет незначительные проблемы, поскольку нет никаких гарантий того, что память не будет засорена после возврата из функции. Какова цель strcpys? Если вы просто хотите вернуть эти строки, просто верните эти строки!

Вот что я бы сделал:

char* f(int i) {
        char buffer[20];
        switch ( i ) {
                case 1: return "string1";
                case 2: return "string2";
                case 3: return "string3";
                default: return "defaultstring";
        }
        return buffer;
}
1 голос
/ 07 апреля 2010

Вы возвращаете локальную переменную, которая может закончиться только слезами.

1 голос
/ 07 апреля 2010

Проблема именно в том, что она говорит вам. В самом начале у вас есть:

char* f(int i) {
        int i; 

Вторая строка определяет переменную с именем i, которая "скрывает" (скрывает) i, который был передан в качестве параметра. Когда вы делаете switch для значения i, вы делаете это для (неинициализированного) значения локальной переменной вместо полученного вами параметра.

Вы также определили buffer локально для f, поэтому возвращение является проблемой - к моменту возврата оно больше не существует. Учитывая то, что вы помещаете в него любой из нескольких строковых литералов, вам лучше будет возвращать строковые литералы напрямую:

char const *f(int i) { 
    switch (i) { 
        case 1: return "string 1";
        case 2: return "string 2";
        case 3: return "string 3";
        default: return "default string";
    }
}

В качестве альтернативы, вы можете использовать массив строк:

char const *f(int i) { 
    char *strings[] = {"", "string 1", "string 2", "string 3"};
    if (i>0 && i<3) 
        return strings[i];
    return "default string";
}
1 голос
/ 07 апреля 2010

Затеняет параметр.Я - аргумент функции, затем объявляется внутри функции.Кроме того, вы не можете объявить массив в стеке (char buffer [20]), а затем вернуть его.Он (буфер) выходит из области видимости, как только выходит из функции.

1 голос
/ 07 апреля 2010

Вы объявляете локальную переменную i, которая скрывает параметр i для функции.

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