What's the difference between const void *
and void *
? Under what circumstances can a void pointer be cast to a const void
pointer?
const void *和void *之间的区别是什么?在什么情况下,空指针可以被强制转换为空指针?
2 个解决方案
#1
30
A const void *
points to memory that should not be modified.
const void *指向不应该修改的内存。
A void *
(non-const) points to memory that could be modified (but not via the void *
; you'd have to cast it first).
void *(非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).
转换另一种方法(从常量指针到非常量指针)是一种非常危险的操作。不能保证指向的内存是可修改的;例如,字符串文字可以存储在只读(常量)内存中,如果您失去了cast的一致性,并尝试修改字符串,您可能会得到一个分割错误或它的对等错误——您的程序将突然停止,而不在您的控制之下。这不是一件好事。所以,不要将指针从常量更改为非常量,而要非常确定向编译器撒谎是可以的。要注意,编译器不喜欢被骗,通常在最不方便的时候(比如在你的老板、老板的老板的老板、老板的老板的老板的老板面前向一个重要的潜在客户演示你的程序时),编译器可以得到自己的支持。
#2
7
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.
将一个void *转换为const void *是完全合理的,编译器应该在后台隐式地这样做,而不需要考虑您的部分,但是另一种方法是危险的,必须避免。
Remember, if a function takes a const
pointer, then you're free to pass to it either a const
or a non-const
value. Saying you take a const
pointer 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 DANGER should throw a compiler error)
示例:(注意,标记为危险的行应该抛出编译器错误)
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 const
pointer. Using a pointer that isn't declared const
means 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 const
pointer to a non-const
one, 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指针的情况下,您应该将point -to值复制到内存的可变部分,并将副本传递给函数,而不是原始的。如果这听起来像头痛,那是因为它是。如果你发现自己处于那种情况,那么你可能做错了什么。
Conceptually, if the variable holds a "value", then it's likely a const
pointer. If, instead it holds a "buffer", then it's a non-const
pointer.
从概念上讲,如果变量持有一个“值”,那么它很可能是一个const指针。如果它持有一个“缓冲区”,那么它就是一个非常量指针。
Pointers in you function signatures should always be declared const
unless 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年后才理解这个简单的规则。
#1
30
A const void *
points to memory that should not be modified.
const void *指向不应该修改的内存。
A void *
(non-const) points to memory that could be modified (but not via the void *
; you'd have to cast it first).
void *(非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).
转换另一种方法(从常量指针到非常量指针)是一种非常危险的操作。不能保证指向的内存是可修改的;例如,字符串文字可以存储在只读(常量)内存中,如果您失去了cast的一致性,并尝试修改字符串,您可能会得到一个分割错误或它的对等错误——您的程序将突然停止,而不在您的控制之下。这不是一件好事。所以,不要将指针从常量更改为非常量,而要非常确定向编译器撒谎是可以的。要注意,编译器不喜欢被骗,通常在最不方便的时候(比如在你的老板、老板的老板的老板、老板的老板的老板的老板面前向一个重要的潜在客户演示你的程序时),编译器可以得到自己的支持。
#2
7
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.
将一个void *转换为const void *是完全合理的,编译器应该在后台隐式地这样做,而不需要考虑您的部分,但是另一种方法是危险的,必须避免。
Remember, if a function takes a const
pointer, then you're free to pass to it either a const
or a non-const
value. Saying you take a const
pointer 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 DANGER should throw a compiler error)
示例:(注意,标记为危险的行应该抛出编译器错误)
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 const
pointer. Using a pointer that isn't declared const
means 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 const
pointer to a non-const
one, 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指针的情况下,您应该将point -to值复制到内存的可变部分,并将副本传递给函数,而不是原始的。如果这听起来像头痛,那是因为它是。如果你发现自己处于那种情况,那么你可能做错了什么。
Conceptually, if the variable holds a "value", then it's likely a const
pointer. If, instead it holds a "buffer", then it's a non-const
pointer.
从概念上讲,如果变量持有一个“值”,那么它很可能是一个const指针。如果它持有一个“缓冲区”,那么它就是一个非常量指针。
Pointers in you function signatures should always be declared const
unless 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年后才理解这个简单的规则。