В ответ на ваш вопрос о том, является ли объект, передаваемый в функцию, массивом или указателем, соответствующая часть стандарта C99 (6.3.2.1/3) гласит:
За исключением случаев, когда это операнд оператора sizeof или унарный оператор &, или строковый литерал, используемый для инициализации массива, выражение с типом '' массив типа '' преобразуется в выражение с типом ' указатель на тип, который указывает на начальный элемент объекта массива и не является lvalue.
Так что да, кроме введения другой явной переменной, следующие две строки эквивалентны:
char x[] = "abc"; fn (x);
char x[] = "abc"; char *px = &(x[0]); fn (px);
Что касается критики, я хотел бы поднять следующее.
Хотя это и законно, я считаю неуместным иметь прототипы функций (например, stringreverse
) где-либо, кроме уровня файлов. На самом деле, я склоняюсь к тому, чтобы упорядочить свои функции так, чтобы они обычно не были необходимы, что делает на одно место меньше места, где вы должны его изменить, если необходимо изменить аргументы или тип возвращаемого значения. Это влечет за собой, в данном случае, размещение stringreverse
перед main
.
Не никогда не использовать gets
в реальной программе. Он не защищен от переполнения буфера. Как минимум, используйте fgets
, который можно защитить, или используйте подходящую функцию ввода, такую как найденная здесь .
Вы не можете создать локальную переменную в stringreverse
и передать ее адрес. Это неопределенное поведение. Как только эта функция возвращается, эта переменная исчезает , и вы, скорее всего, указываете на то, что произойдет, чтобы заменить ее в стеке при следующем вызове функции.
Также нет необходимости передавать переменную revstr
. Если бы это был указатель с резервной памятью (т. Е. Для него было выделено место), это было бы хорошо, но тогда не было бы необходимости возвращать его. В этом случае вы должны выделить оба в вызывающей стороне:
char tempstr[1024];
char revstr[1024];
stringreverse (tempstr, revstr); // Note no return value needed
// since you're manipulating revstr directly.
Вам также следует избегать магических чисел, таких как 1024
. Лучше иметь такие строки, как:
#define BUFFSZ 1024
char tempstr[BUFFSZ];
, поэтому вам нужно изменить его только в одном месте, если вам когда-либо понадобится новое значение (это становится особенно важным, если у вас много 1024
чисел с различными значениями - глобальный поиск и замена будь вашим врагом в этом случае, а не вашим другом).
Чтобы сделать вашу функцию более адаптируемой, вы можете рассмотреть возможность использования любой длины. Вы можете сделать это, передав оба буфера или используя malloc
для динамического выделения буфера для вас, что-то вроде:
char *reversestring (char *src) {
char *dst = malloc (strlen (src) + 1);
if (dst != NULL) {
// copy characters in reverse order.
}
return dst;
}
Это возлагает ответственность за освобождение памяти на вызывающего, но это изношенный способ делать вещи.
Вам, вероятно, следует использовать одну из двух канонических форм для main
:
int main (int argc, char *argv[]);
int main (void);
Также особенно плохая идея - звонить main
из куда-либо. Хотя это может выглядеть как изящный способ получить бесконечный цикл, почти наверняка это закончится жеванием до стека пространства: -)
В общем, это, вероятно, функция, которую я бы изначально написал. Он позволяет пользователю заполнить свой собственный буфер, если он хочет, или указать, что у него его нет, и в этом случае для него будет создан один:
char *revstr (char *src, char *dst) {
// Cache size in case compiler not smart enough to do so.
// Then create destination buffer if none provided.
size_t sz = strlen (src);
if (dst == NULL) dst = malloc (sz + 1);
// Assuming buffer available, copy string.
if (dst != NULL) {
// Run dst end to start, null terminator first.
dst += sz; *dst = '\0';
// Copy character by character until null terminator in src.
// We end up with dst set to original correct value.
while (*src != '\0')
*--dst = *src++;
}
// Return reversed string (possibly NULL if malloc failed).
return dst;
}