c语言易错点

负数使用位运算符:

负数的特殊性

c语言中,数据都是以补码的形式进行运算,正数三码合一,负数的补码为反码加1,反码->原码符号位不变数据位取反。
在左右移位时,除负数右移补1外,其他情况都补0。
例如-8右移三位为-1。计算方法为:写出-8的补码,对补码右移三位,结果再求补码得到答案-1。


swtich

提示:如果case中没有break,会接着向下执行case::

swtich(必须为整数,字符类型也可以归为整形){
   case  (必须为常量) :
		...
		...
		break;
	case  1 :
		...
		...
		break;
	defalut:
		...
		...
		break;
}

数组:

提示:注意下标越界编译器不会报错,但程序会崩溃,一定要小心

int arr[必须为常量];
int arr[] = {1,2,3};//对全部数组初始化时不指定长度
int arr[3][2] = {1,2, 3,4, 5,6};//对二维数组初始化时指定长度
int arr[][2] = {1,2, 3,4, 5,6};//可以省略行下标,列下标不可省略

int arr[][2] = {{1,2}, {3,4}, {5,6}};//可以分行赋值
arr[0][2] = 3; //数组在内存中是一段连续内存,越界会向后查找

部分赋值时,未赋值的部分为0
数组名是一个指针常量,指向第一个元素。

#字符数组:
char str[] = "helloworld";//sizeof (str) = 11,因为有终止符\0,例:
char str2[11] ;
str2 = "helloworld";//字符数组的长度要大于等于十一

define和typedef

提示::

//以下结果一样
#define NEWINT int
typedef int NEWINT2;
NEWINT n;//编译时直接替换
NEWINT2 m; //NEWINT2是别名,但类似于新类型,不会替换

define和typedef

提示::

//以下结果一样
#define NEWINT int
typedef int NEWINT2;
NEWINT n;//编译时直接替换
NEWINT2 m; //NEWINT2是别名,但类似于新类型,不会替换

//以下结果不不不一样
#define PINT int*
typedef int* PINT2;
PINT  p1,p2,p3,p4;//只有p1是指针
PINT2 p1,p2,p3,p4; //四个都是指针

指针

提示::

//
任何指针都占四个字节,所有应用程序程序,在系统里面的都是4G虚拟内存

//指针运算
关键://指针+整数=指针->实际增加 = 指针地址 + 整数*数据类型长度(指针偏移)
//指针-整数=指针->实际增加 = 指针地址 - 整数*数据类型长度
//指针-指针=相隔长度

//一维数组名是指向第一个元素的指针,数组作为函数参数传递时,传递的是首地址
关键://二维数组名是指向第一个数组的指针,可以把二维数组看成若干个一维数组的集合
int arr2[2][3];
*(*(arr2 + 1) + 2) ---> 等价于arr2[1][2]

const int n = 0;
int* pn = &n;
*pn = 45;//结果n = 45;可以通过指针修改
解决方法: const int *pn = &n;

const int* 和int* const区别

提示::

//以下结果一样
int n = 10int m = 10const int* pn = &n;
//pn = &m;//可以改变指针
//错误语句:*pn = 4;//指针常量,指向的东西不能修改

int* const pm = &m;
//*pm = 4;//正确
//错误语句:pn = &m;//指向的是常量,不能修改


枚举

提示::

enum Color{red, green=9, blue}color;
color=red;//color=0
color=green;//color=9
color=blue;//color=10

enum {MONDAY=3,TUESDAY=4};
int today = TUESDAY;//MONDAY,TUESDAY可以直接拿去运算,相当于宏定义

数组赋值

提示::

struct People{
char name[20];
};
struct  People p1;
错误的赋值方式:p1.name = "熊猫大虾";//数组名是一个常量不能直接赋值,可以采用以下方式赋值
p1.name[0]='x';p1.name[1]='y';//如果是英文字母,可以一个一个的存
strcpy(p1.name,"熊猫大虾");

结构体内存对齐

提示:规则是按最大数据类型并且最省内存的方式对齐

1:
struct People{
char c;//1
short s;//2
int i;//4
};
struct  People p1;
printf("%d\n",sizeof(p1));
对于以上的一个结构体变量,目测是占有7个字节,但是结果是8.原因:先按int对齐,charshort在一个int长度内,在此长度内,再按short对齐。

例2:
struct People{
char c;//1
int i;//4
double d;//8
};
struct  People p2;
printf("%d\n",sizeof(p2));
对于以上的一个结构体变量,目测是占有13个字节,但是结果是16.原因:按double对齐,charint在一个double长度内,在此长度内,再按int对齐。

动态数组

提示:在声明数组时,必须要用常量来规定数组的长度,例如:int arr[10];。然而实际当中,我们需要数组的长度是不确定的,动态分配数组长度是很有必要的,就可以配内存管理函数malloc来实现,直接上代码

//假设n是一个动态值
int n = 0scanf("%d", &n);
int* pint = malloc(sizeof(int) * n);//分配n个int
if(pint = NULL){
	return 0;
}
/*因为分配的是连续的内存空间,所以pint就可以当作数组来使用了*/
//提示,内存分配后,里面不一定是0,很可能是垃圾值
//使用方法复习:
1: *(pint + 0) = 0;  *(pint + 1) = 10; *(pint + 2) = 20;...
2: pint[0] = 0;  pint[1] = 10;  pint[2] = 20;...

使用calloc()

//假设n是一个动态值
int n = 0scanf("%d", &n);
int* pint = calloc(n , sizeof(int));//分配n个int
if(pint = NULL){
	return 0;
}
/*与malloc不同的是,calloc分配完地址,会把分配的内存清零*/

realloc()变大或缩小分配的内存

//假设n是一个动态值
int n = 0scanf("%d", &n);
int* pint = calloc(5 , sizeof(int));//分配5个int
if(pint = NULL){
	return 0;
}
int* pint2 = calloc(pint ,sizeof(int) * 10);//分配10个int
/*pint与pint2首地址相同*/

四个分区

提示:栈里的变量系统会自动回收,堆里的内存动态分配完要自己回收,静态区的生命周期比较长,贯穿程序的始终。代码段就是ssssssss......
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值