STRUCT
实验目的
代码总览
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int a[ 2 ] ;
double d;
} struct_t;
double fun ( int i) {
volatile struct_t s;
s. d = 3.14 ;
s. a[ i] = 1073741824 ;
return s. d;
}
int main ( int argc, char * argv[ ] ) {
int i = 0 ;
if ( argc >= 2 )
i = atoi ( argv[ 1 ] ) ;
double d = fun ( i) ;
printf ( "fun(%d) --> %.10f\n" , i, d) ;
return 0 ;
}
代码分析
主函数
int main ( int argc, char * argv[ ] )
{
int i = 0 ;
if ( argc >= 2 )
i = atoi ( argv[ 1 ] ) ;
double d = fun ( i) ;
printf ( "fun(%d) --> %.10f\n" , i, d) ;
return 0 ;
}
atoi函数
:atoi是把字符串转换成整型数的一个函数。int atoi(const char *nptr) 函数会扫描参数nptr 字符串,会跳过前面的 空白字符(例如空格,tab缩进) 等。如果 nptr不能转换成 int 或者 nptr为空字符串,那么将返回0。特别注意,该函数要求被转换的字符串是按十进制数 理解的。atoi输入的字符串对应数字存在大小限制 (与int类型大小有关),若其过大可能报错-1。
fun函数
double fun ( int i)
{
volatile struct_t s;
s. d = 3.14 ;
s. a[ i] = 1073741824 ;
return s. d;
}
volatile函数
:volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值 。volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,编译器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份 。
编译运行
结果分析
struct结构体中,定义数组能使用部分只有a[0]和a[1],故i为0和1时,结果并未出现问题;当i为2或3时,机器访问内存的时候跨过了数组本身的界限修改了 d 的值,导致结果出现错误;当i为4或5时,机器又越过了d,结果仍然正确;当i为6时,机器报错,何时报错与机器系统有关系。如果不检查输入字符串的长度,就很容易出现这种问题,尤其是针对在栈上有界限的字符数组。