使用强制转换帮助编译器在此代码 sn-p 中找到错误
int** pt;
pt = (int*) malloc(sizeof(int)*10);
例如,错误消息可能看起来像
error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
pt = (int*) malloc(sizeof(int)*10);
^
如果不进行强制转换,编译器可以接受这个明显无效的代码,因为函数malloc 的返回类型是void *,并且void * 类型的指针可以分配给指向任何其他类型对象的指针。
即在赋值的右侧,计算表达式的类型为int *,而在赋值的左侧,有一个int **类型的对象,并且没有从@987654328类型的隐式转换@ 类型为int **。
这段代码sn-p
int** pt;
*pt = (int*) malloc(sizeof(int)*10);
由于其他原因无效。指针pt 未由对象的有效地址初始化。如果指针具有自动存储持续时间,则它具有不确定的值;如果指针具有静态存储持续时间,则它具有 NULL。在任何情况下,它的取消引用都会导致未定义的行为。
这样写就对了
int* pt;
^^^^^^^
pt = (int*) malloc(sizeof(int)*10);
但是这个结构
int** pt;
//...
*pt = (int*) malloc(sizeof(int)*10);
可以在某些情况下有效。
假设你声明了一个指针
int *pt;
并且想在一个函数中初始化它。在这种情况下,您必须通过引用将指针传递给函数。否则,函数将处理指针的副本,在这种情况下,函数中不会分配原始指针。
所以对应的代码sn-p可以看成演示程序中的样子
#include <stdlib.h>
#include <stdio.h>
size_t f( int **pt )
{
const size_t N = 10;
*pt = (int*) malloc( sizeof( int ) * N );
if ( *pt )
{
int value = 0;
for ( size_t i = 0; i < N; i++ ) ( *pt )[i] = value++;
}
return *pt == NULL ? 0 : N;
}
int main( void )
{
int *pt;
size_t n = f( &pt );
if ( n )
{
for ( size_t i = 0; i < n; i++ ) printf( "%d ", pt[i] );
putchar( '\n' );
}
free( pt );
}
程序输出是
0 1 2 3 4 5 6 7 8 9