这里写目录标题
编程日志1(show-bytes.c)
代码说明
将数val=12345各种不同的类型强制转换,并在屏幕上输出每个字节在计算机内部所占地址值
代码"showbytes.c"
/* show-bytes - prints byte representation of data */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned char *byte_pointer;
//typedef char *byte_pointer;
//typedef int *byte_pointer;
void show_bytes(byte_pointer start, size_t len) {
size_t i;
for (i=0;i<len;i++)
printf("%p\t0x%.2x\n", &start[i], start[i]);
printf("\n");
}
void show_int(int x) {
show_bytes((byte_pointer) &x, sizeof(int));
}
void show_float(float x) {
show_bytes((byte_pointer) &x, sizeof(float));
}
void show_pointer(void *x) {
show_bytes((byte_pointer) &x, sizeof(void *));
}
void test_show_bytes(int val) {
int ival = val;
//float fval = (float) ival;
double fval = (double) ival;
int *pval = &ival;
printf("Stack variable ival = %d\n", ival);
printf("(int)ival:\n");
show_int(ival);
printf("(float)ival:\n");
show_float(fval);
printf("&ival:\n");
show_pointer(pval);
}
void simple_show_a() {
int val = 0x87654321;
byte_pointer valp = (byte_pointer) &val;
show_bytes(valp, 1); /* A. */
show_bytes(valp, 2); /* B. */
show_bytes(valp, 3); /* C. */
}
void simple_show_b() {
int val = 0x12345678;
byte_pointer valp = (byte_pointer) &val;
show_bytes(valp, 1); /* A. */
show_bytes(valp, 2); /* B. */
show_bytes(valp, 3); /* C. */
}
void float_eg() {
int x = 3490593;
float f = (float) x;
printf("For x = %d\n", x);
show_int(x);
show_float(f);
x = 3510593;
f = (float) x;
printf("For x = %d\n", x);
show_int(x);
show_float(f);
}
void string_ueg() {
const char *s = "ABCDEF";
show_bytes((byte_pointer) s, strlen(s));
}
void string_leg() {
const char *s = "abcdef";
show_bytes((byte_pointer) s, strlen(s));
}
void show_twocomp() {
short x = 12345;
short mx = -x;
show_bytes((byte_pointer) &x, sizeof(short));
show_bytes((byte_pointer) &mx, sizeof(short));
}
int main(int argc, char *argv[])
{
int val = 12345;
if (argc > 1) {
val = strtol(argv[1], NULL, 0);
printf("calling test_show_bytes\n");
test_show_bytes(val);
}
else {
printf("calling show_twocomp\n");
show_twocomp();
printf("Calling simple_show_a\n");
simple_show_a();
printf("Calling simple_show_b\n");
simple_show_b();
printf("Calling float_eg\n");
float_eg();
printf("Calling string_ueg\n");
string_ueg();
printf("Calling string_leg\n");
string_leg();
}
return 0;
}
代码解释
各个类型变量在计算机中储存字节不同,相同的数强制转换为不同数据类型后,其储存结果可能在计算机内部发生变化,因而在声明变量类型时需要注意类型变化引起的各种后果。
gcc运行结果
编程日志2(fsum.c)
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 256
int main(int argc, char *argv[]) {
char prefix[BUFSIZE];
char next[BUFSIZE];
int i;
float sum = 0.0;
for (i = 1; i < argc; i++) {
float x = atof(argv[i]);
sum += x;
if (i == 1)
sprintf(prefix, "%.4g", x);
else {
sprintf(next, " + %.4g", x);
strcat(prefix, next);
printf("%s = %.4g\n", prefix, sum);
}
}
return 0;
}
调试
测试输入1: 1e20 -1e20 3.14
测试输入2: -1e20 3.14
测试输入3: -1e20 3.14 1e20
调试结果如下:
代码解释
3.14在加上1e20时会舍去,太小了
编程日志3(struct.c)
代码
#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; /* Possibly out of bounds */
return s.d; /* Should be 3.14 */
}
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;
}
调试
测试输入:0; 1;2;3;4;
运行结果:
代码解释
int a[2]在程序运行超过三次后会溢出,超过数组范围输出的数据应该是随机数
结论
写程序时需注意数组的溢出,理解栈内数据存放方式,防止因为数据溢出而产生的隐患
编程日志4(sq.c)
输出一个数的平方
代码
#include <stdio.h>
#include <stdlib.h>
int sq(int x) {
return x*x;
}
int main(int argc, char *argv[]) {
int i;
for (i = 1; i < argc; i++) {
int x = atoi(argv[i]);
int sx = sq(x);
printf("sq(%d) = %d\n", x, sx);
}
return 0;
}
调试
测试输入:12;133;2333;4000;5000;65535;400000;500000;
运行结果:
其对应相反数(负数)运行结果与正数相同,如下:
代码解释
当测试数据超过4000–5000中的一个数时,其平方储存(double类型)会发生溢出
编程日志5(locate.c)
输出16MB和1GB在内存中存在的地址与内容,并且增加存储,用不同的64位移位函数输出
代码
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
static void show_pointer(void *p, char *descr) {
// printf("Pointer for %s at %p\n", descr, p);
printf("%s\t%p\t%lu\n", descr, p, (unsigned long) p);
}
char big_array[1L<<24]; /* 16 MB */
//char huge_array[1L<<31]; /* 2 GB */
char huge_array[1L<<30];/* 1 GB */
int global = 0;
int useless() { return 0; }
int main ()
{
void *p1, *p2, *p3, *p4;
int local = 0;
p1 = malloc(1L << 28);
p2 = malloc(1L << 8);
//p3 = malloc(1L << 32);
p3 = malloc(1L << 16);
p4 = malloc(1L << 8);
show_pointer((void *) big_array, "big array");
show_pointer((void *) huge_array, "huge array");
show_pointer((void *) &local, "local");
show_pointer((void *) &global, "global");
show_pointer((void *) p1, "p1");
show_pointer((void *) p2, "p2");
show_pointer((void *) p3, "p3");
show_pointer((void *) p4, "p4");
show_pointer((void *) useless, "useless");
show_pointer((void *) exit, "exit");
show_pointer((void *) malloc, "malloc");
return 0;
}
运行结果
编程日志6(runaway.c)
设立栈 从100挨个递减
代码
#include <stdio.h>
#include <stdlib.h>
int recurse(int x) {
int a[1<<15]; /* 4 * 2^15 = 64 KiB */
printf("x = %d. a at %p\n", x, a);
a[0] = (1<<14)-1;
a[a[0]] = x-1;
if (a[a[0]] == 0)
return -1;
return recurse(a[a[0]]) - 1;
}
int main(int argc, char *argv[]) {
int x = 100;
if (argc > 1)
x = atoi(argv[1]);
int v = recurse(x);
printf("x = %d. recurse(x) = %d\n", x, v);
return 0;
}
调试
运行结果:
编程日志7(bufdemo.c)
代码
/* Demonstration of buffer overflow */
#include <stdio.h>
#include <stdlib.h>
/* Implementation of library function gets() */
char *gets(char *dest)
{
int c = getchar();
char *p = dest;
while (c != EOF && c != '\n') {
*p++ = c;
c = getchar();
}
*p = '\0';
return dest;
}
/* Read input line and write it back */
void echo()
{
char buf[4]; /* Way too small! */
gets(buf);
puts(buf);
}
void call_echo() { echo(); }
/*void smash()
{
printf("I've been smashed!\n");
exit(0);
}*/
int main()
{
printf("Type a string:");
call_echo();
return 0;
}
调试结果
编程日志8(hexify.c)
代码
/* Convert sequence of hex digits on command line into a string, terminated by \n */
#include <stdio.h>
int main(int argc, char *argv[]) {
int i;
for (i = 1; i < argc; i++) {
unsigned long dig = strtoul(argv[i], NULL, 16);
putchar((char) dig);
}
putchar('\n');
return 0;
}