[C语言基础]C学习笔记(二)

一,程序找错

1,

char *getmem()
{
	char p[]="hello world";
	return p;
}

int main()
{
	char *str=NULL;
	str=getmem();
	printf("%s\n",str);
}

以上程序出错的原因是getmem函数里p是一个本地变量,是在栈上申请内存的,返回时候就释放了,正确的应该是调用malloc函数从堆上申请,返回时候不会释放,在main()函数里程序员主动释放。

正确的如下:

char *getmem()
{
	char *p=(char*)malloc(20);
	strcpy(p,"hello world");
	return p;
}

int main()
{
	char *str=NULL;
	str=getmem();
	printf("%s\n",str);
	free(str);
	return 0;
}

2,

void getmem(char *p)
{
	p=(char*)malloc(100);
	p="hello world";
}


int main()
{
	char *str=NULL;
	getmem(str);
	printf("%s\n",str);
}

以上程序出错的原因是getmem函数里,p用malloc分配了一块内存,然后又将内存指向 了常量区域,这样malloc()分配的内存永远不能得到释放,这样会造成内存泄露,另外主函数里的调用getmem(str),在返回的时候str仍然指向空,形参和实参的差别。因为要要改变指针的值,所以要将指针本身的地址当作函数参数传进去。要改变函数参数的值,就要将该值的地址传进去。

正确的应该如下:

void getmem(char **p)
{
	*p=(char*)malloc(100);
	strcpy(*p,"hello world");
}


int main()
{
	char *str=NULL;
	getmem(&str);
	printf("%s\n",str);
	free(str);
	return 0;
}
void swap(int *a, int *b)
{
        int t;
        t = *a;
        *a = *b;
        *b = t;
}     //标准的交换两个数的函数

3,正确处理C语言的整型溢出的问题

C语言溢出问题总结

对于unsigned整型溢出,C的规范是有定义的——“溢出后的数会以2^(8*sizeof(type))作模运算”,也就是说,如果一个unsigned char(1字符,8bits)溢出了,会把溢出的值与256求模。例如:
1,unsigned char x = 0xff;
2,printf("%d\n", ++x);
上面的代码会输出:0 (因为0xff + 1是256,与2^8求模后就是0)
对于signed整型的溢出,C的规范定义是“undefined behavior”,也就是说,编译器爱怎么实现就怎么实现。对于大多数编译器来说,算得啥就是啥。比如:
signed char x =0x7f; //注:0xff就是-1了,因为最高位是1也就是负数了
printf("%d\n", ++x);
上面的代码会输出:-128,因为0x7f + 0×01得到0×80,也就是二进制的1000 0000,符号位为1,负数,后面为全0,就是负的最小数,即-128。


4,C语言类型在32位和64位机器上的长度

 charshortintlongptrlong-long 
32位124448 
62位124888 


5,int long对应的最大值

int           ->32位,最高位是正负位所以实际值只有31位,那它的最大值=2^31-1 = 2147483647.
 unsigned  int ->2^32 -1 = 4294967295
 long long     ->2^63 -1 = 92233720368547758007
 unsigned  long long ->2^64-1=18446744073709551615


6,内存对齐

#pragma pack(1)
struct node{
  char f;
   int e;
   short int a;
   char b;};
struct node n;
printf("%d\n",sizeof(n));
这里强制按照1字节进行对齐,可以理解成所有的内容都是按照1字节进行读取(暂且这样理解,因为这样可以很好的理解内存对其机制),
其他所有的数据成员都是1字节的整数倍,所以也就不用进行内存对其,各个成员在内存中就按照实际顺序进行排列,结构体实际长度为8
 
#pragma pack(2)
struct node{
  char f;
   int e;
   short int a;
   char b;};
struct node n;
printf("%d\n",sizeof(n));
这里强制按照2字节进行对齐。如果内存分布仍然是连续的话,那么int e就得三次才能读到CPU中,所以为了“讲究”int e的读取,
所以在char f之后预留1BYTE,最后的char b也是如此,所以长度为10
 
#pragma pack(4)
struct node{
  char f;
   int e;
   short int a;
   char b;};
struct node n;
printf("%d\n",sizeof(n));
这里强制按照4字节进行对齐。所以char f后要预留3BYTE,而short int a 和 char b可以一次读取到CPU(按照4字节读取),所以长度为12
如果#pramga pack(n)中的n大于结构体成员中任何一个成员所占用的字节数,则该n值无效。编译器会选取结构体中最大数据成员的字节数为基准进行对其

7,内联函数和宏定义的区别

内联函数在编译的时候内联函数可以直接呗镶嵌到目标代码中,宏不是函数,只是在编译前(编译预处理阶段)将程序中有关字符串替换成宏体,宏是在代码处不加任何验证的简单替代,而内联函数是将代码直接插入调用处,而减少了普通函数调用时的资源消耗,宏是在代码处不加任何验证的简单替代,而内联函数是将代码直接插入调用处,而减少了普通函数调用时的资源消耗, inline 可以作为某个类的成员函数,当然就可以在其中使用所在类的保护成员及私有成员。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值