为什么在为指针指定整数时使用cast更好?

为什么在为指针指定整数时使用cast更好?,c,pointers,casting,C,Pointers,Casting,假设我有以下代码: char *pointer; unsigned int a; pointer = a; 对我来说,这不会产生任何问题,但我会收到以下警告: assignment makes pointer from integer without a cast 为什么使用cast更好? 我用的是32位的机器 编辑: 通过“这不会产生任何问题”,我是说它编译并存储变量a的值 编辑: 变量a将实际存储一个地址 因为在C中: pointer = a; // not valid i

假设我有以下代码:

  char *pointer;
  unsigned int a;
  pointer = a;
对我来说,这不会产生任何问题,但我会收到以下警告:

assignment makes pointer from integer without a cast
为什么使用cast更好? 我用的是32位的机器

编辑: 通过“这不会产生任何问题”,我是说它编译并存储变量
a
的值

编辑: 变量
a
将实际存储一个地址

因为在C中:

pointer = a;  // not valid in C: a is an int object
              // pointer an object of pointer type
该语句无效,您需要显式转换(转换)才能将
值转换为指针类型

pointer = (char *) a;  // valid assignmnent

有些编译器对您很好,会将
int
值隐式转换为指针类型(并添加警告!),但它们不是必需的,编译器可能会拒绝编译您的程序。

几乎总是最好不要尝试将整数值赋给指针。在极少数情况下,这样的任务是有意义的,演员阵容不仅更好,而且是必需的

指针和整数是不同的类型。在某些情况下,将它们混合在一起是有意义的;在这种情况下,您需要强制转换,因为整数和指针之间没有隐式转换(除了
0
的特殊情况,被视为空指针常量)

此分配是非法的(更准确地说,是违反约束)。一个合格的C编译器必须至少对此发出警告。许多编译器在打印警告后,会生成执行隐式转换的代码,但这不是语言所要求的,您不应该依赖它。我个人的看法是,这样做的编译器对您没有任何好处

pointer = (char*)a;
这是合法的;强制转换告诉编译器生成从
int
char*
的转换。但是转换的结果是由实现定义的,并且很可能不会产生有意义的结果——即使
char*
int
恰好大小相同

(在您问题中的代码中,
a
尚未初始化。我认为您没有向我们展示的真实代码中并非如此。)


你到底想做什么?

在C语言中,指针不仅是内存中的地址,还是一种类型:

pointer = memory size + type
理解这一点的最好方法是考虑防止执行某些算术运算的指针算法。例如,您可以执行以下操作:

int i;
int * ptr, ptr2;

ptr = &i;  // Assign the address of an int to an int pointer
ptr2 = ptr + 2; // Shift the pointer of two int size further
i = ptr - ptr2; // Compute the number of slots between ptr and ptr2
但是,你不能这样做:

int i;
char c;
int * ptr;
char * ptr2;

ptr = &c; // The types are not matching, the compiler will complain 
ptr = 2 * ptr; // This is not allowed by pointer arithmetic
ptr = ptr + ptr; // This is not allowed by pointer arithmetic
等等

但是,您必须始终记住的是,指针不仅仅是内存地址。它是内存地址和类型的组合。

%cat int cast.c
% cat int-cast.c

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    printf("sizeof char *: %zu\n", sizeof (char *));
    printf("sizeof int: %zu\n", sizeof (int));
}
#包括 #包括 内部主(空) { printf(“sizeof char*:%zu\n”,sizeof(char*)); printf(“sizeof int:%zu\n”,sizeof(int)); }
如果编译为32位或64位,则类型的大小不同

%cc-m32 int cast.c&./a.out
字符大小*:4
内部大小:4
%cc-m64 int cast.c&./a.out
字符大小*:8
内部大小:4


正如基思·汤普森(Keith Thompson)明确指出的那样,即使保证它们的大小相同,也仍然需要一个cast,结果充其量只是定义了实现

将一种类型的指针存储到另一种类型的指针是很奇怪的,因此添加cast可以清楚地表明这就是您的意图。您能告诉我们您到底想做什么吗?为什么你需要将
a
分配到
指针中呢?你应该通过扩展“对我来说,这不会产生任何问题”的含义来澄清你的问题。这并不能真正改变任何事情。@StoicaDan:正如我提到的,我是在一台有32位
int
和64位指针的机器上输入的,这是很常见的。在这种情况下,您不能在
int
中存储指针而不丢失信息。在
中声明了整数类型
intptr\u t
uintptr\u t
,它们可以存储转换的指针(如果这些类型存在的话)。我没有必要删除这个问题;在一些答案中有一些很好的信息。标准答案很好,但客观地看,这就像你的孩子问你“为什么不允许”,而你回答“因为禁止”。@MatteoItalia well no,在C中,为什么?@barakmanos警告背后的原因是赋值运算符违反了约束,并且违反约束至少需要来自编译器的诊断消息。我理解这一点,但这里的人们似乎经常试图“坚持”他们的答案,而不是标准说的原因。有时确实没有理由解释或详细说明。但在这种情况下,问题来源的基本逻辑表明OP不了解这种(不安全)分配所带来的风险。@barakmanos“两种类型在每个平台上不一定大小相同”我不认为这是标准中分配约束的基本原理。看,您可以将不同大小的任何整数类型分配给另一个大小的任何整数类型(例如从
无符号长字符
无符号字符
)。在这种情况下,一种类型是整数类型,另一种类型是指针类型。C可能会禁止赋值,因为C是一种类型化语言,类型化语言倾向于限制隐式转换的数量。实际上,我正在测试其他人的代码。他希望能够从键盘输入地址并将其存储到指针中。@StoicaDan:这样做几乎没有意义;这就是为什么语言不允许你直接做。在极少数有意义的情况下,您可以使用石膏。演员说,实际上,“闭嘴,编译器,我真的知道我在做什么”。这段代码对生成的指针有什么作用?@StoicaDan:对于希望从用户处获取地址的罕见情况,您可能希望将
sscanf
%p
@mafso一起使用:这是一个好主意,但需要用户知道实现
% cat int-cast.c

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    printf("sizeof char *: %zu\n", sizeof (char *));
    printf("sizeof int: %zu\n", sizeof (int));
}