У меня есть рабочий пример фрагмента кода C, который я использую, чтобы научить себя эффективно использовать указатели в нетривиальном приложении.(У меня есть мечта добавить недостающую функцию в библиотеку C, на которую я полагаюсь.)
Мой пример кода выглядит следующим образом:
#include <stdio.h>
#include <stdlib.h>
struct config_struct {
int port;
char *hostname;
};
typedef struct config_struct config;
void setup(config*);
void change(config*);
void set_hostname(config*, char*);
void get_hostname_into(config*, char**);
void teardown(config*);
void inspect(config*);
int main() {
char* hostname;
config* c;
c = calloc( 1, sizeof(config));
setup(c);
inspect(c);
change(c);
inspect(c);
set_hostname(c, "test.com");
inspect(c);
get_hostname_into(c, &hostname);
inspect(c);
printf("retrieved hostname is %s (%p)\n", hostname, &hostname);
teardown(c);
printf("retrieved hostname is %s (%p) (after teardown)\n", hostname, &hostname);
return EXIT_SUCCESS;
}
void setup(config* c) {
c->port = 9933;
c->hostname = "localhost";
}
void change(config* c) {
c->port = 12345;
c->hostname = "example.com";
}
void set_hostname(config* c, char* new_hostname) {
c->hostname = new_hostname;
}
void get_hostname_into(config* c, char** where) {
*where = c->hostname;
}
void teardown(config* c) {
free(c);
}
void inspect(config* c) {
printf("c is at %p\n", c);
printf("c is %ld bytes\n", sizeof(*c));
printf("c:port is %d (%p)\n", c->port, &(c->port));
printf("c:hostname is %s (%p)\n", c->hostname, &(c->port));
}
Это требуется по природебиблиотека (функция get_session_property(session*, enum Property, void*)
- таким образом, я ищу способ разыменования пустого указателя; я смог успешно реализовать это для int
, но пытался понять, как это сделатьэто для char*
(что-то от void*
до int
имеет некоторый смысл, но я не могу понять, как это сделать для void* to char*
.
Моя успешная реализация (с тестами) длябиблиотека находится на моей ветке Github проекта, здесь .
Самое близкое, что я пришел, это:
enum Property { Port, Hostname };
void get_property(config*, enum Property, void*);
void get_property(config* c, enum Property p, void* target) {
switch(p) {
case Port:
{
int *port;
port = (int *) target;
*port = c->port;
}
break;
case Hostname:
{
char *hostname;
hostname = (char *) target;
*hostname = c->hostname;
}
break;
}
}
Который, к счастью, не является ошибкой, но такжеоставляет char *get_hostname_into_here
null
, выдавая предупреждение (которое я не могу понять:)
untitled: In function ‘get_property’:
untitled:33: warning: assignment makes integer from pointer without a cast
Полный исходный код моего надуманного примера здесь; пожалуйста, отвечая на объяснение, или порекомендуйте любое чтение, которое у вас естьпри использовании пустых указателей и / или хорошего стиля C, кажется, что каждыйу одного есть другая идея, и несколько человек, которых я знаю в реальном мире, просто сказали: «Библиотека делает это неправильно, не используйте пустые указатели) - хотя было бы хорошо, если бы библиотека делала структуру общедоступной;для инкапсуляции и по другим веским причинам, я думаю, что указатели на пустоту, универсальный подход к функциям вполне разумны в этом случае.
Итак, что я делаю неправильно в моей ветке hostname
get_property()
функция, что char*
равен NULL
после вызова get_property(c, Hostname, &get_hostname_into_here);
char *get_hostname_into_here;
get_property(c, Hostname, &get_hostname_into_here);
printf("genericly retrieved hostname is %s (%p)\n", get_hostname_into_here, &get_hostname_into_here);
// Expect get_hostname_into_here not to be NULL, but it is.
полный исходный код, например (с выводом) .