除了0之外,我们可以手动初始化指针变量吗?什么是无法初始化的原因

时间:2011-07-16 13:25:46

标签: c pointers

为什么我们不能用用户定义的输入初始化指针变量?

4 个答案:

答案 0 :(得分:3)

您可以将指针变量初始化为anyvalue。

int *ptr = 0;

将指针ptr初始化为0(这实际上意味着它没有指向任何有效的指针)

int a = 10;
int *ptr = &a;

初始化指针ptr以指向整数变量a的地址。

答案 1 :(得分:2)

您可以将全局范围内的指针初始化为任何值,该值可以是常量表达式,也可以由链接器解析。这是因为C编译器将常量直接放入初始化代码中。引用的符号也放在初始化代码中,链接器用实际地址值替换这些符号。

// global scope
int foo;
int* bar = &foo; // ok, since &foo is a known address
int* bar2 = &foo+1; /* ok, since &foo is a known
            address and the offset is constant. */
int* whatever = (int*) 0xabcd; /* Ok, since 0xabcd is
                a constant value, and can be used as
                an address, but it depends on your
                environment if this address makes any
                sense */
int *baz = bar; /* not OK, since the value of bar is
                   stored into the RAM at run time,
                   and the linker can't determine that
                   this value does point to &foo */

在函数中,您可以将任何非静态指针变量初始化为已存在的值。这是因为这些初始化的工作方式与普通变量赋值相同。

修改:非法int *baz = bar;部分

免责声明:我描述了在Windows,Linux和* BSD上看到的典型编译器+链接器工具链的行为,在嵌入式世界中,初始化可能看起来非常不同。

全局级别的所有变量初始化都放入可执行文件中的自己的数据段中,并在程序启动时复制到RAM中。这意味着链接器必须通过收集所有全局变量并在此部分中解析符号引用来创建此部分。链接器只能解析仅包含链接时常量值的值,这些值是地址和数字常量。 int *baz = bar;语句确实使用间接值bar。虽然在这种特定情况下bar可以解析为&foo,但编译器并不关心,因为标准要求这是baz的赋值,其运行时内存为bar。由于链接器无法使用此类运行时内存引用,因为链接器无法运行该程序,编译器将拒绝为此语句生成代码。

同样将bar的类型从int* bar更改为int* const bar也没有用,因为常量确实有一个内存区域,C编译器必须表现得好像它使用了这个在某处使用值时的内存区域。这意味着即使明确了哪个值bar,编译器也不能将常量值放入目标代码中,因为标准要求运行时内存用于确定{{1}的值当它被使用时。

作为旁注,在C ++中允许进行基于运行时数据的初始化。

答案 2 :(得分:1)

让我猜一下,你正试图做这样的事情:

char* usersInput;
scanf("%s", usersInput);     /* error */

这不起作用,因为尚未分配字符串。你可以,例如选择可能是最大输入长度的内容并执行:

char* usersInput = malloc(10000);
scanf("%s", usersInput);     /* fine */

答案 3 :(得分:1)

你可以这样做,例如

uint16_t *p = 0x00DFF01C;

可能有意义, iff 访问该地址有意义,例如该地址被映射到特定硬件中的某些东西(例如特定设备)。通常它没有意义,除非您正在编写低级代码,或嵌入式系统的代码等。

(或者在C语言中对Amiga“经典”硬件进行金属抨击)