C语言条件预处理命令

 /*
格式:
#ifdef 标识符
程序1
#else
程序2
#endif
标识符已经定义时,程序段1才参加编译
应用:如调试版本,发行版本,便于调试 */
#include <stdio.h>
int main()
{
#ifdef ABC // #define ABC 1
printf("程序一");
#endif
printf("hello world\n");
return ;
}

类型修饰符register (不常用)

register int a;

内存(存储器),  寄存器

限制变量定义在寄存器上的修饰符,定义一些快速访问的变量,编译器会尽量的安排CPU的寄存器去存放在这个a。如果寄存器不足时,a还是放在存储器中。

类型修饰符volatite

告知编译器编译方法的关键字,不优化编译

修饰变量的值的修改,不仅仅可以通过软件,也可以通过其他方式(硬件外部的用户)

类型修饰符const

常量的定义,只读的变量,参考收藏的文章

指针+const

//内存属性
// 1、内存操作的大小
// 2、内存的变化性,可写可读 const char *p; //常用这个 字符串 “hello world ” "aaa"
char const *p; //p指向的内容可读不可写 char *const p; // 硬件资源 LCD 固定地址内容可变
char *p const; const char *const p; //ROM 什么都不变

总结:const在char的左边那就是不能修改地址中的值,在右边就是不能指向其他地址,左右都有那就是既不能修改地址的值也不能指向其他地址。

动态内存管理

malloc:

函数原型:void  *malloc(size_t size);
功能:malloc函数向系统申请分配size个字节的内存空间,并返回一个指向这块空间的指针
返回值:成功 void指针(void *)
失败 NULL
函数原型: void free(void *ptr)
功能:释放ptr参数指向的内存空间。该空间必须是由malloc、calloc或realloc函数申请的
返回值:无

内存泄漏:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
while()
{
malloc();
}
return ;
}
结果:卡顿

导致内存泄漏主要有两种情况:

  • 隐式内存泄漏(即用完内存块没有及时使用free函数释放)
  • 丢失内存块地址

以mem开头的函数包含在string.h头文件中:如memset,memcpy

void *memset(void *s,int c,size_t n)

总的作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c
void *memset(void *s,int c,size_t n)

总的作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 10
int main(void)
{
int *ptr=NULL;
int i;
ptr=(int *)malloc(N*sizeof(int));
if(ptr==NULL)
{
exit();
}
memset(ptr,,N*sizeof(int));
for(i=;i<N;i++)
{
printf("%d",ptr[i]);
}
putchar('\n');
free(ptr);
return ;
}

另外还有calloc:申请并出示化一系列内存空间   realloc:重新分配空间

结构体:可以将多种数据类型组合起来的结构

声明方式:

 struct 结构体名称{
类型 变量名;
}结构变量1, 结构变量2;

结构体的大小:

struct st01{

      char c;
};
sizeof(struct st01);//c++ 直接st01就行
//输出结果为1
struct st1{
char c1;
char c2;
int a;
};
struct st2{
char c1;
int al
char c2;
};
sizeof(struct st1);//
sizeof(struct st2);//
struct st3{
char arr[];
int b;
short c;
};
struct st4{
char arr[];
short c;
int b;
};
sizeof(struct st3);//
sizeof(struct st4);//
struct st5{
char c1;
char c2;
double a;
};
struct st6{
char c1;
double a;
char c2;
};
sizeof(struct st5);//
sizeof(struct st6);//

结论:

  1. 结构体定义的时候,变量成员的顺序会影响结构体的大小
  2. 对齐:成员变量以什么样的方式排列,紧密排列还是松散,中间是不是有间隔。
  3. 大小影响因素:成员变量的大小;对齐方式
  4. 编译器对于对齐方式,可以选择的,VS默认是8字节对齐的。字节对齐:1,4,8,16;不同类型变量的对齐
  5. 如果编译器的对齐方式大于4字节:int:4字节,必须以字节的倍数分配地址;如果结构体里面有int,那么结构体的大小就是4的整数倍。
  6. 如果short,double,同样的道理;
  7. 如果有相同类型的变量呢,一定要放在一起,会减少结构体的空间。
  8. 结构体定义,变量类型从小到大的顺序比较合适(建议)
  9. 程序中设置内存对齐#pragma pack(n)   如:#pragma pack(1) //1个字节对齐,会紧密排列

关键字union

