100分求解简单C语言题(麻烦 星羽 进来下)
to 星羽: 嘿嘿,上次服务周到,只好又叫你了,不好意思。实在太感谢你了,对我帮助很大,你还敢说你表达能力不怎么样。。,注释写得很好,那程序我理解了。我原本想给你100多分的。。但系统提示,我最多只能给100分,在以后帖子多加给你。malloc()和free()是成对分配和释放的吗?比如malloc分配4个字节,free就释放4个?malloc分配n个, free()就释放n个?所以前面List L = (List)malloc(sizeof(List))用free(L)就出错?
1)sizeof问题,谁能解释下 下面程序的输出结果?为什么会出现8, 4. (vc6.0)
#include <stdio.h>
struct student
{
int num;
float socre;
};
typedef struct student *List;
int main(void)
{
List L;
printf( "%d\n ", sizeof * L);
printf( "%d\n ", sizeof L);
return 0;
}
2)动态存储分配问题,要创建动态一维数组,应该分配 n 个 int型的内存吧?看下面程序,谁帮忙解释下?(vc6.0)
#include <stdio.h>
#include <stdlib.h>
//结构声明
typedef int *ListItem;
struct alist
{
int n;//表长
int maxsize;//表的最大长度
ListItem table;//表元素数组
};
typedef struct alist *List;
int main(void)
{
//创建表
int size;
List myTable = (List)malloc(sizeof * myTable);
printf( "请输入你要创建的表的大小: ");
scanf( "%d ", &size);
myTable-> table = (ListItem)malloc(size * sizeof(ListItem)); //书上是这句,为什么不是下面那句呢?
//myTable-> table = (ListItem)malloc(size * sizeof(int));
return 0;
}
3)函数返回值问题,请看下面函数
int test(int i)
{
if (i < 0)
{
//这里是安全性检查,我想在这里返回,但不想返回任何值?怎么做?不要用return; 那样会有警告...
}
}
4)问一个比较傻的问题,数组在内存中是连续存储的,那还能不能用动态内存来分配,我的意思是象链表那样,需要一个结点分配一个,且在内存中是不连续的。
[解决办法]
1. 注意你L还没初始化。。sizeof (*L)相当于sizeof(struct student)就是结构体的大小。int,float各占4个字节,所以为8。(这里详细看下字节对齐). sizeof(L)就是一个指针所占的字节数,VC6.0是32位的,所以为4。
2.因为table是(int *)型而不是int 型。
3. printf( "error\n ");
exit(1);
4.可以。。
[解决办法]
1)sizeof问题,谁能解释下 下面程序的输出结果?为什么会出现8, 4. (vc6.0)
#include <stdio.h>
struct student
{
int num;
float socre;
};
typedef struct student *List;
int main(void)
{
List L;
printf( "%d\n ", sizeof * L);//L 类型的指针,其指向多是一个struct student结构体,大小是8.应该这样吧sizeof(*L)
printf( "%d\n ", sizeof L); //L是个存放在四字节空间内的一个地址值.32位的机器地址都是4字节.
return 0;
}
2)动态存储分配问题,要创建动态一维数组,应该分配 n 个 int型的内存吧?看下面程序,谁帮忙解释下?(vc6.0)
#include <stdio.h>
#include <stdlib.h>
//结构声明
typedef int *ListItem;
struct alist
{
int n; //表长
int maxsize; //表的最大长度
ListItem table; //表元素数组
};
typedef struct alist *List;
int main(void)
{
//创建表
int size;
List myTable = (List)malloc(sizeof * myTable);
printf( "请输入你要创建的表的大小: ");
scanf( "%d ", &size);
myTable-> table = (ListItem)malloc(size * sizeof(ListItem)); //书上是这句,为什么不是下面那句呢?
//myTable-> table = (ListItem)malloc(size * sizeof(int)); //为了通用,在有的系统中,int * 和int大小可能不相等.不过在你现在的环境中,实际上是一样的.
return 0;
}
3)函数返回值问题,请看下面函数
int test(int i) //把这里的int 换成void 就可以了,下边就能用return 了.
{
if (i < 0)
{
//这里是安全性检查,我想在这里返回,但不想返回任何值?怎么做?不要用return; 那样会有警告...
}
}
4)问一个比较傻的问题,数组在内存中是连续存储的,那还能不能用动态内存来分配,我的意思是象链表那样,需要一个结点分配一个,且在内存中是不连续的。
好象不能一个一个节点分配.但可以动态分配数组空间,当数组使用.
[解决办法]
第0题 我替你明确一下问题
malloc()和free()两个函数没有什么内在联系, 那么free(L);是如何知道L指向的空间有多大?
有一种方案是在申请空间时返回的要比你要求的多一点点, 而且L并不是指向该空间的开始位置,
那么最前面你不会访问的那点空间就可以用来存放申请空间的大小, 便于以后释放。
第3题 assert(i> =0); //可以满足你文字意思上的要求,不过可能不是你的本意!
第4题 不太清楚你的意思
数组和普通变量一样使用栈空间,申请和释放不用你操心,不会产生内存泄漏;
你自己当然可以申请一段堆空间,你也可以把它当作数组空间来使用,但要避免越界访问和负责释放它,但是这段空间在申请后大小就固定了,不能动态改变;
如果你是想实现类似于动态数组的结构,去学习STL中vector <> 的原理吧,要点是重新申请一块更大的内存,将以前的数据全盘复制过来,再释放以前的内存。
[解决办法]
影响结构体的sizeof的因素:
1) 不同的系统(如32位或16位系统):不同的系统下int等类型的长度是变化 的,如对于16位系统,int的长度(字节)为2,而在32位系统下,int的长度为4;因此如果结构体中有int等类型的成员,在不同的系统中得到的sizeof值是不相同的。
2) 编译器设置中的对齐方式:对齐方式的作用常常会让我们对结构体的sizeof值感到惊讶。
对齐
为了能使CPU对变量进行高效快速的访问,变量的起始地址应该具有某些特性,即所谓的“对齐”。例如对于4字节的int类型变量,其起始地址应位于4字节边界上,即起始地址能够被4整除。变量的对齐规则如下(32位系统):
Type
Alignment
char
在字节边界上对齐
short (16-bit)
在双字节边界上对齐
int and long (32-bit)
在4字节边界上对齐
float
在4字节边界上对齐
double
在4字节边界上对齐
structures
单独考虑结构体的个成员,它们在不同的字节边界上对齐。
其中最大的字节边界数就是该结构的字节边界数。
MSDN原话:Largest alignment requirement of any member
理解结构体的对齐方式有点挠头,如果结构体中有结构体成员,那么这是一个递归的过程。
对齐方式影响结构体成员在结构体中的偏移
设编译器设定的最大对齐字节边界数为n,对于结构体中的某一成员item,它相对于结构首地址的实际字节对齐数目X应该满足以下规则:
X = min(n, sizeof(item))
例如,对于结构体 struct {char a; int b} T;
当位于32位系统,n=8时:
a的偏移为0,
b的偏移为4,中间填充了3个字节, b的X为4;
当位于32位系统,n=2时:
a的偏移为0,
b的偏移为2,中间填充了1个字节,b的X为2;
结构体的sizeof
设结构体的最后一个成员为LastItem,其相对于结构体首地址的偏移为offset(LastItem),其大小为sizeof(LastItem),结构体的字节对齐数为N,则:
结构体的sizeof 为: 若offset(LastItem)+ sizeof(LastItem)能够被N整除,那么就是offset(LastItem)+ sizeof(LastItem),否则,在后面填充,直到能够被N整除。
例如:32位系统,n=8,
结构体 struct {char a; char b;} T;
struct {char a; int b;} T1;
struct {char a; int b; char c;} T2;
sizeof(T) == 2; N = 1 没有填充
sizeof(T) == 8; N = 4 中间填充了3字节
sizeof(T2)==12; N = 4 中间,结尾各填充了3字节
注意:
1) 对于空结构体,sizeof == 1;因为必须保证结构体的每一个实例在内存中都有独一无二的地址。
2) 结构体的静态成员不对结构体的大小产生影响,因为静态变量的存储位置与结构体的实例地址无关。例如:
struct {static int I;} T; struct {char a; static int I;} T1;
sizeof(T) == 1; sizeof(T1) == 1;
3) 某些编译器支持扩展指令设置变量或结构的对齐方式,如VC,
[解决办法]
malloc 分配内存的时候c会纪录这个空间的大小,如果是debug版本,这个大小就在分配的空间前面,
你可以用 _msize() 函数得到这个大小, 也就是说c是可以通过指针知道这个它指向空间的大小,指
针还有一个指向数据类型, 当你指针的类型和指向空间大小不匹配的时候,比如
typedef struct NODE
{
int a;
int b;
}*PNODE;
PNODE p = (PNODE)malloc(sizeof(PNODE));
这里指针p的指向数据类型是PNODE,这种类型指针指向空间大小应该是 sizeof(NODE) 不是 sizeof(PNODE)
(sizeof(PNODE)是指针的大小, sizeof(NODE) 是指针指向数据类的大小)
当你改变 p 的内容,比如 p-> a = 10; p-> b = 10;
然后再free(p); 的时候,由于类型和大小不匹配,在debug版中c会做数据校验
用 HeapValidate() 检查整个堆或堆中的一个对象的完整性, 如果指针类型和大小不匹配,则这个
函数会断言,就是当机. 具体我也不记得太清楚了,有时间你可以看看windows内存管理
总之你记住指针指向数据类型要和指针指数据大小匹配
1)
1)sizeof问题,谁能解释下 下面程序的输出结果?为什么会出现8, 4. (vc6.0)
#include <stdio.h>
struct student
{
int num;
float socre;
};
typedef struct student *List;
int main(void)
{
List L;
printf( "%d\n ", sizeof * L);
printf( "%d\n ", sizeof L);
return 0;
}
----------------------------------
sizeof * L == sizeof(*L) == sizeof(struct student) = 8 (byte) // int float大小都是4,加起来就是 8 byte
sizeof L == sizeof(L) == sizeof(struct student*) = 4 (byte) // 在32位机器上指针都是32 / 8 = 4 byte
指针的大小跟着机器的位数,如果是64位机器,则指针大小是 64 / 8 = 8 byte
c中有些数据时跟机器字长有关的,比如
在 32 位机
sizeof(int) = 4
sizeof(void*) = 4
...
在64位机
sizeof(int) = 8
sizeof(void*) = 8
...
当然在sizeof一个class和struct的时候,还涉及字节对齐问题
2)
myTable-> table = (ListItem)malloc(size * sizeof(ListItem)); //书上是这句,为什么不是下面那句呢?
//myTable-> table = (ListItem)malloc(size * sizeof(int));
----------------------------
你看的是什么书啊,好烂阿,书的写法是错的,你下面那个才是对的,当然在这个例子中
sizeof(ListItem) 刚好和 sizeof(int) 大小一样,如果是
typedef _int64 *ListItem; 书的写法就玩完了
3)
函数返回值问题,请看下面函数
int test(int i)
{
if (i < 0)
{
//这里是安全性检查,我想在这里返回,但不想返回任何值?怎么做?不要用return; 那样会有警告...
}
}
----------------------------
首先当函数定义为有返回值的时候,是不能不返回的,在c,如果你不写return,那么并不代表函数没返回
而是会返回一个未知的值,当然这个是不安全的
如题解决办法很多,比如
1,第一个出错返回值 比如 -1
int test(int i)
{
if (i < 0)
return -1;
......
}
2, 把返回值得做参数
void test(int i, int* result)
{
if (!result) return;
if (i < 0) return;
....
*result = xxxx;
.....
}
4) 问一个比较傻的问题,数组在内存中是连续存储的,那还能不能用动态内存来分配,
我的意思是象链表那样,需要一个结点分配一个,且在内存中是不连续的。
-----------
数组空间一定是连续的,所以不能向连表那样,动态增加节点,如果可以的话,那
连表这个东西就不会有人用了,都用数组去了
数组要求内存连续,但你分配一个数组后,这个数组后面的空间有可能被别的数据用了
所以你再想增加节点是不行的
用realloc 可以改变一个数组的大小,这个是整个空间重新分配了,
相当于重新申请了一块空间,把以前的数据拷贝过去。。。。。。。