如何将const char *存储到char *?

时间:2016-04-22 08:59:31

标签: c++ char const type-conversion

this code按预期工作:

#define MAX_PARAM_NAME_LEN 32

const char* GetName()
{
    return "Test text";
}

int main()
{
    char name[MAX_PARAM_NAME_LEN];
    strcpy(name, GetName());    

    cout << "result: " << name << endl;
}

如果我想将结果存储到char *(因为框架内的某些功能我只使用char *作为输入),而不使用strcpy(对于代码的实用性和可读性,以及学习),我该怎么办?保持const,这很有效:

const char* name;
name = GetName();

但我还有const

尝试使用char*

char* name;
name = GetName();

我得到invalid conversion from 'const char*' to 'char*'。这种转换的最佳习惯是什么?

4 个答案:

答案 0 :(得分:15)

此类转换的最佳习惯是在整个代码中使用std::string。由于您使用的框架以const char*作为输入,因此您始终可以将std::string调用的结果传递给std::string GetName() { return "Test text"; } int main() { std::string name = GetName(); int res = external_framework_function(name.c_str()); cout << "result: " << res << " for " << name << endl; }

const char*

遥远的第二好是在您的代码中使用const char* name = GetName();

const char*

由于您使用的框架需要char* copy(const char* orig) { char *res = new char[strlen(orig)+1]; strcpy(res, orig); return res; } ... char *name = copy(GetName()); ... delete[] name; ,因此您也很满意。

如果需要非const指针,则无法复制字符串。你可以为你做一个功能,但你仍然有责任释放你从中获得的副本:

import base64
from Crypto.Cipher import DES
from passlib.utils.pbkdf2 import pbkdf1

password = 'xxxxxxx'
iterations = 22
salt_bytes = [19,15,78,45,34,90,12,11]

# convert saltBytes to a string
salt_string = ''.join([chr(a) for a in salt_bytes])

# a sample request
raw_data = '''{"something":"to","encrypt":"here"}'''

# from the standard...
padding_value = (8 - (raw_data.__len__() % 8))
padding_data = chr(padding_value) * padding_value
padded_data = raw_data + padding_data

# 22 iterations, 16 is the # of bytes in an md5 digest
pbkres = pbkdf1(password, salt_string, iterations, 16, 'md5')

# split the digest into two 8-byte halves
# this gives the DES secret key and initializing vector
des_key, iv = pbkres[0:8], pbkres[8:16]

# encrypt with DES
cipher = DES.new(des_key, DES.MODE_CBC, iv)
cmsg = cipher.encrypt(padded_data)

# and base64 encode
base64.b64encode(cmsg)

答案 1 :(得分:9)

return "Test text";返回指向只读字符串 literal 的指针。

如果你正在使用一个以char*作为输入的函数,并且你有const char*(例如只读字符串文字),那么你应该提供一个从const char*开始的字符串的深层副本到这些函数。

否则,如果函数尝试修改只读字符串,则会在运行时冒未定义的行为。

你现在拥有的是足够的;假设您无法使用std::string。 (如果您可以使用std::string 所有框架函数都需要const char*输入,那么我建议您重构代码使用std::string,并将该字符串类的c_str()方法的输出传递给框架函数。)

最后,如果你的某些框架函数需要char*,那么你总是可以自己构建一个小的适配器类:

class Adapter
{
public:
    Adapter(const& Adapter) = delete; /*don't try to copy me please*/
    Adapter& operator=(const Adapter& ) = delete; /*don't try to copy me please*/
    Adapter(const char* s) : m_s(::strdup(s))
    {
    }
    ~Adapter() /*free memory on destruction*/
    {
        ::free(m_s); /*use free to release strdup memory*/
    }
    operator char*() /*implicit cast to char* */
    {
        return m_s;
    }
private:
    char* m_s;
};

然后,对于功能void foo(char* c),您可以拨打foo(Adapter("Hello"/*or any const char* */));foo可以随心所欲地使用匿名临时中嵌入的char*!您甚至可以增强此类以将构造函数带到char*,在这种情况下,只会获取指针的浅表副本(并且析构函数不会删除内存)。

答案 2 :(得分:-1)

在C ++中,“放弃#include <cmath> #include <array> using floats = std::array<float, 4>; using floats2 = std::array<floats, 4>; class MATRIX { public: floats2 ele; float rows; float cols; MATRIX Add(MATRIX m); MATRIX Subtract(MATRIX m); MATRIX Multiply(MATRIX m); MATRIX Transpose(); MATRIX Initialize(); }; int main(int argc, char ** argv){ float x_angle = 0, y_angle = 0, z_angle = 0; MATRIX xRotation, yRotation, zRotation; xRotation.ele = { floats{ 1, 0, 0, 0 }, floats{ 0, cosf(x_angle), -sinf(x_angle), 0 }, floats{ 0, sinf(x_angle), cosf(x_angle), 0 }, floats{ 0, 0, 0, 1 } }; } ”的典型方法是使用const

const_cast<>

这当然是不受欢迎的,丑陋的和潜在的危险,因为char *name = const_cast<char*>(GetName()); 真的有可能返回指向不应该被改变的东西的指针,然后你走了并允许自己改变它。在这种情况下,这是一个很难找到错误的好方法。

解决方法是使用GetName()作为临时保留区域;这将意味着复制字符串,但这可能是性能可接受的:

std::string

std::string s(GetName()); char *name = s.c_str(); 超出范围时,如果name未被保留,那么这当然有效。如果是这种情况,那么你将会有某种形式的持久性字符串存储层。

答案 3 :(得分:-2)

你可以明确地施展它。 (char*) getName()。但你可能不应该这样做。因为const位意味着“承诺不改变它”。所以如果我有一个函数void foo(const char* string)我正在说:“给我一个指向字符串的指针。我不会改变它。” 如果你声明一个变量const char* string = "hello";你说,不应该改变这个字符串。因为你做出了这个承诺,编译器知道,并且可以使你的代码更有效率。这就是原因:

const char* a = "hello";
const char* b = "hello";
(a==b); //is probably true

您的编译器知道您不会更改ab,因此它会指向相同的地址,因此它只需存储一个"hello"字符串。如果你现在要改变ab也会改变,这不是你想要的。

长话短说,如果你绝对确定你的调用函数没有改变字符串,你可以明确地转换它。 (或者更好的是,如果它是您的,则将功能更改为(const char*)。) 如果你不确定,你将不得不复制。 (就像你已经在使用strcpy())。