union 关键字的用法与struct 的用法非常类似。
union 维护足够的空间来置放多个数据成员中的“一种”,而不是为每一个数据成员配置空间,在union 中所有的数据成员共用一个空间,同一时间只能储存其中一个数据成员,所有的数据成员具有相同的起始地址。

这里需要考虑存储模式:大端模式和小端模式。

  1. 大端模式(Big_endian):字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。
  2. 小端模式(Little_endian):字数据的高字节存储在高地址中,而字数据的低字节则存放在低地址中。

枚举类型enum

以下代码定义了这种新的数据类型 - 枚举型

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};

(1) 枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号,隔开。

(2) DAY是一个标识符,可以看成这个集合的名字,是一个可选项,即是可有可无的项。

(3) 第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。

(4) 可以人为设定枚举成员的值,从而自定义某个范围内的整数。

(5) 枚举型是预处理指令#define的替代。

(6) 类型定义以分号;结束。

指针

指针是一个特殊的变量,它是存放地址的。

四要素:指针的类型、指针所指向的类型、指针的值或者叫指针所指向的内存区、指针本身所占据的内存区。
//*:取值操做符
//&:取址操做符 &与*优先级相同
int i=;
int *pointer;
pointer=&i;
printf("%d\n",*pointer);

指针变量和指针:

知道了一个变量的地址,就可以通过这个地址来访问这个变量,因此,又把变量的地址称为该变量的“指针”

C语言可以定义一类特殊的变量,这些变量专门用来存放变量的地址,称为指针变量。

注意:指针变量的值(即指针变量中存放的值)是地址(即指针)。

  float *pointer_1;//指针变量名是pointer_1,而不是*pointer_1

几种常用格式:

pointer=&a;

&*pointer //与&a相同,即变量a的地址】 *&a //先&a,得到a的地址,再进行*运算。即&a所指向的变量,也就是变量a (*pointer)++ //相当于a++
 #include <stdio.h>
void main()
{
int *p1,*p2,*p,a,b;
scanf("%d %d",&a,&b);
p1=&a;
p2=&b;
if(a<b)
{
p=p1;
p1=p2;
p2=p;
}
printf("a=%d,b=%d\n",a,b);
printf("max=%d,min=%d\n",*p1,*p2); }

多级指针:存放地址的地址空间,更多的是描述线性关系。

char  **p;(圆圈p)   p[m]=NULL结束

指针数组

char  *a[]

sizeof(a)=*;  //一个指针4个地址

指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身的大小决定,每一个元素都是一个指针,在32 位系统下任何类型的指针永远是占4 个字节。它是“储存指针的数组”的简称。
数组指针:首先它是一个指针,它指向一个数组。在32 位系统下任何类型的指针永远是占4 个字节,至于它指向的数组占多少字节,不知道,具体要看数组大小。它是“指向数组的指针”的简称。、

具体可以参考收藏的文章。

数组越界

所谓的数组越界,简单地讲就是指数组下标变量的取值超过了初始定义时的大小,导致对数组元素的访问出现在数组的范围之外,这类错误也是 C 语言程序中最常见的错误之一。

C 语言并不检验数组边界,数组的两端都有可能越界,从而使其他变量的数据甚至程序代码被破坏。

   void test1()
{
char string[];
char* str1="";
strcpy(string, str1);
}

string数组越界,因为字符串长度为10,还有一个结束符‘\0’。所以总共有11个字符长度。string数组大小为10,这里越界了。

使用strcpy函数的时候一定要注意前面目的数组的大小一定要大于后面字符串的大小,否则便是访问越界。

  void test2()
{
char string[], str1[];
for(i=; i<;i++)
{
str1[i] =’a’;
}
strcpy(string, str1);
}

这里有一个一眼就能看出的问题,那就是变量i没有定义,这在代码编译阶段编译器可以帮你发现,很容易搞定。然而很多问题是自己造成的漏洞,编译器是帮不上什么忙的。这里最大的问题还是str1没有结束符,因为strcpy的第二个参数应该是一个字符串常量。该函数就是利用判断第二个参数的结束符来得到是否拷贝完毕。所以在for循环后面应加上str1p[9] = ‘\0’;

字符数组和字符串的最明显的区别就是字符串会被默认的加上结束符‘\0’。

  void test3(char* str1)
{
char string[];
if(strlen(str1)<=)
{
strcpy(string, str1);
}
}
//strlen函数得到字符串除结束符外的长度。如果这里是<=10话,就很明显越界了。

