【发布时间】:2018-07-25 07:53:39
【问题描述】:
根据this answer,不应该删除常量,因为它们可能一开始就没有被分配。但是,在某些情况下,我想保护动态分配的数据。例如,在管理用户会话时†,我想确保像当前用户名这样的数据不会被其他函数意外覆盖,但会话数据在解析时确实是分配的请求。
这是一个代码示例,可以让您更好地了解。不过请记住,事情已经大大简化了。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *request = "www.example.com/index?first-name=SOME&last-name=DUDE";
char *get_username_from_request(const char *req) {
char *first_name = strstr(req, "first-name") + strlen("first-name") + 1;
char *last_name = strstr(req, "last-name") + strlen("last-name") + 1;
char *username = malloc(10);
memcpy(username, first_name, 4);
username[4] = ' ';
memcpy(username + 5, last_name, 4);
/* The returned string is "SOME DUDE" */
return username;
}
int main(void) {
char *username = get_username_from_request(request);
printf("Welcome, %s.\n", username);
free(username);
return 0;
}
我真的想改用const char *username = get_username_from_request(request);,但是当我进行此更改时,Clang 会发出警告:
/Applications/CLion.app/Contents/bin/cmake/bin/cmake --build /Users/nalzok/CLionProjects/zero/cmake-build-debug --target zero -- -j 2
Scanning dependencies of target zero
[ 50%] Building C object CMakeFiles/zero.dir/main.c.o
/Users/nalzok/CLionProjects/zero/main.c:24:10: warning: passing 'const char *' to parameter of type 'void *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]
free(username);
^~~~~~~~
/usr/include/stdlib.h:151:18: note: passing argument to parameter here
void free(void *);
^
1 warning generated.
[100%] Linking C executable zero
[100%] Built target zero
任何想法都值得赞赏。
†:嗯,believe it or not,我正在用 C 编写一个 Web 应用程序。
【问题讨论】:
-
@SanderDeDycker 是的,通过强制转换来抑制警告是显而易见的答案,并且有效。但是,这样做时您必须非常小心,所以我想看看是否有人可以提供更安全的替代方案。例如,也许有一种方法可以“锁定”一些内存,防止后续的写入操作。
-
重复问题中被接受(并且投票最多)的答案并不是唯一的答案 - 它只是社区最支持的答案。其他答案建议不要在这种情况下使用
const,例如。你可以做char* u = malloc(...); const char* cu = u; puts(cu); free(u);- 即。u仅用于取消分配,cu用于其他所有操作。 -
The returned string is "SOME DUDE"并不完全正确。username不一定指向 string,因为username指向的数据肯定不包含 null 字符。 -
@chux 我的错,忘了添加 NUL 终止符。很好的收获。
标签: c pointers memory-management constants qualifiers