const void *和之间有什么区别void *?在什么情况下可以将void指针强制转换为const void指针?
Jon*_*ler 31
一个const void *指向的内存不应该被修改.
A void *(非常量)指向可以修改的内存(但不是通过void *;你必须先抛出它).
使用时memmove(),源地址将强制转换为const void *:
void *memmove(void *dst, const void *src, size_t nbytes);
Run Code Online (Sandbox Code Playgroud)
这是一个插图,可以将void指针强制转换为常量void指针.基本上,当您知道不打算修改指针所指向的内存时,您可以随时执行此操作(转换为常量).这适用于任何指针 - 而不仅仅是void指针.
转换另一种方式(从常量指针转换为非常量指针)是一项更危险的练习.无法保证指向的内存实际上是可修改的; 例如,字符串文字可以存储在只读(常量)内存中,如果你失去了使用强制转换的常量并尝试修改字符串,你可能会遇到分段错误或等效错误 - 你的程序会突然停止而不是在你的控制之下.这不是一件好事.所以,不要将指针从常量更改为非常量而不确定它实际上可以骗你的编译器.请注意编译器不喜欢被骗,并且可以自己回来,通常是在最不方便的时刻(例如在向老板面前的重要潜在客户展示您的程序,老板的老板和老板老板的老板) ).
将a转换void *为a 是完全合理的const void *,编译器应该在幕后隐式地这样做,而不需要你的任何想法,但反过来是危险的,必须避免.
请记住,如果函数使用const指针,那么您可以自由地将其传递给const非const值或非值.说你拿const指针只是你声明你的功能不会修改内存.
示例:(请注意,标记为DANGER的行应该抛出编译器错误)
const void *p_const;
void *p_buffer;
// const pointers are allowed to hold static memory
p_const = "Foo"; // allowed
p_buffer = "Foo"; // DANGER!!!
// casting to const is implicit
p_const = malloc(LEN); // allowed - implicit cast
p_buffer = malloc(LEN); // allowed
// casting to const implicit again
write(STDOUT, p_const, LEN); // allowed
write(STDOUT, p_buffer, LEN); // also allowed - implicit cast
// const memory cannot be used where mutable memory is expected
read(0, p_buffer, LEN); // allowed
read(0, p_const, LEN); // DANGER!!
// To make the above more obivous, we'll skip the intermediate variable
// and place instead what it holds
read(0, malloc(LEN), LEN); // allowed - useless but at least no crashes
read(0, "foo", 4); // DANGER!!!
Run Code Online (Sandbox Code Playgroud)
作为一般规则,如果您编写的函数接收指向您不会修改的值的指针,则函数签名应使用const指针.使用未声明的指针const意味着允许修改您指向的内存.
另一个例子:
void do_something(const void* ptr, int length);
// Since the signature is a const pointer, I know I can call it like this:
do_something("foo",4);
Run Code Online (Sandbox Code Playgroud)
相反,函数调用非常量指针,然后我必须允许它:
void do_something(void* ptr, int length);
// This tells me that the function may overwrite my value.
// The safe solution therefore looks more like this:
char *myptr = char[4];
memcpy(myptr,"foo",4);
do_something(myptr,4);
Run Code Online (Sandbox Code Playgroud)
类似地,如果您发现自己处于需要将const指针强制转换为非指针的情况const,则应将指向值复制到内存的可变部分,并将副本传递给函数而不是原始函数.如果这听起来很头疼,那是因为它是.如果你发现自己处于那种情况,那么你可能做错了什么.
从概念上讲,如果变量保持"值",那么它很可能是一个const指针.如果它拥有一个"缓冲区",那么它就是一个非const指针.
除非您打算写入该内存,否则应始终声明函数签名中的指针const.遵循该规则将帮助您避免程序逻辑中的灾难性问题.
在我编程6年之前,我并不理解这个简单的规则.