C语言常用知识点的更多相关文章

  1. c语言 常用知识点

    强制类型转换 (int)(x+y) 输入 scanf("a=%f,b=%f",&a,&b);  a=1,b=1 char a; a=getchar(); 输入一个字 ...

  2. 学Android开发,入门语言java知识点

    学Android开发,入门语言java知识点 Android是一种以Linux为基础的开源码操作系统,主要使用于便携设备,而linux是用c语言和少量汇编语言写成的,如果你想研究Android,就去学 ...

  3. JAVA常用知识点及面试题总结

    1. String.StringBuffer.StringBuilder三者区别? (1)三者在执行速率上的比较: String<StringBuffer<StringBuilder 原因 ...

  4. JavaScript语言基础知识点图示(转)

    一位牛人归纳的JavaScript 语言基础知识点图示. 1.JavaScript 数据类型 2.JavaScript 变量 3.Javascript 运算符 4.JavaScript 数组 5.Ja ...

  5. DB2_SQL_常用知识点&实践

    DB2_SQL_常用知识点&实践 一.删除表中的数据(delete或truncate) 1 truncate table T_USER immediate; 说明:Truncate是一个能够快 ...

  6. JavaScript 语言基础知识点总结

    网上找到的一份JavaScript 语言基础知识点总结,还不错,挺全面的. (来自:http://t.cn/zjbXMmi @刘巍峰 分享 )  

  7. C语言常用的库文件(头文件、函数库)

    C语言常用的库文件(头文件.函数库) C系统提供了丰富的系统文件,称为库文件.C的库文件分为两类,一类是扩展名为".h"的文件,称为头文件,在前面的包含命令中我们已多次使用过.在& ...

  8. JavaScript语言基础知识点图示

    原文:JavaScript语言基础知识点图示 一位牛人归纳的JavaScript 语言基础知识点图示. 1.JavaScript 数据类型 2.JavaScript 变量 3.Javascript 运 ...

  9. HTML常用知识点代码演示

    1 HTML部分常用知识点 <!-- 版本声明 --> <!DOCTYPE html> <!-- 唯一根元素 --> <html> <!-- 对网 ...

随机推荐

  1. web 应用响应乱码问题

    非西欧语系乱码原因 在没有设置任何内容类型或编码之前,HttpServletResponse使用的字符编码默认是ISO-8859-1.也就是说,如果直接输出中文,在浏览器上就会看到乱码. 有两种方式可 ...

  2. java 内存分析之this

    package Demo; /** * this 的值是当前对象的引用 * @author Aaron * */ public class Boy { private int age; public ...

  3. 使用 NGINX 进行微程序缓存的好处

    [编者按]本文作者为 Owen Garrett,主要介绍使用 nginx 进行微程序缓存的好处,辅之以生动的实例.文章系国内 ITOM 管理平台 OneAPM 编译呈现. NGINX 和 NGINX ...

  4. git工具的使用

    Git工具的出现降低了软件版本维护的成本,极大的提高了工作效率,在这里列出了一些使用方法,方便以后查看. 1.Git的初始化->创建一个Git仓库:git init 2.创建信息:git con ...

  5. c# 设计模式 之:装饰模式

    一.引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).A ...

  6. java基础——队列

    目录 前言 基础 实现: 两个队列模拟一个堆栈 前言 java已经提供了堆和栈的相对应的类,这里只是模拟一下队列. 队列是一种先进先出的线性表. 基础 java5中新增加了java.util.Queu ...

  7. 模仿SDWebImage实现异步加载图片

    模仿SDWebImage实现异步加载图片 SDWebImage想必大家都不陌生吧,要实现它的图片异步加载功能这个还是很简单的. 注意:此处我只实现了异步加载图片,并没有将文件缓存到本地的打算哦:) 源 ...

  8. 如何生成.p12文件

    如何生成.p12文件 1. 打开钥匙串 2. 钥匙串选登录,种类选证书 3. 选择开发者,然后导出证书 4. 存储证书 5. 选择存储的时候会提示输入证书的密码,当然,也可以不用输入密码 6. 点击上 ...

  9. php 实现hash表

    hash表又称散列表,通过把关键字key经过hash函数映射到hash表中某个位置获取记录. 存放记录的数组又称为hash表,映射函数称为hash函数 下面是php中实现hash表的方法 <?p ...

  10. 【[BJOI2017]魔法咒语】

    矩阵乘法+\(AC\)自动机 是道很不错的题了 首先是前六十分,就是一个\(AC\)自动机上的套路\(dp\),设\(dp[i][j]\)表示匹配出的长度为\(i\)在自动机上位置为\(j\)的方案数 ...