C语言基础知识点

数据类型:(32位机)
char short int(4字节,32位) long(4)
double(8字节) float(4)

构造类型:
数组 struct uinon enum

指针:

void:

位运算:
位与 位或 位取反 位异或 逻辑取反
& | ~ ^ !

左移 <<
右移 >>

读-改-写
特定位清零用 &
特定位置1用 |
特定位取反 ^

位运算与宏定义
#define SET_NTH_BIT(x, n) (x | ((1U)<<(n-1)));
#define CLEAR_NTH_BIT(x, n) (x & ~((1U)<<(n-1)));

指针:
* &
const int* p;//指向整形常量 的指针,它指向的值不能修改
int const *p;//指向整形常量 的指针,它指向的值不能修改
int* const p;//指向整形的常量指针 ,它不能再指向别的变量,但指向(变量)的值可以修改
const int* const p; //指向整形常量 的常量指针 。它既不能再指向别的常量,指向的值也不能修改

初始化的全局变量和静态的变量放在.data段  
未初始化化的全局变量和未初始化的静态变量放在.bss

int a[10]
a a[0] &a &a[0]
a 左值 sizeof(a) 4*10
a做右值等同于 &a[0]
&a 不能左值,右值 数组的首地址
&a[0]

数组名[下标])和指针 *指针+偏移量

int* p; int a[5]; p = a; 匹配
int* p; int a[5]; p = &a; 类型不匹配,&a是整个数组指针,是一个数组指针类型,不是int指针类型
&a、a、&a[0] a和&a[0]是元素指针,int 类型; &a 是数组指针,是int()[5]
指针变量+1,是加 1*sizeof(指针类型)

char str[] = ”hello”; sizeof(str) 6 sizeof(str[0]) 1 strlen(str) 5
char *p=str; sizeof(p) 4 sizeof(*p) 1 strlen(p) 5
strlen接收的参数必须是一个字符串(字符串的特征是以’\0’结尾)

输入型参数和输出型参数:
函数名是一个符号,表示整个函数代码段的首地址
参数多的时候打包成结构体,传结构体变量的指针

函数传参中使用const指针
(1)const一般用在函数参数列表中,用法是const int *p;(意义是指针变量p本身可变的,而p所指向的变量是不可变的)。
(2)const用来修饰指针做函数传参,作用就在于声明在函数内部不会改变这个指针所指向的内容,所以给该函数传一个不可改变的指针(char *p = “linux”;这种)不会触发错误;而一个未声明为const的指针的函数,你给他传一个不可更改的指针的时候就要小心了。

哪个参数做输入哪个做输出?函数传参如果传的是普通变量(不是指针)那肯定是输入型参数;如果传指针就有2种可能性了,为了区别,经常的做法是:如果这个参数是做输入的(通常做输入的在函数内部只需要读取这个参数而不会需要更改它)就在指针前面加const来修饰;如果函数形参是指针变量并且还没加const,那么就表示这个参数是用来做输出型参数的。

内存:
malloc,free bzero
位、字节、半字、字
位(1bit) 字节(8bit) 半字(16) 字(32)

指针高级:
int *p[5] 核心是P,p是一个数组,数组有5个元素,数组中的元素都是指针,指针指向是元素类型是int,是一个指针数组 int(*p)[5]核心是p,p是一个指针,指针指向一个数组,数组有5个元素,数组中的元素都是指针,指针指向的元素是int类型,是一个数组指针
int *(p[]5)与第一个相同
符号优先级[] . ->

typedef

函数指针的书写和分析方法:
void func(void); 对应的函数指针:void (p)(void); 类型是:void ()(void)

b[i] 等同于 *(p+i)
a[i][j]等同于 ((p+i)+j)

二维数组

C语言的字符串类型:
定义字符串的方法:char *p = “linux”,p指向字符串的起始地址
本质:指针指向头,固定尾部的地址相连的一段内存
char *p = “linux” p指针4个字节,”linux”代码段6个字节,’\0’结尾

sizeof、strlen(size_t strlen(const char *s);)

字符数组与字符串的本质差异(内存分配角度)
(1)字符数组char a[] = “linux”;来说,定义了一个数组a,数组a占6字节,右值”linux”本身只存在于编译器中,编译器将它用来初始化字符数组a后丢弃掉(也就是说内存中是没有”linux”这个字符串的);这句就相当于是:char a[] = {‘l’, ‘i’, ‘n’, ‘u’, ‘x’, ‘\0’};
(2)字符串char *p = “linux”;定义了一个字符指针p,p占4字节,分配在栈上;同时还定义了一个字符串”linux”,分配在代码段;然后把代码段中的字符串(一共占6字节)的首地址(也就是’l’的地址)赋值给p。 总结对比:字符数组和字符串有本质差别。字符数组本身是数组,数组自身自带内存空间,可以用来存东西(所以数组类似于容器);而字符串本身是指针,本身永远只占4字节,而且这4个字节还不能用来存有效数据,所以只能把有效数据存到别的地方,然后把地址存在p中。

结构体:typedef
struct 结构体名{
结构体所包含的变量或数组
};

struct stu{
char *name; //姓名
int num; //学号
};

定义结构体的同时定义结构体变量:
struct stu{
char *name; //姓名
int num; //学号
} stu1, stu2;

struct{
char *name; //姓名
int num; //学号
} stu1, stu2 = { “Tom”, 12};
结构体变量来访问元素用. 用结构体变量的指针来访问元素用->

共用体union:
不存在内存对齐的问题,是同一内存空间的多种解释

写一个函数来测试当前机器的大小端模式:
union myunion{
int a;
char b;
};
//union从低地址取
char is_little_endian(void){//小端回1,大端回0
union myunion u1;
u1.a = 1;
return u1.b;//地址0对应的字节为1小端, 高字节对应低地址小端
}

枚举:enum
设有变量a,b,c被说明为上述的weekday,可采用下述任一种方式:
enum weekday{ sun,mou,tue,wed,thu,fri,sat };
enum weekday a,b,c;
或者为:
enum weekday{ sun,mou,tue,wed,thu,fri,sat }a,b,c;
或者为:
enum { sun,mou,tue,wed,thu,fri,sat }a,b,c;

宏定义:

define MAX(a, b) (((a)>(b)) ? (a) : (b))

define SEC_PER_YEAR (365*24*60*60UL)

字符串处理函数:

关键字:
static register auto
extern:主要用来声明全局变量:在b.c 中定义:int g_b = 4; 在a.c中使用:extern int g_b;(外部链接属性)
volatile

链表:
struct node{
int data;
struct node* pNext;
}

struct node* create_node(int data)
{
struct node* p = (struct node*)(malloc(sizeof(p)));

if(NULL == p)
{
    printf("malloc error\n");
    return NULL;
}
bzero(p, sizeof(struct node));

p->data;
p->pNext = NULL;

return p;

}

void insert_tail(struct node* pH, struct node* new)
{
struct node* p = pH;

while(NULL != p -> pNext)
{
    p = p->pNext;
}
p->pNext = new;

}

void insert_head(struct node* pH, struct node* new)
{
new->pNext = pH->pNext;

pH->pNext = new;

}

void reverse_list(struct node* pH)
{

}

struct node* list_3(int* data)
{
struct node* p = (struct node*)malloc(sizeof(struct node));
struct node* pNew;

if(NULL == p)
{
    printf("malloc error\n");
    return NULL;
}

for(i=0; i<3; i++)
{
    pNew = create_node(data[i]);
    if(NULL == pNew)
    {
        return NULL;
    }
    p->pNext = pNew;
    p = p->pNext;
}
return p;

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值