
c语言深度剖析
xmzzy2012
这个作者很懒,什么都没留下…
展开
-
pragma pack与__attribute__区别
一、pragma pack(n):告诉编译器结构体或类内部的成员变量相对于第一个变量的地址的偏移量的对齐方式,缺省情况下,编译器按照自然边界对齐,当变量所需的自然对齐边界比n大 时,按照n对齐。二、__attribute__((aligned(m))):告诉编译器一个结构体或者类或者联合或者一个类型的变量(对象)分配地址空间时的地址对齐方式。也就是说,如 果将__attribute__((...转载 2019-08-04 20:21:36 · 821 阅读 · 0 评论 -
两头文件相互包含,且内容相互引用问题
//HEAD1.H#ifndef __HEAD_1_H__#define __HEAD_1_H__ //防止多次包含,重复定义#include "head2.h"#define VAR_MACRO 1 //define a macro, which used in head2.hbool func(ClassA* CA); //ClassA is...原创 2018-02-23 10:58:34 · 1730 阅读 · 0 评论 -
多个文件使用同一全局变量(未初始化) 以及局部变量重复定义
如果是多个文件中同一变量,是由C语言编译器中的linker解决的。首先,要编译的文件中的符号(函数名,全局变量名)分为weak和strong类型。weak symbol:未初始化的全局变量strong symbol:函数名,初始化的全局变量linker解决按3条规则解决此问题1,多个相同名称的strong symbol是不被允许的2,一个strong symbol和多个weak symbol相同,...转载 2018-01-06 09:29:05 · 1976 阅读 · 0 评论 -
内存对齐
1、字(2字节)、双字(4字节),四字(8字节)的起始地址必须为偶数地址、被4整除的地址、被8整除的地址,称为自然边界2. 结构体中还有结构体,内部的结构体按自身成员类型最大值为对齐参数( 自然边界 )3、最后占用的内存空间为结构体最长类型的整数倍以上3点可以节省存储空间并且优化性能 struct TestStudent{ char a; int b; };如下:a占...原创 2015-12-25 19:01:05 · 286 阅读 · 0 评论 -
C整型升级和寻常算术转换以及数据类型转换
一、在算术表达式中存在整型升级和寻常算术转化问题(unsigned)char,(unsigned)short --> ( unsigned )int -->float -->double -->long doublefloat、double、long double为浮点型数据。当没有浮点型数据参与计算时,统一转为(unsigned)int例如:char a=1,b=1,c;...原创 2018-02-27 17:20:18 · 427 阅读 · 0 评论 -
++符号的贪心方法与左值右值和未定义表达式
编译器将程序分解成符号的方法是,从左到右一个一个字符地读入,如果该字符可能组成一个符号,那么再读入下一个字符,判断已经读入的两个字符组成的字符串是否可能是一个符号的组成部分;如果可能,继续读入下一个字符,重复上述判断,直到读入的字符组成的字符串已不再可能组成一个有意义的符号。这个处理的策略被称为“贪心法” 要看懂下面式子,明白两点:1、左值右值区别。 左值原创 2015-01-30 21:08:07 · 457 阅读 · 0 评论 -
两异号数相除和余数
表达式: q=a/b,r=a%b;规则如下:1、a = q*b + r;2、a改变符号,则q也改变符号3、r与a同号例如:q = 3/(-2) = -1,r = 3%(-2) = 1。-1*(-2) + 1 =3 同时满足以上1,3条件改变3的符号,又有,q = (-3)/(-2) =1,r = (-3)%(-2) = -1 同时满足以上3条件原创 2018-02-07 17:10:34 · 1765 阅读 · 0 评论 -
浮点数的大小比较为什么不能用等号?
1、不是所有的数都可以用浮点数精确表示,如3.333 二进制表示1*2^1+1*2^0+0*2^(-1)+1*2^(-2)...。内存中存储的仅是真实值得近似值。有精度误差2、浮点数精度不同#include #include using namespace std;int main(){ float a = (float)0.1; float b = (flo转载 2018-01-03 01:45:31 · 1633 阅读 · 0 评论 -
转义字符
1、C中定义了一些字母前加"\"来表示常见的那些不能显示的ASCII字符,如\0,\t,\n等,就称为转义字符,因为后面的字符,都不是它本来的ASCII字符意思了2、常见的转移字符表转义字符意义ASCII码值(十进制)\a响铃(BEL)007\b原创 2017-12-27 23:41:54 · 599 阅读 · 0 评论 -
c语言变量存储的本质
1、给定的值若是带(-符号),需将负数转为补码形式。若给定的数无符号表示(即无+-号,即为补码) 负数补码方法:除符号位外其余位取反(反码),再加1(反码+1)。 (char) -1 二进制存储格式,变换如下:1000,0001->反码:1111,1110->补码:1111,1111 = 0xff 所以char a = -1;和char a = 0xff原创 2017-12-31 01:08:58 · 327 阅读 · 0 评论 -
内存管理
1、野指针,数组越界范围 1.1当一指针不再用是一定记得要让起指向NULL 1.2数组越界访问可能会导致非法访问的错误2、堆、栈、静态区 2.1 堆是编译器留给程序员开辟的区域,malloc和new两函数。其生命周期有free和delete决定 2.2 栈是系统运行时保存局部变量,生命周期有函数自身决定 2.3 静态区通常放置全局变量和static变量原创 2015-12-25 18:06:22 · 276 阅读 · 0 评论 -
浮点数的存储
1、先看一例题:#include void main(void){ int num=9; /* num是整型变量,设为9 */ float* pFloat=# /* pFloat表示num的内存地址,但是设为浮点数 */ printf("num的值为:%d\n",num); /* 显示num的整型值 */ printf("*pFloat的值为:%转载 2017-09-02 11:46:34 · 403 阅读 · 0 评论 -
位段以及位段内存对齐
位段(bit-field)是以位为单位来定义结构体(或联合体)中的成员变量所占的空间。含有位段的结构体(联合体)称为位段结构。采用位段结构既能够节省空间,又方便于操作。位段结构中位段的定义格式为: 类型 <成员名>:<二进制位数>struct bytedata{ unsigned a:2; /*位段a,占2位*/ unsigned:6; /...原创 2018-02-23 16:15:22 · 892 阅读 · 1 评论 -
标号语句 与 变量定义
标号语句有:goto、case ,用 vc 6.0 goto 和case里头定义变量都提示错误,vc 在函数执行语句开始后就不能再定义或声明变量了。(dev c++未测试)以下是官方解释:见 http://en.cppreference.com/w/c/languageExplanationThe goto statement causes an unconditional jump (tran...原创 2018-02-22 16:58:44 · 1109 阅读 · 0 评论 -
变量名与数组名
1、变量名 --代表对应的内存地址,但在代码中表示的是内存中的值int a = 10; //开辟一内存空间名字为a,里面存放10a++; //a 存放 10&a 取的是a内存首地址2、数组名 --具有数组属性 + 隐式转换后的指针常量的性质数组属性:类型:int a[10],a的类型为int [10]sizeof(a) = 10*sizeof(int) = 40;&...原创 2018-03-16 14:42:29 · 3789 阅读 · 0 评论 -
字符串在内存中的拷贝以及内存重叠
在strcpy函数中需要注意导入的形参dst,src不能有内存重叠。(尤其注意dst不能处在src字符串的内存中间,否则拷贝的时候会替换到src原有的结束字符,最终导致src字符串无结束字符,一直拷贝下去导致程序崩溃)char *my_strcpy(char *dst,char *src){ char *_src = NULL; char *_dst = NULL; in...原创 2018-05-31 09:25:30 · 666 阅读 · 0 评论 -
递归写法转成迭代
一个常见的递归算法例子://斐波那契long Fib(int n){ if (n == 0) return 0; if (n == 1) return 1; if (n > 1) return Fib(n-1) + Fib(n-2);}1、例如求Fib(10) 中间值Fib(3)会被求值21次。但是其实只需求一次即可,剩余的20次求职 属于资源的浪费。2、...原创 2018-05-30 09:08:44 · 1972 阅读 · 0 评论 -
linux下的stdin,stdout和stderr理解
在linux中经常会看到stdin,stdout和stderr,这3个可以称为终端(Terminal)的标准输入(standard input),标准输出( standard out)和标准错误输出(standard error)。通过man stdin查看手册,可以看到它们都是在stdio.h中定义的。 当linux开始执行程序的时候,程序默认会打开这3个文件流,这样就可以对终端进行输入输出操作...转载 2018-06-05 17:49:35 · 30245 阅读 · 1 评论 -
可变参数列表 应用简介
可变参数列表即函数参数可以是不固定的,例如常规函数 type func(type A,type B,type C);定义了三个参数,因此调用的时候也必须导入三个参数。可变参数列表type func(type A , ......);type A为固定参数,......省略号为可变参数列表,可长可端。常见的printf函数声明为int printf(const char *fmt, ...) 介绍可...原创 2018-05-28 17:49:48 · 249 阅读 · 0 评论 -
求两变量在规定值范围循环增长的距离值
假设变量 ticks_now、tick_old<=0x00ffffff,且在0-0x00ffffff循环,求tick_now、tick_old过了多少间隔static uint32_t ticks_diff_get(uint32_t ticks_now, uint32_t ticks_old){ return ((ticks_now - ticks_old) & 0x00ff...原创 2018-05-08 11:12:17 · 212 阅读 · 0 评论 -
指针数组与二级指针
二级指针:指向指针的指针指针数组:元素是指针的数组int lookup_keyword(char *desire_word,char **keytable,int size) //char *keytable[],因为keytable[]可写成指针形式 故= char **keytable{ char **kwp = NULL; for(kwp=keytable;kwp<k...原创 2018-04-04 17:10:37 · 524 阅读 · 0 评论 -
字符串常量与字符数组
字符数组的初始化:char a[6] = "hello1";//char b[6] = {'h','e','l','l','o','2',0};char c[] = "hello3";//c字符:h,e,l,l,o,3,\0char d[] ={'h','e','l','l','o','4','\0'};//d字符:h,e,l,l,o,4,\0 strcpy(a,b); //以\0为结束字...原创 2018-04-08 17:24:29 · 214 阅读 · 0 评论 -
++ --在C与C++中左值区别
转自:http://blog.youkuaiyun.com/julysee/article/details/43760205今天网上看到一个华为的面试题目:写出判断ABCD四个表达式的是否正确, 若正确, 写出经过表达式中 a的值int a = 4;(A)a += (a++); (B) a += (++a) ;(C) (a++) += a;(D) (++a) += (a++);答案是C是错误的,而A B D是...转载 2018-02-24 18:12:02 · 232 阅读 · 0 评论 -
指针常量与常量指针( const修饰 )
①const int p; ②const int* p; ③int const* p; ④int * const p;⑤const int * const p;⑥int const * const p;第一种是常量整数,没什么好说的。后面五种是指针,有一个简便的办法记忆。从右往左读,遇到p就替换成“p is a ”遇到 * 就替换成“point to”。比如说②,读作:p is a point t...原创 2018-02-24 15:53:49 · 281 阅读 · 0 评论 -
c语言关键字
C 语言标准定义的32 个关键字 1、auto 声明自动变量,缺省时编译器一般默认为auto2、int 声明整型变量3、double 声明双精度变量:双精度浮点型4、long 声明长整型变量5、char 声明字符型变量6、float 声明浮点型变量:单精度浮点型 6.1 float的有效位通常有6位,指的是小数点后面有6位数,四舍五入。 6.2 通常不将float与一个具体值进行...原创 2015-01-28 20:22:13 · 582 阅读 · 0 评论 -
无类型名的结构体
1、无类型名的结构体变量在声明结构体时就得定义。2、不同时刻声明的结构体变量,即使成员列表一致,在编译器看来也是不一致的数据类型例如:struct{ int x;}a;struct{ int x;}b; b = a;//报 incompatible type error且无类型名结构体使用限制:1、他不能作为参数传递给一个函数,因为编译器无法对他进行类型检查;2、也不能使被调用的...原创 2018-02-24 14:06:29 · 2114 阅读 · 1 评论 -
C语言中内存分配
在任何程序设计环境及语言中,内存管理都十分重要。在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的。因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题。第1节主要介绍内存管理基本概念,重点介绍C程序中内存的分配,以及C语言编译后的可执行程序的存储结构和运行结构,同时还介绍了堆空间和栈空间的用途及区别。第2节主要介绍C语言中内存分配及释放函数、函数的功能,以及如何调用这些转载 2016-05-23 15:38:00 · 365 阅读 · 0 评论 -
用define 宏定义注释符号?
#define BSC //#define BMC /*#define EMC */D),BSC my single-line commentE),BMC my multi-line comment EMCD)和E)都错误,为什么呢?因为注释先于预处理指令被处理,当这两行被展开成//…或/*…*/时,注释已处理完毕,此时再出现//…或/*…*/自然错误.因此,试图用宏开始或原创 2015-01-30 21:58:01 · 2020 阅读 · 0 评论 -
浮点型的打印和有效值位数问题
/*1、float double默认都输出到小数点后6位(但可格式化输出)2、float 有效位6,超过6位的不保证显示正确(有可能正确有可能错误),double有效位15,超过15位不保证显示正确3、输出值比实际短,打印值最后一不确定4、输出指定%f,%lf没什么影响*/#include #include void main(){ f原创 2018-01-03 01:13:11 · 3096 阅读 · 0 评论 -
指针加减与地址强制转化
1、指针加减表示类型元素移动的个数struct Test{ int Num; char *pName; short sDate;}*p;以上定义了一个指针p,指向struct Test类型假设p = 0x1000,有以下结果p + 1 = p值+sizeof(struct Test);(unsigned long)p + 1 =0x0100原创 2015-12-28 16:51:38 · 903 阅读 · 0 评论 -
定义为指针,外部声明为数组和定义为数组,外部声明为指针,会发生什么?
转:http://blog.youkuaiyun.com/yucan1001/article/details/7450388思科的一道面试题如下:不要用编译器 用1分钟事件思考下源文件A:int a[10];int *b=a;源文件B:extern int *a;extern int b[];int x,y;...x=a[3];y=b[3];原创 2015-12-07 11:53:54 · 1995 阅读 · 1 评论 -
#ifdef 与#if defined
#ifdef 与#if defined都可以实现是否有定义的判断,但在使用上有点区别1、#ifdef XXX。。。。 #else。。。。 #endif类似if。。else。。的判断。2、#if defind XXX。。。。。 #elif defined XXX。。。。。 #elif defined原创 2015-06-17 11:27:18 · 562 阅读 · 0 评论 -
c语言命名
一般来说习惯上用n,m,i,j,k 等表示int 类型的变量;c,ch 等表示字符类型变量;a 等表示数组;p 等表示指针。当然这仅仅是一般习惯,除了i,j,k 等可以用来表示循环变量外,别的字符变量名尽量不要使例:char cVariable;boolean bVariable;int iVariable;float fVariable;void原创 2015-01-28 23:03:09 · 373 阅读 · 0 评论 -
int *p=NULL与*p=NULL
int *p=NULL,式子说明1、定义了一个指针变量p,2、其所指向的内存里存放的是int型数据,3、初始化p指向NULL(空内存)。以上只是初始化了一个指针*p=NULL,式子说明1、将p指向的内存所存储的值设为NULL。以上只是对p指向的内存所存储的变量赋值例如:int i=10; //定义一整型变量int *p=&i;//定义一个整型原创 2015-02-06 15:37:10 · 1878 阅读 · 0 评论 -
逗号表达式
int x;int i = 3;x = (++i, i++, i+10);逗号表达式最后值为最后一个式子。所以x=i+10;但是如果改成:x=++i,i++,i+10呢?因为赋值比逗号表达式等级高,所以x=++i原创 2015-01-30 20:40:40 · 456 阅读 · 0 评论 -
优先级问题
归纳如下:初值运算符 :[ ]、()、. 、->单目运算符 :++、--,!,~,&,*,sizeof,强转算数运算符 :+、-,*,/移位运算符 :<<、>>关系运算符 :>=、<=,!=,>、<,==位运算符 :|,&,^逻辑运算符 :&&,||条件运算符 ...原创 2015-01-30 21:45:33 · 369 阅读 · 0 评论 -
c符号
反斜杆\是断行,其中断行之后以及下一行都不能有空格出现,否则编译器会将反斜杆后的内容命令语句。//这是一条合法的\单行注释/\ // /\这个符号是 / \的组合/这是一条合法的单行注释cha\r* s="这是一个合法的\\n 字符串";原创 2015-01-30 20:10:19 · 461 阅读 · 0 评论 -
数组和指针
1、如何将数值存储到指定的内存地址上? int *p = (int *)0x12ff7c;//将地址0x12ff7c强转成int *,赋给指针p *p = 0x10;//将10存储到地址0x12ff7c上2、int *p = &p;//将p指向了自身 地址p处 保存 &p。图1 *p =NULL;//对p指向的内存地址空间赋值NULL。图2,赋值完后变成p =NU原创 2015-12-26 17:35:47 · 404 阅读 · 0 评论 -
函数指针
1、函数指针的定义 int (*p)[10 ]表示定义一个数组指针,指针p 指向数组类型int [10] 同理我们可以定义函数指针,指针指向某一函数类型 int *(*fun)(char *p,int *n) 表示定义了一个函数指针,指向函数类型int *(char *p,int *n) //(*fun)表示定义了一个指针,指针类型为int * (char *p,int *n原创 2015-12-28 18:40:48 · 375 阅读 · 0 评论 -
符号
1、/斜杠,\反斜杠 \反斜杠主要起连接字符和转义字符的作用。作反斜杠用时,要求\之后不能有空格且下一行要顶格。2、/* */起注释作用 2.1 /*总是与最近的*/配对,因此/* */不能嵌套。比如/* xxx /*xxx */ xxx */ 错误,最后一个*/多余 2.2 只要/和*之间没有空格,系统认为注释开始 /*xxx都是注释 2.3 编译原创 2015-12-25 17:37:01 · 418 阅读 · 0 评论