2012-06-20 3 views
-2

Если я хочу, чтобы вернуть пустой char*, я могу это сделатьВозвращает пустой массив полукокса *

char* Fun1(void) { 
return ""; 
} 

Теперь представьте себе такую ​​же проблему с char**, я хочу, чтобы вернуть пустой массив char*.

Есть ли более короткий способ написать это без использования временной переменной?

char** Fun2(void) { 
char* temp[1] = {""}; 
return temp; 
// return {""}; // syntax error ! 
} 

Цель состоит в том, чтобы скрыть тот факт, что строка может представлять собой NULL указатель.

+1

Ваш 'Func2' приведет к непредсказуемому поведению, как вы вернуть указатель на локальная переменная, которая недействительна после возвращения функций. –

+1

Помимо того факта, что вы возвращаете указатель на локальную переменную, которая недопустима, массив, который вы пытаетесь вернуть, фактически не пуст (он содержит пустую строку). Я не понимаю, что вы здесь делаете. – interjay

+0

Вы говорите: «Я хочу вернуть пустой массив», но ваш код на самом деле возвращает (не указатель на) непустой массив с 1 элементом, который является пустой строкой. Я думаю, сначала вам нужно решить, что для вас означает «пустой». Как только вы это сделаете, вы можете внести изменения в другое место в коде, которые делают этот вопрос неуместным. –

ответ

1

Не используйте временную переменную, так как она будет недоступна при возврате. Если у вас есть несколько функций, которые возвращают один и тот же пустой массив, они могут возвращать указатели в один и тот же «пустой массив».

char* EmptyArray[1] = {""}; 

char** Fun2(void) 
{ 
    return EmptyArray; 
} 

Кроме того, это позволяет легко обнаружить, если функция специально вернулась пустота, сопоставляя указатели: -

char **arr = Fun2(); 

if (arr == EmptyArray) 
    ... 
0

Не можете ли вы просто вернуть null, потому что null - пустой указатель?

+0

У меня есть другие части кода, которые используют Fun1 и Fun2, и которые не ведут себя хорошо с NULL значением. Поэтому я хотел бы скрыть эту обработку ошибок внутри Fun1 и Fun2. –

0

{""} только может использоваться для ввода переменной в ее определении. но не как выражение, то есть, вы не можете использовать его как

char* temp[1]; 
temp = {""}; // invalid 
1

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

Имея это в виду, вы хотите выделить 2 бита памяти: один для указателя на символ, а другой для самого символа.

char** p = malloc(sizeof(*p)); 
*p = malloc(sizeof(**p)); 
**p = '\0'; 
return p; 

И тогда помните, пользователь затем должен сделать:

free(*p); 
free(p); 

Но скажу еще раз, что вы делаете, это не хорошо программирования. Вам лучше писать функции, которые принимают нулевой указатель.

+0

Тогда, например, каждый раз, когда я печатаю что-то, мне нужно было бы проверить, является ли это NULL? –

+0

Возвращающиеся указатели на вещи, которые не были 'malloc''d (и не обязательно должны быть), являются идиоматическим программированием на языке C. Подумайте о функциях строк C - 'strchr',' strcpy' и т. Д. ... и т. Д. ... – Roddy

+0

@John: Mat указывает, что 'char **' имеет значение null. Почему вы передаете 'char **' для printf, и почему это имеет значение, если оно имеет значение null, когда вы это делаете? –

2

эквивалент того, что вы сделали с строкового литерала было бы что-то вроде этого:

char const* const* Fun2(void) { 
    static char const* const tmp[] = {""}; 
    return tmp; 
} 

Но, как я сказал в комментарии к этому вопросу, возможно, потребуется повторно думать, что «пустые» означает ,

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

+0

Это кажется слишком сложным для того, что я хочу сделать + он использует временную переменную. Я хотел бы сделать это в одной строке. –

+0

Я думаю, вы недооценили, насколько сложное управление памятью находится в C. В любом случае разница между строками и массивами в C заключается в том, что строковые литералы сохраняются до тех пор, пока выполняется программа, тогда как литералы массива C99 продолжаются до тех пор, пока выражение 're used in, поэтому они не подходят для возврата из функции (и C89 вообще не имеет литералов массива). Я не думаю, что то, что вы хотите, возможно. –

+0

@JohnPoe, почему это важно, сколько линий вы используете? Вы используете неправильный язык, если хотите использовать однострочные решения. – Matt

0

Первый случай прекрасен, строковый литерал, такой как "", безопасен для возврата из функции. Во втором случае, когда вам нужен массив длиной 1, которая содержит указатель на пустую строку, вы могли бы сделать некоторые хитрости:

char ** array_empty_if_null(const char **array) 
{ 
    static char *empty[] = { "" }; 

    return (array == NULL || array[0] == NULL) ? empty : array; 
} 

Я думаю, что это соответствует вашему описанию, что вам нужно.

Смежные вопросы