在这个问题,有人建议意见,我应该不会投的结果malloc,即
int *sieve = malloc(sizeof(int) * length);
Run Code Online (Sandbox Code Playgroud)
而不是:
int *sieve = (int *) malloc(sizeof(int) * length);
Run Code Online (Sandbox Code Playgroud)
为什么会这样呢?
今天我到了The C Programming Language(第二版Brian W. Kernighan和Dennis M. Ritchie)的第167页,发现作者说我必须演员.这是本书的一部分:malloc
7.8.5存储管理
函数malloc和calloc动态获取内存块.
Run Code Online (Sandbox Code Playgroud)void *malloc(size_t n)返回指向未初始化存储的n个字节的指针,如果无法满足请求,则返回NULL.
Run Code Online (Sandbox Code Playgroud)void *calloc(size_t n, size_t size)为具有指定大小的n个对象的数组返回指向足够可用空间的指针,如果无法满足请求,则返回NULL.存储初始化为零.malloc或calloc返回的指针对于有问题的对象具有正确的对齐方式,但必须将其强制转换为适当的类型,如
Run Code Online (Sandbox Code Playgroud)int *ip; ip = (int *) calloc(n, sizeof(int));
我已经知道malloc(和它的族)返回类型void*,并且有很好的解释为什么不进行转换malloc.
但我的问题是:为什么这本书说我应该施展它?
我有一个C代码,它创建一个char指针数组,如下所示:
char* arr[100];
Run Code Online (Sandbox Code Playgroud)
我使用此数组中的每个元素指向一个由另一个函数计算的字符串.所以基本上arr [0]会指向string1,arr [1]指向string2等.
这很好用.但是,现在要求用户指定字符串数作为参数,以使其更加灵活.
如何在对代码进行最小更改的情况下执行此操作?我知道我需要使用malloc.但是我在之前的所有赋值语句中都收到了很多警告.我更改了数组的声明如下:
char* arr = (char*)malloc(n * sizeof(char*)); //where n is provided by user
Run Code Online (Sandbox Code Playgroud)
我以为我只需要改变声明.现在所有的赋值语句都给出了警告("赋值使得没有强制转换的指针产生整数").以下是赋值语句的示例:
arr[i] = str; //where str is defined as char* and is calculated by another function
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么吗?
换句话说,我可以将void*指针重新解释(而不是转换!)作为某种结构类型的void*指针(假设该指针确实包含正确转换的有效结构地址)
实际上,在以下情况下我很有趣:
typedef struct void_struct void_struct_t;
typedef somestruct
{
int member;
// ... other members ...
}somestruct_t;
union
{
void* pv;
void_struct_t* pvs;
somestruct_t* ps;
}u;
somestruct_t s={};
u.pv= &s;
u.ps->member=1; // (Case 1) Ok? unspecified? UB?
u.pvs=(void_struct_t*)&s;
u.ps->member=1; // (Case 2) )Ok?
Run Code Online (Sandbox Code Playgroud)
我在C11标准中发现的情况1相当令人失望:
§6.2.5
28指向void的指针应具有与>指向字符类型的指针相同的表示和对齐要求。相似地,指向兼容类型的合格或不合格版本的指针应具有相同的表示和对齐要求。所有指向结构类型的指针应具有相同的表示和对齐要求。所有指向联合类型的指针应具有相同的表示和对齐要求。指向其他类型的指针不必具有相同的表示或对齐要求。
不过,情况2似乎有效,但我不确定100%...
这个问题主要是面向C的,但是我对C ++也很感兴趣(我希望代码在由C ++编译器编译时将是有效的)。老实说,我在C ++ 11标准中发现的更少,所以即使情况2对我来说也值得怀疑...但是,可能是我遗漏了一些东西。
[编辑]这个问题背后的真正问题是什么?
我有一组(可能很大)定义为结构的类型。对于每种类型,我需要定义一个伴随类型:
typedef struct companion_for_sometype
{
sometype* p_object;
// there are also other members
}companion_for_sometype;
Run Code Online (Sandbox Code Playgroud)
显然,伴随类型将是C ++中的模板,但是我需要C的解决方案(更确切地说,是“干净的C”,即C89和C ++的交集,因为我希望我的代码也是有效的C ++代码)。
幸运的是,即使在C语言中也不是问题,因为我可以定义一个宏
DECLARE_COMPANION(type_name) typedef struct companion_for_##type_name …Run Code Online (Sandbox Code Playgroud)