错误:无法将'unsigned char *'转换为'const int *'

时间:2014-12-01 22:37:39

标签: c++

我正在编写一个函数来接受unsigned char *和int *:

int foo(const int * a)

然而,当我将unsigned char * a传递给foo()时,它有这个编译错误。我以为unsigned char会自动转换为int吗? (较小的范围变量将被铸造成较大的变量)。它也适用于数组指针吗?

示例代码:

#include <iostream>
using namespace std;

int average(const int * array, int size)
{
    int sum = 0;
    for (int i = 0; i <size; i++)
    sum+=*(array+i);
    return sum/size;
}

int main() {
    unsigned char array[5] = {0,1,2,3,4};
    std::cout << average(array, 5);
    return 0;
}

编写接受unsigned char *和int *?

的函数的最佳方法是什么?

3 个答案:

答案 0 :(得分:6)

  

我以为unsigned char会自动转换为int?

unsigned char会自动投放到int,但unsigned char*不会自动投放到int*

 unsigned char c = 'a';
 unsigned char* cp = &a;

 int i = c;      // This is allowed  
 int* ip = cp;   // This is not allowed

如果允许,你可以这样做:

 *ip = INT_MAX;

&c没有足够的空间来容纳这个数字。您将最终访问未经授权的内存,这将立即导致未定义的行为。

答案 1 :(得分:3)

TL;博士

欢迎使用某种类型的安全性。 const intunsigned char是完全不同的类型。两者之间的隐式转换将是类型系统中的一个巨大缺陷。

允许的指针转换

只有3种类型的有效指针转换,在标准的第4.10节中描述:

空指针

从空指针prvalue到指针类型。例如:

const int* ptr = nullptr;

具体而言:

  

空指针常量是值为零的整数文字(2.14.2)或类型为std :: nullptr_t的prvalue。空指针常量可以转换为指针类型;结果是该类型的空指针值,并且可以与对象指针或函数指针类型的每个其他值区分开。这种转换称为空指针转换。相同类型的两个空指针值应相等。将空指针常量转换为指向cv限定类型的指针是单个转换,而不是指针转换的序列,后跟限定转换(4.4)。可以将整数类型的空指针常量转换为std :: nullptr_t类型的prvalue。 [注意:生成的prvalue不是空指针值。 - 结束说明]

void*

的特例

我说“某种类型系统”的原因正是如此。 [const] void* [const]可以表示任何指针类型,只要它是相同的常量限定符:

const int* x = ...;
const void* vx = x; // OK

const int* y = ...;
void* vy = y; // Nope

具体描述如下:

  

类型为“指向cv T的指针”的prvalue,其中T是对象类型,可以转换为类型为“指向cv void的指针”的prvalue。将指针的非空指针值转换为对象类型的结果为“指向cv void的指针”表示内存中与原始指针值相同的字节的地址。空指针值将转换为目标类型的空指针值。

多态指针

最后,我们有多态指针:指向基类的指针:

class B { ... };
class C : public B { ... };
class D : public B { ... };

...

C* c = new C();
D* d = new D();

B* b1 = c; // Yup
B* b2 = d; // Yup

D* dw = b1; // Nope. If you really want this UB you need to use `dynamic_cast`

具体做法是:

  

类型为“指向cv D的指针”的prvalue,其中D是类类型,可以转换为类型为“指向cv B的指针”的prvalue,其中B是D的基类(第10节)。 B是D的不可访问(第11条)或模糊(10.2)基类,需要这种转换的程序是不正确的。转换的结果是指向派生类对象的基类子对象的指针。空指针值将转换为目标类型的空指针值。

答案 2 :(得分:1)

指针的范围相同,因为它们都是指针。问题是它们都可以被[]索引,但是int和char的字节步长是不同的,它们是4和1.

如果要传递一个数组,则必须将字符复制到一个int数组中,这样它们就像内存中的int一样。

void char_array_to_int_array(int *ints, char *chars, int length){
     for(int i=0; i<length; i++){
       ints[i]=chars[i]; //Here the cast will happen
     }
 }

或者,您可以再次为char *定义函数作为参数,以便可以正确计算索引。

实际上我刚刚意识到你的问题是多态,你想要一个像这样的模板函数:

 template <class T>
 int average(T *array, int size){
     int sum = 0;
     for (int i = 0; i <size; i++)
     sum+=*(array+i);
     return sum/size;
 }

这里编译器将为程序中调用它的每个类型编译此函数。我应该尽快意识到实际问题,而不是谈论类型和演员。

这可以像平常一样调用。

char a[4] = {1,2,3,4};
int i[4] = {1,2,3,4};
cout << "The ints: " << average(i,4) << endl;
cout << "The chars: " << average(a,4) << endl;