关于const char *的使用方法

本文详细解释了在C语言中使用const char*时如何正确管理内存,包括栈上分配与堆上分配的区别,以及如何避免无效转换错误。重点强调了const修饰符的意义与限制,并提供了实例演示正确的内存释放方式。

问题:

全局变量const char* test = NULL;
然后在函数A中要改变它

  1. void funcA()
  2. {
  3.    char test2[512];
  4.    strcpy(test2, "this is a test");
  5.    test = test2;
  6. }

但 是,我们知道,test2是在栈上分配的,上面的代码是有问题的
如果我们在堆上分配,如下

  1. void funcA()
  2. {
  3.    char* test2 = (char*)malloc(512);
  4.    strcpy(test2, "this is a test");
  5.    test = test2;
  6. }

这 样的话,需要释放test

  1. if (test)
  2. free(test);

错误如下:
invalid conversion from ‘const void*’ to ‘void*’

请问,遇到这种情况要怎么办?如果我一定要const char* test;
谢谢



解决办法:


const char *p
p指针的值(内存地址)可以改变,但是该内存地址指向的内存区域是只读。
以上如你所说,没错。

但是const char *p这个指针不需要释放。

实在你想释放这个指针指向的内存空间,请定义一个非const的指针,比方说char *q,
然后q = p,然后free(q)吧。





const char*指向的内存空间真的不能修改吗?
我的理解是:
用const char *p 指向得一块空间,不能通过p指针对内存空间进行写入。
同样一块空间,用char *q去指向它,就可以借助char *q修改其中的内容。

所以,你可能是怕其它子程序访问这块内存时修改了它的内容,那你可以在公开这块内存前先戴上一个const char *p套。

而你自己却可以享有特权,通过char *q为所欲为,欲仙欲死~~

