简体   繁体   English

更改指针指向的字符串

[英]Change string pointed by pointer

Many functions in c take pointer to constant strings/chars as parameters eg void foo(const char *ptr) . c语言中的许多函数都将指向常量字符串/字符的指针作为参数,例如void foo(const char *ptr) However I wish to change the string pointed by it ( ptr ).how to do it in c 但是我想更改它指向的字符串( ptr )。如何在c中做到这一点

You can just cast away the const : 您可以抛弃const

void evil_function(const char *ptr)
{
  char *modifiable = (char *) ptr;

  *modifiable = 'f';
}

Note that this is dangerous, consider cases where the data being passed to the function really can't be changed. 请注意,这很危险,请考虑确实无法更改传递给函数的数据的情况。 For instance, evil_function("bar"); 例如, evil_function("bar"); might crash since the string literal is often placed in read-only memory. 由于字符串文字常被放置在只读存储器中,因此可能会崩溃。

Don't do it as it will cause your code to behave unpredictably. 不要这样做,因为它将导致您的代码行为异常。 Basically the string pointed by const char* may be stored in the read-only section of your program's data and if you try to write something there, bad things will happen. 基本上,由const char *指向的字符串可以存储在程序数据的只读部分中,如果尝试在其中写入内容,则会发生不良情况。 Remember that foo can be called as foo("Test") , here you have not allocated memory for "Test" yourself, you just have a pointer to memory which contains the string. 记住foo可以称为foo("Test") ,这里您没有为“ Test”分配内存,只是有一个指向包含字符串的内存的指针。 This memory may be read-only. 该内存可能是只读的。

You can copy it to another piece of memory, and modify it there. 您可以将其复制到另一块内存,然后在此处进行修改。

If you cast it to non-const, and then modify, chances are good you'll just segfault. 如果将其强制转换为非const,然后进行修改,则很有可能会出现段错误。

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

Because foo() does not change its argument, the compiler can change this code to 因为foo()不会更改其参数,所以编译器可以将此代码更改为

void foo(const char *x);
char data[4] = "Hi!";
int sum = 0;
for (int k=0; k<strlen(data); k++) {
    sum += data[k];      /* sum first */
    foo(data);
}
printf("%d\n", sum);

But, if foo() changes the values in the data array, the results will be different according to the order the compiler chose to code the loop! 但是,如果foo()更改data数组中的值,则结果将根据编译器选择对循环进行编码的顺序而不同!

In short: don't lie to your compiler 简而言之: 不要对您的编译器撒谎

How to lie to the compiler 如何对编译器撒谎

Cast the const away 抛弃const

void foo(const char *readonly) {
    char *writable = (char *)readonly;
    /* now lie to the compiler all you like */
}

by notation "const char *ptr" we are telling Compiler that ptr contains should not be changed. 通过符号“ const char * ptr”,我们告诉编译器不应更改ptr包含的内容。

Just, we can't change it! 只是,我们无法更改它!

The whole reason the const is so to express that the underlying content is not to be modified by this function, so don't change it because that will most likely break some code which is relying on the constness. const之所以如此表示,是因为它的根本原因是该函数不会修改其基础内容,因此请不要更改它,因为这很可能会破坏某些依赖于constness的代码。 other then that you can always cast the constness away using either const_cast<char*> or by directly casting the pointer 除此之外,您始终可以使用const_cast<char*>或直接强制转换指针来放弃const_cast<char*>

If you do it like this: 如果您这样做:

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

Then the pointer that you send into the function will be changed despite being a const pointer, the other suggestions so far only let you change the contents of the string, not the pointer to the string. 这样,尽管您是const指针,但仍将更改发送到函数中的指针,到目前为止,其他建议只允许您更改字符串的内容,而不是指向字符串的指针。

And I agree with the others that you shouldn't, ever , "un-const" any parameter you get, since the callee may really depend on that there are no side-effects to the function regarding those parameters. 我同意其他人的看法,因为您永远不应该“ u​​n-const”获得的任何参数,因为被调用方可能真的依赖于该函数对这些参数没有副作用。

There is also this way to get rid of the warnings/errors 也有这种方法可以消除警告/错误

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

As you see it is quite possible and popular to actually do this, but you have to know what you are doing or mysterious faults may appear. 如您所见,实际执行此操作很有可能并且很受欢迎,但是您必须知道自己在做什么,否则可能会出现神秘的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM