指向静态char的int指针

时间:2015-02-13 17:21:11

标签: c pointers memory-management static

考虑以下代码:

#include <stdio.h>

#define main_arg int argc, char *argv[]

int main(main_arg)
{
    static char chr = '5' - '0'; // Dec 5
    int *p = &chr;               // 4 bytes pointer

    printf("Result: %i", *p);

    return(0);
}

Result: 5

为什么我必须将chr声明为静态以获得适当的值? 如果我不使用静态,p将读取4个字节的总数,其中3个将是&#34;随机&#34;。但如果一个字节chr表示位于静态存储器中,那不会发生吗?

这是未定义的行为,结果是不确定的,它只是这样,意外地(我一直在尝试)?

3 个答案:

答案 0 :(得分:3)

当你声明一个变量static时,它被分配在.BSS或.data中,并且该区域全部归零,所以即使你已经将chr初始化为5,巧合的是chr地址之前和之前的所有字节都是零

这是一种验证方法。 (可能在您的系统上有所不同)

(gdb) x/16w &chr - 16
0x601030:   0   0   0   0
0x601040 <chr.2180>:    5   0   0   0
0x601050:   0   0   0   0
0x601060

以下是各节。

06:43:46~ $ readelf -s a.out

53: 0000000000601030     0 NOTYPE  WEAK   DEFAULT   24 data_start
54: 0000000000601041     0 NOTYPE  GLOBAL DEFAULT   24 _edata
55: 00000000004005e4     0 FUNC    GLOBAL DEFAULT   14 _fini
56: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@@GLIBC_2.2.5
57: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_
58: 0000000000601030     0 NOTYPE  GLOBAL DEFAULT   24 __data_start
59: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
60: 0000000000601038     0 OBJECT  GLOBAL HIDDEN    24 __dso_handle
61: 00000000004005f0     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used
62: 0000000000400570   101 FUNC    GLOBAL DEFAULT   13 __libc_csu_init
63: 0000000000601048     0 NOTYPE  GLOBAL DEFAULT   25 _end
64: 0000000000400440     0 FUNC    GLOBAL DEFAULT   13 _start
65: 0000000000601041     0 NOTYPE  GLOBAL DEFAULT   25 __bss_start
66: 000000000040052d    53 FUNC    GLOBAL DEFAULT   13 main
67: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses

答案 1 :(得分:3)

char数据类型是一个字节。您使用整数点“int * P”指向chr的单字节内存位置,但C将此视为四字节位置,因为它认为它是指向int的指针,其长度为四个字节。基于你的5的结果,显然当你将它声明为静态时,chr的位置恰好跟随零,因此结果只是5.当它没有被声明为静态时,它就在堆栈上并且只是选择在chr的位置之后的内存中的不同值。无论如何,使用* P引用它不应该存储的内存并且将产生不可预测的结果。

顺便说一下,你的样本将int *声明为“* P”(大写字母P)并稍后将其引用为“* p”(小写p),因此该代码不会按原样运行。

答案 2 :(得分:3)

在某些系统中,您的代码可能无法运行,主要是因为对齐。在某些RISC系统中,char可以与任何对齐,但是int必须与4个字节对齐,例如。在这种情况下,如果您尝试取消引用这样的指针,某些内存访问保护机制可能会发出中断,整个程序将立即失败。

在你的情况下,假设你在Linux中运行,使用intel cpu,使用gcc编译,chr将驻留在.data段中,并且它的所有不相关部分将最有可能设置为0。

但同样,你以错误的方式访问内存,一切都应该发生,因为它是一个未定义的行为。

提供更多信息,如果你删除static,并在上述环境中运行该程序,你读取的额外值不是&#34; random&#34;,但它是随机的,字面意思。这称为canary。它是一种用于检测堆栈聚焦攻击的内存保护机制。