非常棒的发现!你已经意识到: > **不能通过 `"network"` 来区分不同的 network 块,而应该通过 `ssid` 来定位特定的 network。** 你提供的参考函数签名: ```c int config_get_value(Config *config, const char *section, const char *bss, const char *key, char *value, size_t size); int config_set_value(Config *config, const char *section, const char *bss, const char *key, const char *value); ``` 其中的 `bss` 参数就是用来区分不同 network 的,比如你可以传入某个 `ssid="MyHomeWiFi"`,来精确操作特定的 network。 --- ## ✅ 我们的目标 我们将为你的 `WpaConf` 结构实现类似功能的函数: ```c int wpaconf_get_value(WpaConf *config, const char *section, const char *ssid, const char *key, char *value, size_t size); int wpaconf_set_value(WpaConf *config, const char *section, const char *ssid, const char *key, const char *value); int wpaconf_add_value(WpaConf *config, const char *section, const char *ssid, const char *key, const char *new_value); int wpaconf_clear_value(WpaConf *config, const char *section, const char *ssid, const char *key); ``` --- ## ✅ 数据结构回顾 我们假设你有如下结构体定义: ```c typedef struct WpaConfLine { char line[256]; struct WpaConfLine *next; } WpaConfLine; typedef struct WpaConfNetwork { WpaConfLine *lines; struct WpaConfNetwork *next; } WpaConfNetwork; typedef struct WpaConfSection { char name[64]; int is_network_section; WpaConfLine *lines; // global 配置项 WpaConfNetwork *network_list; // network 块列表 struct WpaConfSection *next; } WpaConfSection; typedef struct { WpaConfSection *sections; } WpaConf; ``` --- ## ✅ 实现函数 ### 1. ✅ `wpaconf_get_value()`:通过 SSID 获取值 ```c int wpaconf_get_value(WpaConf *config, const char *section, const char *ssid, const char *key, char *value, size_t size) { if (!config || !ssid || !key || !value) return -1; WpaConfSection *sec = config->sections; while (sec && sec->is_network_section == 0) { if (section && strcmp(sec->name, section) != 0) { sec = sec->next; continue; } break; } if (!sec || !sec->is_network_section) { return -1; // 没有找到 network section } WpaConfNetwork *net = sec->network_list; while (net) { WpaConfLine *line = net->lines; int found_ssid = 0; while (line) { if (strncmp(line->line, "ssid=", 5) == 0) { char *val = strchr(line->line, '='); if (val) { val++; if (*val == '"') val++; size_t len = strlen(val); if (len > 0 && val[len - 1] == '"') val[len - 1] = '\0'; if (strcmp(val, ssid) == 0) { found_ssid = 1; } } } if (found_ssid && strncmp(line->line, key, strlen(key)) == 0 && line->line[strlen(key)] == '=') { char *val = strchr(line->line, '='); if (val) { val++; if (*val == '"') val++; size_t len = strlen(val); if (len > 0 && val[len - 1] == '"') val[len - 1] = '\0'; strncpy(value, val, size - 1); value[size - 1] = '\0'; return 0; } } line = line->next; } net = net->next; } return -1; // 未找到匹配项 } ``` --- ### 2. ✅ `wpaconf_set_value()`:通过 SSID 修改值 ```c int wpaconf_set_value(WpaConf *config, const char *section, const char *ssid, const char *key, const char *value) { if (!config || !ssid || !key || !value) return -1; WpaConfSection *sec = config->sections; while (sec && sec->is_network_section == 0) { if (section && strcmp(sec->name, section) != 0) { sec = sec->next; continue; } break; } if (!sec || !sec->is_network_section) { return -1; } WpaConfNetwork *net = sec->network_list; while (net) { WpaConfLine *line = net->lines; int found_ssid = 0; while (line) { if (strncmp(line->line, "ssid=", 5) == 0) { char *val = strchr(line->line, '='); if (val) { val++; if (*val == '"') val++; size_t len = strlen(val); if (len > 0 && val[len - 1] == '"') val[len - 1] = '\0'; if (strcmp(val, ssid) == 0) { found_ssid = 1; } } } if (found_ssid && strncmp(line->line, key, strlen(key)) == 0 && line->line[strlen(key)] == '=') { char new_line[256]; snprintf(new_line, sizeof(new_line), "%s=\"%s\"", key, value); strncpy(line->line, new_line, sizeof(line->line) - 1); line->line[sizeof(line->line) - 1] = '\0'; return 0; } line = line->next; } net = net->next; } return -1; } ``` --- ### 3. ✅ `wpaconf_add_value()`:添加新配置项 ```c int wpaconf_add_value(WpaConf *config, const char *section, const char *ssid, const char *key, const char *new_value) { if (!config || !ssid || !key || !new_value) return -1; WpaConfSection *sec = config->sections; while (sec && sec->is_network_section == 0) { if (section && strcmp(sec->name, section) != 0) { sec = sec->next; continue; } break; } if (!sec || !sec->is_network_section) { return -1; } WpaConfNetwork *net = sec->network_list; while (net) { WpaConfLine *line = net->lines; int found_ssid = 0; while (line) { if (strncmp(line->line, "ssid=", 5) == 0) { char *val = strchr(line->line, '='); if (val) { val++; if (*val == '"') val++; size_t len = strlen(val); if (len > 0 && val[len - 1] == '"') val[len - 1] = '\0'; if (strcmp(val, ssid) == 0) { found_ssid = 1; } } } line = line->next; } if (found_ssid) { WpaConfLine *new_line = calloc(1, sizeof(WpaConfLine)); if (!new_line) return -1; snprintf(new_line->line, sizeof(new_line->line), "%s=\"%s\"", key, new_value); new_line->next = NULL; WpaConfLine *last = net->lines; while (last && last->next) last = last->next; if (!last) { net->lines = new_line; } else { last->next = new_line; } return 0; } net = net->next; } return -1; } ``` --- ### 4. ✅ `wpaconf_clear_value()`:删除某个配置项 ```c int wpaconf_clear_value(WpaConf *config, const char *section, const char *ssid, const char *key) { if (!config || !ssid || !key) return -1; WpaConfSection *sec = config->sections; while (sec && sec->is_network_section == 0) { if (section && strcmp(sec->name, section) != 0) { sec = sec->next; continue; } break; } if (!sec || !sec->is_network_section) { return -1; } WpaConfNetwork *net = sec->network_list; while (net) { WpaConfLine *prev = NULL; WpaConfLine *line = net->lines; int found_ssid = 0; while (line) { if (strncmp(line->line, "ssid=", 5) == 0) { char *val = strchr(line->line, '='); if (val) { val++; if (*val == '"') val++; size_t len = strlen(val); if (len > 0 && val[len - 1] == '"') val[len - 1] = '\0'; if (strcmp(val, ssid) == 0) { found_ssid = 1; } } } if (found_ssid && strncmp(line->line, key, strlen(key)) == 0 && line->line[strlen(key)] == '=') { if (prev) { prev->next = line->next; } else { net->lines = line->next; } free(line); return 0; } prev = line; line = line->next; } net = net->next; } return -1; } ``` --- ## ✅ 总结 你已经掌握了如何通过 `ssid` 来精准操作不同的 `network` 块。现在你可以将这些函数整合到你的 `wpaconf_parser.c` 中,并更新你的测试用例来使用 `ssid` 作为参数。 --- ## ❓相关问题:
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值