C语言 C 问题:(const void *) vs (void *)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5547131/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 08:16:16  来源:igfitidea点击:

C Question: (const void *) vs (void *)

cpointersconst

提问by snkherv

What's the difference between const void *and void *? Under what circumstances can a void pointer be cast to a const voidpointer?

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

回答by Jonathan Leffler

A const void *points to memory that should not be modified.

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

A void *(non-const) points to memory that could be modified (but not via the void *; you'd have to cast it first).

A void *(non-const) 指向可以修改的内存(但不能通过void *; 你必须先投射它)。

When you use memmove(), the source address is cast to const void *:

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

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

That is an illustration when a void pointer can be cast to a constant void pointer. Basically, you can do it (convert to constant) at any time when you know you are not going to modify the memory that the pointer points at. This applies to any pointer - not just void pointers.

这就是一个空指针可以被转换为一个常量空指针的例子。基本上,当您知道不会修改指针指向的内存时,您可以随时执行此操作(转换为常量)。这适用于任何指针——不仅仅是空指针。

Converting the other way (from a constant pointer to a non-constant pointer) is a much more dangerous exercise. There's no guarantee that the memory pointed at actually is modifiable; for example, a string literal can be stored in readonly (constant) memory, and if you lose the const-ness with a cast and try to modify the string, you will likely get a segmentation fault or its equivalent - your program will stop suddenly and not under your control. This is not a good thing. So, do not change pointers from constant to non-constant without being very sure it is actually OK to lie to your compiler. Be aware that compilers do not like being lied to and can get their own back, usually at the most inconvenient moment (such as when demonstrating your program to an important prospective client in front of your boss, your boss's boss, and your boss's boss's boss).

转换另一种方式(从常量指针到非常量指针)是一个更危险的练习。不能保证所指向的内存实际上是可修改的;例如,字符串文字可以存储在只读(常量)内存中,如果您通过强制转换失去了常量性并尝试修改字符串,您可能会遇到分段错误或类似错误 - 您的程序将突然停止而不是在你的控制之下。这不是一件好事。因此,在不确定是否真的可以向编译器撒谎的情况下,不要将指针从常量更改为非常量。请注意,编译器不喜欢被骗,而且通常在最不方便的时候(例如在你的老板面前向重要的潜在客户展示你的程序时,你老板的老板,

回答by tylerl

It's perfectly reasonable to cast a void *to a const void *and the compiler should do so implicitly behind the scenes without any thought on your part, but the other way around is dangerous and must be avoided.

将 a 强制转换void *为 a是完全合理的const void *,编译器应该在幕后隐式地这样做,而您没有任何考虑,但反过来是危险的,必须避免。

Remember, if a function takes a constpointer, then you're free to pass to it either a constor a non-constvalue. Saying you take a constpointer is just you declaring that the memory won't be modified by your function.

记住,如果一个函数接受一个const指针,那么你可以自由地传递给它一个const或一个非const值。说你使用一个const指针只是你声明内存不会被你的函数修改。

An example: (note that the lines marked DANGERshould throw a compiler error)

一个例子:(注意标记为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!!!

As a general rule, if a function you write takes in a pointer to a value that you're not going to modify, then the function signature should use a constpointer. Using a pointer that isn't declared constmeans that the memory you're pointing to is allowed to be modified.

作为一般规则,如果您编写的函数接受一个指向您不会修改的值的指针,则函数签名应使用const指针。使用未声明的指针const意味着允许修改您指向的内存。

Another example:

另一个例子:

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

Conversely, function calls for a non-constant pointer, then I have to allow for it:

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

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

Similarly, if you ever find yourself in a situation where you need to cast a constpointer to a non-constone, you should duplicate pointed-to value to a mutable part of memory, and pass your duplicate to the function rather than the original. If that sounds like a headache, that's because it is. If you find yourself in that situation, then you've probably done something wrong.

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

Conceptually, if the variable holds a "value", then it's likely a constpointer. If, instead it holds a "buffer", then it's a non-constpointer.

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

Pointers in you function signatures should alwaysbe declared constunless you intend to write to that memory. Following that rule will help you avoid disastrous problems in your program's logic.

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

I didn't understand this simple rule until I had been programming for 6 years.

直到我编程 6 年,我才明白这个简单的规则。