C 更改指针指向的字符串
c中的许多函数都将指向常量字符串/字符的指针作为参数,例如C 更改指针指向的字符串,c,pointers,C,Pointers,c中的许多函数都将指向常量字符串/字符的指针作为参数,例如void foo(const char*ptr)。但是,我希望更改它所指向的字符串(ptr)。如何在c中执行此操作请不要执行此操作,因为它将导致代码的行为不可预测。基本上,const char*所指向的字符串可能存储在程序数据的只读部分,如果您试图在其中写入内容,则会发生不好的事情。请记住,foo可以称为foo(“Test”),这里您自己没有为“Test”分配内存,您只有一个指向包含字符串的内存的指针。此内存可能是只读的。不要这样做,因为
void foo(const char*ptr)
。但是,我希望更改它所指向的字符串(ptr
)。如何在c中执行此操作请不要执行此操作,因为它将导致代码的行为不可预测。基本上,const char*所指向的字符串可能存储在程序数据的只读部分,如果您试图在其中写入内容,则会发生不好的事情。请记住,foo可以称为foo(“Test”)
,这里您自己没有为“Test”分配内存,您只有一个指向包含字符串的内存的指针。此内存可能是只读的。不要这样做,因为它会导致代码的行为不可预测。基本上,const char*所指向的字符串可能存储在程序数据的只读部分,如果您试图在其中写入内容,则会发生不好的事情。请记住,foo可以称为foo(“Test”)
,这里您自己没有为“Test”分配内存,您只有一个指向包含字符串的内存的指针。此内存可能是只读的。您可以将其复制到另一块内存中,然后在那里进行修改
如果您将其强制转换为非常量,然后进行修改,很有可能您只会执行segfault。您可以将其复制到另一块内存中,并在那里进行修改 如果您将其强制转换为非常量,然后进行修改,很有可能您只会执行segfault。通过符号“const char*ptr”,我们告诉编译器 ptr包含的内容不应更改 只是,我们不能改变它 通过符号“const char*ptr”,我们告诉编译器 ptr包含的内容不应更改
只是,我们不能改变它 您可以扔掉
常量
:
void evil_function(const char *ptr)
{
char *modifiable = (char *) ptr;
*modifiable = 'f';
}
注意这是危险的,考虑传递给函数的数据真的不能被改变的情况。例如,
evil_函数(“bar”)代码>可能会崩溃,因为字符串文本通常被放在只读内存中。您只需丢弃常量即可:
void evil_function(const char *ptr)
{
char *modifiable = (char *) ptr;
*modifiable = 'f';
}
注意这是危险的,考虑传递给函数的数据真的不能被改变的情况。例如,
evil_函数(“bar”)
可能会崩溃,因为字符串文本通常被放在只读内存中。常量之所以如此表示,是因为此函数不能修改底层内容,所以不要更改它,因为这很可能会破坏依赖常量的某些代码。除此之外,您始终可以使用const_cast
或直接投射指针来丢弃常量。常量之所以如此表达,是因为此函数无法修改基础内容,所以不要更改它,因为这很可能会破坏依赖常量的某些代码。除此之外,您始终可以使用const_cast
或直接使用指针将constness丢弃
void foo(const char *x);
char data[4] = "Hi!";
int sum = 0;
for (int k=0; k<strlen(data); k++) {
foo(data); /* foo first */
sum += data[k];
}
printf("%d\n", sum);
但是,如果foo()
更改data
数组中的值,结果将根据编译器选择的循环编码顺序而有所不同
简而言之:不要对你的编译器撒谎
如何向编译器撒谎
扔掉常量
void foo(const char *readonly) {
char *writable = (char *)readonly;
/* now lie to the compiler all you like */
}
但是,如果foo()
更改data
数组中的值,结果将根据编译器选择的循环编码顺序而有所不同
简而言之:不要对你的编译器撒谎
如何向编译器撒谎
扔掉常量
void foo(const char *readonly) {
char *writable = (char *)readonly;
/* now lie to the compiler all you like */
}
如果您这样做:
void dont_do_this_at_home(const char *ptr)
{
char **steve-o_ptr = (char **) &ptr;
char *bam_margera = "viva la bam";
*steve-o_ptr = bam_margera;
}
然后,您发送到函数中的指针将被更改,尽管它是常量指针,到目前为止的其他建议只允许您更改字符串的内容,而不允许更改指向字符串的指针
我同意其他人的观点,你永远不应该“unconst”你得到的任何参数,因为被调用方可能真的依赖于函数没有关于这些参数的副作用
还有一种方法可以消除警告/错误
typedef struct {
union {
const void* the_const;
void* the_no_const;
} unconsting;
}unconst_t;
/* Here be dragons */
void* unconst_pointer(const void* ptr) {
unconst_t unconst.unconsting.the_const = ptr;
return unconst.unconsting.the_no_const;
}
正如您所看到的,实际上这样做是非常可能和流行的,但您必须知道自己在做什么,否则可能会出现神秘的故障。如果您这样做:
void dont_do_this_at_home(const char *ptr)
{
char **steve-o_ptr = (char **) &ptr;
char *bam_margera = "viva la bam";
*steve-o_ptr = bam_margera;
}
然后,您发送到函数中的指针将被更改,尽管它是常量指针,到目前为止的其他建议只允许您更改字符串的内容,而不允许更改指向字符串的指针
我同意其他人的观点,你永远不应该“unconst”你得到的任何参数,因为被调用方可能真的依赖于函数没有关于这些参数的副作用
还有一种方法可以消除警告/错误
typedef struct {
union {
const void* the_const;
void* the_no_const;
} unconsting;
}unconst_t;
/* Here be dragons */
void* unconst_pointer(const void* ptr) {
unconst_t unconst.unconsting.the_const = ptr;
return unconst.unconsting.the_no_const;
}
正如你所看到的,实际上这样做是很有可能的,也是很流行的,但是你必须知道你在做什么,否则可能会出现神秘的错误。他确实说过“或通过直接投射指针”,这在CHe中是可以的,他说“或通过直接投射指针”,这在Cthanks中没有问题实际上我想在函数中添加它作为一个例外情况进一步函数总是被传递一个指针而不是字符串(例如“邪恶”)谢谢实际上我想在函数中添加它作为一个例外情况进一步函数总是被传递一个指针而不是字符串(例如“邪恶”)