Автоматическая передача аргумента по ссылке в C - PullRequest
1 голос
/ 24 сентября 2010

Я пишу библиотеку Unicode для C как личное упражнение. Без фактического кода у меня есть это:

typedef struct string {
    unsigned long length;
    unsigned *data;
} string;

// really simple stuff

string *upush(string *s, unsigned c) { ... }

// UTF-8 conversion

string *ctou(char *old) { ... }

char *utoc(string *old) { ... }

upush помещает полную кодовую точку Unicode c в конец s, перераспределяя при необходимости.

Я могу использовать такой класс, например:

string a;
upush(&a, 0x44);
puts(utoc(&a));

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

string a;
upush(a, 0x44);
puts(utoc(a));

Или , как вы думаете, лучше просто ввести defdef string в качестве struct string указателя, а не самой структуры, и всегда иметь дело с struct string указателями?

Разрешение? Благодаря Dummy00001, теперь это общий профиль моей библиотеки:

typedef struct string {
    unsigned long length;
    unsigned *data;
} string;

// really simple stuff

string *upush(string *s, unsigned c) { ... }

// UTF-8 conversions

string ctou(char *old) { ... }

char *utoc(string old) { ... }

Вот несколько примеров:

string a = ctou("Hello, world");
upush(&a, '!');
puts(utoc(a));

Я также узнаю, благодаря Doches, что в C ++ (для этого я и напишу оболочку для этой библиотеки), вы можете написать прототип следующим образом, чтобы выполнить неявную передачу по ссылке:

string *upush(string &s, unsigned c);

Для тех, кто заинтересован, вот мой текущий прогресс: http://delan.ath.cx/ulib

Ответы [ 3 ]

3 голосов
/ 24 сентября 2010

Вместо того, чтобы использовать & для передачи ссылки на функцию, есть ли способ написать так, чтобы я мог вызвать:
строка а;
упуш (а, 0х44);
ставит (UTOC (а));

Лично я предпочитаю нотацию & и использую ее (даже в C ++) для разграничения между случаем функции, которая может изменить ее аргумент, и случаем функции, обращающейся к структуре как const. IOW:

string a;  
upush(&a, 0x44);  // pass pointer, we modify the "a"
puts(utoc(a));    // pass "a" as a copy, utoc() doesn't modify it

В приведенном выше коде сразу видно, что upush() принимает &a и, таким образом, потенциально модифицирует его. В то время как utoc() принимает a и не изменяет его.

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

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

Сделать символ string указателем на непрозрачную структуру, определенную только внутри самой библиотеки. В общедоступном интерфейсе заголовок:

struct string_s;
typedef struct string_s *string;

во внутреннем заголовке:

struct string_s {
   unsigned long length;
   unsigned *data;
};

Интерфейсные функции могут принимать только string, который является указателем. Предоставить функции для создания новой строки (calloc(1,sizeof(string *))) и ее уничтожения (free()). Таким образом, вы бы предоставили интерфейс для приложения, который был бы непротиворечивым (разработчику не нужно думать о том, что является указателем, а что нет), а также устойчив к внутренним изменениям библиотеки (поскольку структура структуры известна только внутри самой библиотеки).

Недостатком является то, что нужно использовать динамическое управление памятью, чтобы выделить маленькую структуру: malloc() / free() быстрые, но все равно кажутся излишними.

2 голосов
/ 24 сентября 2010

К сожалению, пример, который вы приводите, является правильным способом передачи по ссылке в C. Я думаю, что вам нужно, это запись & для указания, что аргумент должен передаваться по ссылке, а не по значению который является C ++ - ism ( длиннее, лучший пример из IBM ).

В C ++ (не C!) Вы можете написать:

typedef struct _foo_t {
  int value;
} foo;

void modify_foo(foo &f)
{
  f.value = -1;
}

и делайте в точности то, что вы просите, например ::10000

foo aFoo;
aFoo.value = 1;
modify_foo(aFoo);
printf("%d\n",aFoo.value);
1 голос
/ 24 сентября 2010

string a выделяет нужную вам память в текущей области, string *a - это только указатель на память, который вы должны распределить и освободить для себя.

поэтому ответ: зависит.Если вы используете стратегию указателя, вы должны предоставить функции create и destroy и помнить, что пользователи «забывают» использовать эти функции.

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