我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*'
。这种转换的最佳习惯是什么?
答案 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
您的编译器知道您不会更改a
或b
,因此它会指向相同的地址,因此它只需存储一个"hello"
字符串。如果你现在要改变a
,b
也会改变,这不是你想要的。
长话短说,如果你绝对确定你的调用函数没有改变字符串,你可以明确地转换它。 (或者更好的是,如果它是您的,则将功能更改为(const char*)
。)
如果你不确定,你将不得不复制。 (就像你已经在使用strcpy()
)。