const char区别




C问题:(const void*)vs(void*) (2)

const void *指向不应修改的内存。

void * (非const)指向可以修改的内存(但不是通过void * ;你必须先抛出它)。

当您使用memmove() ,源地址将转换为const void *

void *memmove(void *dst, const void *src, size_t nbytes);

这是一个插图,可以将void指针强制转换为常量void指针。 基本上,当您知道不打算修改指针指向的内存时,您可以随时执行此操作(转换为常量)。 这适用于任何指针 - 而不仅仅是void指针。

转换另一种方式(从常量指针转换为非常量指针)是一项更危险的练习。 无法保证指向的内存实际上是可修改的; 例如,字符串文字可以存储在只读(常量)内存中,如果你失去了使用强制转换的常量并尝试修改字符串,你可能会遇到分段错误或等效错误 - 你的程序会突然停止而不是在你的控制之下。 这不是一件好事。 所以,不要将指针从常量更改为非常量而不确定它实际上可以骗你的编译器。 请注意编译器不喜欢被欺骗并且可以自己回来,通常是在最不方便的时刻(例如在向老板面前的重要潜在客户展示您的程序,老板的老板和老板老板的老板时) )。

const void *void *之间有什么区别? 在什么情况下可以将void指针强制转换为const void指针?


void *转换为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!!!

作为一般规则,如果您编写的函数接收指向您不会修改的值的指针,则函数签名应使用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);

相反,函数调用非常量指针,然后我必须允许它:

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);

类似地,如果您发现自己处于需要将const指针强制转换为非const ,则应将指向的值复制到内存的可变部分,并将副本传递给函数而不是原始函数。 。 如果这听起来很头疼,那是因为它是。 如果你发现自己处于那种情况,那么你可能做错了什么。

从概念上讲,如果变量包含“值”,那么它很可能是一个const指针。 如果它拥有一个“缓冲区”,那么它就是一个非常量指针。

除非您打算写入该内存,否则您的函数签名中的指针应始终声明为const 。 遵循该规则将帮助您避免程序逻辑中的灾难性问题。

在我编程6年之前,我并不理解这个简单的规则。





const