指针混淆

3

我正在尝试学习C语言。我所阅读的资料将指针解释如下:

/* declare */
int *i;

/* assign */
i = &something;

/* or assign like this */
*i = 5;

我理解这意味着i = 存储在something中的内容的地址。

或者

将5或5的内部表示放入*i指向的地址中。

然而,在实践中,我看到:

i = 5;

这不会导致类型不匹配吗? 编辑:分号。Ruby 语法习惯...

4
既然你正在学习C语言,那么学习每个语句都要以分号结束可能是值得的。 - Kerrek SB
2
检查你的视野。当 i 的类型为 int* 时,你应该看到的只有编译器错误,而你可能看到的是具有自动存储期的变量,如 int i - pmr
1
关于分号。来自 Ruby...习惯了。 - providence
@pmr,我说的是例如连接到PostgreSQL的教程[在此处](http://www.linuxjournal.com/content/accessing-postgresql-cc)。`conn` 和 res 都被声明为 *con*res,但以我上面质疑的方式进行分配。 - providence
1
除了res = PQexec(...),PQexec函数可能返回指针而不是典型变量。 - Philip
显示剩余2条评论
6个回答

3

好的,是的,在您的示例中将int指针设置为5是类型不匹配,但这是C语言,所以没有任何限制。这可能会导致故障。一些真正的黑客行为可能会期望在绝对地址5处有一些相关数据,但您永远不应该这样做。

英文等效内容:

i = &something

将i赋值为某个东西的地址

*i =5

将i所指向的内容赋值为5。


2
如果您按照您问题中所写的设置i = 5,那么i将包含地址0x00000005,这可能指向垃圾数据。希望这可以帮助解释事情:
int *i;           /* declare 'i' as a pointer to an integer */
int something;    /* declare an integer, and set it to 42 */
something = 42;   
i = &something;   /* now this contains the address of 'something' */
*i = 5;           /* change the value, of the int that 'i' points to, to 5 */
                  /* Oh, and 'something' now contains 5 rather than 42 */ 

2
如果您看到类似以下内容的东西:
int *i;
...
i = 5;

有人试图将地址0x00000005分配给i。尽管这样做有些危险(N1256),但是这是允许的:

6.3.2.3 指针
...
3 值为 0 的整型常量表达式,或者将这样的表达式强制转换为类型 void *,被称为空指针常量55) 如果将空指针常量转换为指针类型,则生成的指针称为空指针,保证与任何对象或函数的指针不相等。
...
5 整数可以转换为任何指针类型。除非先前已指定,否则结果是实现定义的,可能对齐不正确,可能不指向所引用类型的实体,并且可能是陷阱表示。56)
...
55) 宏NULL在头文件<stddef.h>(和其他头文件)中定义为一个空指针常量;请参见7.17。

56) 将指针转换为整数或将整数转换为指针的映射函数旨在与执行环境的寻址结构一致。

根据您所使用的架构和环境,0x00000005可能不是有效的整数地址(我熟悉的大多数架构都要求多字节类型以偶地址开始),这样低的地址可能无法被您的代码直接访问(我不从事嵌入式工作,因此请谨慎考虑)。


这是一个非常有帮助的解释,谢谢。看起来C语言允许你做任何想做的事情,包括杀死你的电脑!我必须小心。 - providence
虽然情况并不是那么糟糕,但是没错,C语言的设计目标是尽可能提供灵活性,同时尽量减少麻烦。因此,它假定你在任何时候都知道自己在做什么。很多时候,即使是写了几十年C语言的人(比如我自己),也不能保证这是一个有效的假设。 - John Bode

1
我理解的意思是i = 存储在something中的东西的地址。
实际上,i包含一个地址,这个地址应该是包含int的变量的地址。我说“应该”是因为在C语言中你不能确定它。
char x;
int *i;
i = (int *)&x;

如果i是一个指针,那么将其分配给一个不同于程序可访问的有效地址,这是一个错误,我认为可能会导致未定义的行为:

int *i;
i = 5;
*i; //undefined behavior..probably segfault

这里有一些例子:

int var;
int *ptr_to_var;

var = 5;
ptr_to_var = var;

printf("var %d ptr_to_var %d\n", var, *ptr_to_var); //both print 5
printf("value of ptr_to_var %p must be equal to pointed variable var %p \n" , ptr_to_var, &var);

那么执行 i = 5;5 的地址放入 i 中?这与执行 i = &5 有什么不同吗? - providence
1
不是。它将五放入i中。换句话说,在指针应该存储地址的地方放置一个不表示有效地址的数字。 - Heisenbug
@Heisenbug:只是为了扮演恶魔的辩护人,数字五 可能 是某些虚构系统上的有效地址,不是吗?或者在某些 C/POSIX 等规范中是否有定义有效的内存地址范围? - maerics
一个从4开始的整数呢?第二个字节位于地址5处。内存按字节寻址,而不是按整数寻址。 - Femaref
@Femaref:嗯,我说错了话。我会删除那条评论。 - Heisenbug

1

希望这可以帮到你。

这声明了一个名为“myIntPointer”的变量,其类型为“指向整数的指针”。

int *myIntPointer;

这段代码将一个名为“blammy”的整型变量的地址存储在名为“myIntPointer”的整型指针中。
int blammy;
int *myIntPointer;

myIntPointer = &blammy

这段代码将整数值5存储在内存中由int变量"blammy"寻址的空间中,通过一个名为"myIntPointer"的int指针分配该值。

int blammy;
int *myIntPointer;

myIntPointer = &blammy

*myIntPointer = 5;

这将把名为“myIntPointer”的整型指针设置为指向内存地址5。

int *myIntPointer;

myIntPointer = 5;

1

将硬编码地址分配作为一种做法不应该被采用(即使在嵌入式领域中,但有些情况下是适合的)。 在声明指针时,请限制自己仅使用动态分配的内存(请参见malloc())或静态(非临时)变量的&(地址)来为其分配值。这将确保强健的代码,并减少获得臭名昭着的分段错误的机会。

祝您学习c顺利。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接